hid_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package hid
  2. import (
  3. "os"
  4. "testing"
  5. "time"
  6. )
  7. func TestReadTimesOutWithoutResponse(t *testing.T) {
  8. reader, writer, err := os.Pipe()
  9. if err != nil {
  10. t.Fatalf("os.Pipe() error = %v", err)
  11. }
  12. defer reader.Close()
  13. defer writer.Close()
  14. oldTimeout := hidReadTimeout
  15. hidReadTimeout = 10 * time.Millisecond
  16. defer func() { hidReadTimeout = oldTimeout }()
  17. device := Device{fd: int(reader.Fd())}
  18. if _, err := device.Read(make([]byte, 1)); err == nil {
  19. t.Fatal("Read() error = nil, want timeout")
  20. }
  21. }
  22. func TestParseHex(t *testing.T) {
  23. cases := []struct {
  24. name string
  25. input string
  26. want uint16
  27. err bool
  28. }{
  29. {"0x36B0", "36b0", 0x36b0, false},
  30. {"0x6666", "6666", 0x6666, false},
  31. {"0x0001", "0001", 0x0001, false},
  32. {"0xFFFF", "ffff", 0xffff, false},
  33. {"0x0000", "0000", 0x0000, false},
  34. {"uppercase", "ABCD", 0xabcd, false},
  35. {"mixed case", "AbCd", 0xabcd, false},
  36. {"6 chars", "0036b0", 0x36b0, false},
  37. {"invalid hex", "12gh", 0, true},
  38. }
  39. for _, tc := range cases {
  40. t.Run(tc.name, func(t *testing.T) {
  41. got, err := parseHex(tc.input)
  42. if tc.err {
  43. if err == nil {
  44. t.Errorf("parseHex(%q) expected error, got nil", tc.input)
  45. }
  46. return
  47. }
  48. if err != nil {
  49. t.Errorf("parseHex(%q) unexpected error: %v", tc.input, err)
  50. return
  51. }
  52. if got != tc.want {
  53. t.Errorf("parseHex(%q) = %d, want %d", tc.input, got, tc.want)
  54. }
  55. })
  56. }
  57. }
  58. func TestSplitLines(t *testing.T) {
  59. cases := []struct {
  60. name string
  61. input string
  62. want int
  63. }{
  64. {"single line", "hello", 1},
  65. {"two lines", "hello\nworld", 2},
  66. {"trailing newline", "hello\n", 1},
  67. {"empty", "", 0},
  68. {"single newline", "\n", 1},
  69. {"double newline", "\n\n", 2},
  70. {"with content and newlines", "foo\nbar\n", 2},
  71. }
  72. for _, tc := range cases {
  73. t.Run(tc.name, func(t *testing.T) {
  74. got := splitLines(tc.input)
  75. if len(got) != tc.want {
  76. t.Errorf("splitLines(%q) = %d lines, want %d lines", tc.input, len(got), tc.want)
  77. }
  78. })
  79. }
  80. }
  81. func TestIsRawHIDDescriptor(t *testing.T) {
  82. rawHID := []byte{
  83. 0x06, 0x60, 0xff, 0x09, 0x61, 0xa1, 0x01,
  84. 0x09, 0x62, 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x20, 0x75, 0x08, 0x81, 0x02,
  85. 0x09, 0x63, 0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x20, 0x75, 0x08, 0x91, 0x02,
  86. 0xc0,
  87. }
  88. keyboard := []byte{
  89. 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01,
  90. 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01,
  91. 0x95, 0x08, 0x75, 0x01, 0x81, 0x02, 0xc0,
  92. }
  93. if !isRawHIDDescriptor(rawHID) {
  94. t.Error("isRawHIDDescriptor(rawHID) = false, want true")
  95. }
  96. if isRawHIDDescriptor(keyboard) {
  97. t.Error("isRawHIDDescriptor(keyboard) = true, want false")
  98. }
  99. }
  100. func TestParseUEVENT(t *testing.T) {
  101. ueventData := `DRIVER=hid-generic
  102. HID_ID=0003:000036B0:0000309F
  103. HID_NAME=RDMCTMZT Impact 80
  104. HID_PHYS=usb-0000:10:00.0-5.4.1.4.4.1/input0
  105. HID_UNIQ=
  106. MODALIAS=hid:b0003g0001v000036B0p0000309F
  107. `
  108. vid, pid := parseUEVENT(ueventData)
  109. if vid != 0x36B0 {
  110. t.Errorf("parseUEVENT() vid = 0x%04X, want 0x36B0", vid)
  111. }
  112. if pid != 0x309F {
  113. t.Errorf("parseUEVENT() pid = 0x%04X, want 0x309F", pid)
  114. }
  115. // Mouse
  116. mouse := `DRIVER=hid-generic
  117. HID_ID=0003:0000046D:0000C041
  118. HID_NAME=Logitech USB Gaming Mouse
  119. `
  120. vid, pid = parseUEVENT(mouse)
  121. if vid != 0x046D {
  122. t.Errorf("parseUEVENT() mouse vid = 0x%04X, want 0x046D", vid)
  123. }
  124. if pid != 0xC041 {
  125. t.Errorf("parseUEVENT() mouse pid = 0x%04X, want 0xC041", pid)
  126. }
  127. }