discovery_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //go:build linux
  2. package modem
  3. import (
  4. "context"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. "testing"
  10. )
  11. func TestSysFSDiscoverySelectsInterface04AndNeverInterface02(t *testing.T) {
  12. root := t.TempDir()
  13. sysRoot := filepath.Join(root, "sys")
  14. devRoot := filepath.Join(root, "dev")
  15. usbRoot := filepath.Join(sysRoot, "bus", "usb", "devices")
  16. mustWrite(t, filepath.Join(usbRoot, "1-6", "idVendor"), "2c7c\n")
  17. mustWrite(t, filepath.Join(usbRoot, "1-6", "idProduct"), "0125\n")
  18. mustWrite(t, filepath.Join(usbRoot, "1-6", "manufacturer"), "Android\n")
  19. mustWrite(t, filepath.Join(usbRoot, "1-6", "product"), "Android\n")
  20. mustWrite(t, filepath.Join(usbRoot, "1-6", "serial"), "Android\n")
  21. for _, item := range []struct {
  22. interfaceName string
  23. interfaceNumber string
  24. tty string
  25. }{
  26. {"1-6:1.2", "02", "ttyUSB0"},
  27. {"1-6:1.3", "03", "ttyUSB1"},
  28. {"1-6:1.4", "04", "ttyUSB2"},
  29. {"1-6:1.5", "05", "ttyUSB3"},
  30. } {
  31. mustWrite(
  32. t,
  33. filepath.Join(usbRoot, item.interfaceName, "bInterfaceNumber"),
  34. item.interfaceNumber+"\n",
  35. )
  36. mustMkdir(t, filepath.Join(
  37. usbRoot,
  38. item.interfaceName,
  39. item.tty,
  40. "tty",
  41. item.tty,
  42. ))
  43. }
  44. mustMkdir(t, filepath.Join(usbRoot, "1-6:1.0", "net", "enx001122334455"))
  45. mustMkdir(t, filepath.Join(usbRoot, "1-6:1.4", "usbmisc", "cdc-wdm0"))
  46. discoverer := NewSysFSDiscoverer(sysRoot, devRoot)
  47. candidates, err := discoverer.Discover(context.Background())
  48. if err != nil {
  49. t.Fatalf("Discover: %v", err)
  50. }
  51. if len(candidates) != 1 {
  52. t.Fatalf("got %d candidates, want 1", len(candidates))
  53. }
  54. candidate := candidates[0]
  55. if candidate.ID != "quectel-0125-1-6" {
  56. t.Fatalf("ID = %q", candidate.ID)
  57. }
  58. if candidate.ATPort.Name != "ttyUSB2" {
  59. t.Fatalf("AT port = %#v, want ttyUSB2", candidate.ATPort)
  60. }
  61. if candidate.ATPort.InterfaceNumber != 0x04 {
  62. t.Fatalf("AT interface = %d, want 4", candidate.ATPort.InterfaceNumber)
  63. }
  64. if candidate.Ports[0].Role != PortRoleDiagnostic {
  65. t.Fatalf("interface 02 role = %q", candidate.Ports[0].Role)
  66. }
  67. if candidate.QMIControl != filepath.Join(devRoot, "cdc-wdm0") {
  68. t.Fatalf("QMI control = %q", candidate.QMIControl)
  69. }
  70. if candidate.NetworkInterface != "enx001122334455" {
  71. t.Fatalf("network interface = %q", candidate.NetworkInterface)
  72. }
  73. }
  74. func TestSysFSDiscoverySelectsTTYUSB2InQMIInterface00Layout(t *testing.T) {
  75. root := t.TempDir()
  76. sysRoot := filepath.Join(root, "sys")
  77. devRoot := filepath.Join(root, "dev")
  78. usbRoot := filepath.Join(sysRoot, "bus", "usb", "devices")
  79. mustWrite(t, filepath.Join(usbRoot, "1-6", "idVendor"), "2c7c\n")
  80. mustWrite(t, filepath.Join(usbRoot, "1-6", "idProduct"), "0125\n")
  81. for number, tty := range []string{"ttyUSB0", "ttyUSB1", "ttyUSB2", "ttyUSB3"} {
  82. interfaceName := "1-6:1." + strconv.Itoa(number)
  83. mustWrite(
  84. t,
  85. filepath.Join(usbRoot, interfaceName, "bInterfaceNumber"),
  86. fmt.Sprintf("%02x\n", number),
  87. )
  88. mustMkdir(t, filepath.Join(usbRoot, interfaceName, tty, "tty", tty))
  89. }
  90. mustWrite(
  91. t,
  92. filepath.Join(usbRoot, "1-6:1.4", "bInterfaceNumber"),
  93. "04\n",
  94. )
  95. mustMkdir(t, filepath.Join(usbRoot, "1-6:1.4", "usbmisc", "cdc-wdm0"))
  96. mustMkdir(t, filepath.Join(usbRoot, "1-6:1.4", "net", "wwp0s20f0u6i4"))
  97. candidates, err := NewSysFSDiscoverer(sysRoot, devRoot).Discover(context.Background())
  98. if err != nil {
  99. t.Fatalf("Discover: %v", err)
  100. }
  101. if len(candidates) != 1 {
  102. t.Fatalf("got %d candidates, want 1", len(candidates))
  103. }
  104. candidate := candidates[0]
  105. if candidate.ATPort.Name != "ttyUSB2" ||
  106. candidate.ATPort.InterfaceNumber != 0x02 ||
  107. candidate.ATPort.Role != PortRoleAT {
  108. t.Fatalf("AT port = %#v, want ttyUSB2 on interface 02", candidate.ATPort)
  109. }
  110. if candidate.QMIControl != filepath.Join(devRoot, "cdc-wdm0") {
  111. t.Fatalf("QMI control = %q", candidate.QMIControl)
  112. }
  113. if candidate.NetworkInterface != "wwp0s20f0u6i4" {
  114. t.Fatalf("network interface = %q", candidate.NetworkInterface)
  115. }
  116. }
  117. func TestSysFSDiscoveryIgnoresNonQuectelUSB(t *testing.T) {
  118. root := t.TempDir()
  119. usbRoot := filepath.Join(root, "sys", "bus", "usb", "devices")
  120. mustWrite(t, filepath.Join(usbRoot, "2-1", "idVendor"), "0403\n")
  121. mustWrite(t, filepath.Join(usbRoot, "2-1:1.0", "bInterfaceNumber"), "00\n")
  122. mustMkdir(t, filepath.Join(usbRoot, "2-1:1.0", "ttyUSB9"))
  123. candidates, err := NewSysFSDiscoverer(
  124. filepath.Join(root, "sys"),
  125. filepath.Join(root, "dev"),
  126. ).Discover(context.Background())
  127. if err != nil {
  128. t.Fatalf("Discover: %v", err)
  129. }
  130. if len(candidates) != 0 {
  131. t.Fatalf("got %#v, want no candidates", candidates)
  132. }
  133. }
  134. func mustWrite(t *testing.T, path, value string) {
  135. t.Helper()
  136. mustMkdir(t, filepath.Dir(path))
  137. if err := os.WriteFile(path, []byte(value), 0o600); err != nil {
  138. t.Fatal(err)
  139. }
  140. }
  141. func mustMkdir(t *testing.T, path string) {
  142. t.Helper()
  143. if err := os.MkdirAll(path, 0o700); err != nil {
  144. t.Fatal(err)
  145. }
  146. }