hidcomm.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package remdeshid
  2. /*
  3. hidcomm.go
  4. This file contains functions to convert HID commands to bytes
  5. that can be sent over the USBKVM device
  6. */
  7. import "fmt"
  8. // Append the keyboard event subtypes to the data
  9. func appendKeyboardEventSubtypes(data []byte, cmd HIDCommand) ([]byte, error) {
  10. /* Keyboard Subtypes */
  11. if len(cmd.Data) == 1 && cmd.Data[0] >= 32 && cmd.Data[0] <= 127 {
  12. //Valid ASCII character
  13. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  14. data = append(data, SUBTYPE_KEYBOARD_ASCII_PRESS)
  15. } else if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_UP {
  16. data = append(data, SUBTYPE_KEYBOARD_ASCII_RELEASE)
  17. } else {
  18. //Key Click
  19. data = append(data, SUBTYPE_KEYBOARD_ASCII_WRITE)
  20. }
  21. data = append(data, cmd.Data[0])
  22. return data, nil
  23. } else if isFuncKey(cmd.Data) {
  24. //Function Key
  25. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  26. data = append(data, SUBTYPE_KEYBOARD_FUNCTKEY_PRESS)
  27. } else {
  28. data = append(data, SUBTYPE_KEYBOARD_FUNCTKEY_RELEASE)
  29. }
  30. data = append(data, funcKeyToByte(cmd.Data))
  31. if data[0] == 0xFF {
  32. return nil, fmt.Errorf("invalid function key: %v", cmd.Data)
  33. }
  34. return data, nil
  35. } else if isModifierKey(cmd.Data) {
  36. //Modifier Key
  37. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  38. data = append(data, SUBTYPE_KEYBOARD_MODIFIER_PRESS)
  39. } else {
  40. data = append(data, SUBTYPE_KEYBOARD_MODIFIER_RELEASE)
  41. }
  42. data = append(data, modifierKeyToByte(cmd.Data))
  43. if data[0] == 0xFF {
  44. return nil, fmt.Errorf("invalid modifier key: %v", cmd.Data)
  45. }
  46. return data, nil
  47. } else if isOtherKeys(cmd.Data) {
  48. //Other Keys
  49. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  50. data = append(data, SUBTYPE_KEYBOARD_OTHERKEY_PRESS)
  51. } else if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_UP {
  52. data = append(data, SUBTYPE_KEYBOARD_OTHERKEY_RELEASE)
  53. } else {
  54. return nil, fmt.Errorf("invalid HID command subtype: %v", cmd.Data)
  55. }
  56. data = append(data, nonAsciiKeysToBytes(cmd.Data)...)
  57. return data, nil
  58. } else if isNumpadKey(cmd.Data) {
  59. //Numpad Keys
  60. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  61. data = append(data, SUBTYPE_KEYBOARD_NUMPAD_PRESS)
  62. } else if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_UP {
  63. data = append(data, SUBTYPE_KEYBOARD_NUMPAD_RELEASE)
  64. } else {
  65. return nil, fmt.Errorf("invalid HID command subtype: %v", cmd.Data)
  66. }
  67. data = append(data, numpadKeyToByte(string(cmd.Data)))
  68. return data, nil
  69. } else if cmd.Data == "NumLock" {
  70. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  71. data = append(data, SUBTYPE_KEYBOARD_SPECIAL_NUMLOCK)
  72. data = append(data, 0x00)
  73. return data, nil
  74. }
  75. return nil, fmt.Errorf("numLock do not support key up")
  76. } else if cmd.Data == "Pause" {
  77. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  78. data = append(data, SUBTYPE_KEYBOARD_SPECIAL_PAUSE)
  79. data = append(data, 0x00)
  80. return data, nil
  81. }
  82. return nil, fmt.Errorf("pause do not support key up")
  83. } else if cmd.Data == "PrintScreen" {
  84. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_UP {
  85. data = append(data, SUBTYPE_KEYBOARD_SPECIAL_PRINT_SCREEN)
  86. data = append(data, 0x00)
  87. return data, nil
  88. }
  89. return nil, fmt.Errorf("printScreen do not support key down")
  90. } else if cmd.Data == "ScrollLock" {
  91. if cmd.EventSubType == FRONTEND_SUBTYPE_KEYBOARD_KEY_DOWN {
  92. data = append(data, SUBTYPE_KEYBOARD_SPECIAL_SCROLL_LOCK)
  93. data = append(data, 0x00)
  94. return data, nil
  95. }
  96. return nil, fmt.Errorf("scrollLock do not support key up")
  97. } else if cmd.Data == "ContextMenu" {
  98. //Special Key: ContextMenu
  99. //TODO: Implement ContextMenu
  100. return nil, fmt.Errorf("ContextMenu not implemented")
  101. } else if cmd.Data == "Ctrl+Alt+Del" {
  102. //Special Key: Ctrl+Alt+Del
  103. data = append(data, SUBTYPE_KEYBOARD_SPECIAL_CTRLALTDEL)
  104. data = append(data, 0x00)
  105. return data, nil
  106. } else {
  107. return nil, fmt.Errorf("invalid HID command subtype: %v", cmd.Data)
  108. }
  109. }
  110. // Append the mouse click event subtypes to the data
  111. func appendMouseClickEventSubtypes(data []byte, cmd HIDCommand) ([]byte, error) {
  112. /* Mouse Click Subtypes */
  113. isPress := cmd.EventSubType == FRONTEND_MOUSE_PRESS
  114. if isPress {
  115. //Mouse Button Press
  116. data = append(data, 0x02)
  117. } else {
  118. //Mouse Button Release
  119. data = append(data, 0x03)
  120. }
  121. if cmd.Data == FRONTEND_MOUSE_BTN_LEFT {
  122. data = append(data, PAYLOAD_MOUSE_BTN_LEFT)
  123. } else if cmd.Data == FRONTEND_MOUSE_BTN_MIDDLE {
  124. data = append(data, PAYLOAD_MOUSE_BTN_MID)
  125. } else if cmd.Data == FRONTEND_MOUSE_BTN_RIGHT {
  126. data = append(data, PAYLOAD_MOUSE_BTN_RIGHT)
  127. } else {
  128. return nil, fmt.Errorf("invalid HID command subtype: %v", cmd.Data)
  129. }
  130. return data, nil
  131. }
  132. // Append the mouse move event subtypes to the data
  133. func appendMouseMoveEventSubtypes(data []byte, cmd HIDCommand) ([]byte, error) {
  134. //The mouse move command requires x_pos, y_pos, x_sign, y_sign
  135. x_pos := cmd.PosX
  136. y_pos := cmd.PosY
  137. xIsNegative := x_pos < 0
  138. yIsNegative := y_pos < 0
  139. x_sign := 0
  140. y_sign := 0
  141. if xIsNegative {
  142. x_pos = -x_pos
  143. x_sign = 1
  144. }
  145. if yIsNegative {
  146. y_pos = -y_pos
  147. y_sign = 1
  148. }
  149. //The max value for x_pos and y_pos are 0xFE, make sure they are within the range
  150. if x_pos > 0xFE {
  151. x_pos = 0xFE
  152. }
  153. if y_pos > 0xFE {
  154. y_pos = 0xFE
  155. }
  156. data = append(data, byte(x_pos), byte(y_pos), byte(x_sign), byte(y_sign))
  157. return data, nil
  158. }
  159. // Append the mouse scroll event subtypes to the data
  160. // The sensitivityDivider is used to divide the scroll value to make it less sensitive
  161. func appendMouseScrollEventSubtypes(data []byte, cmd HIDCommand) ([]byte, error) {
  162. //The mouse scroll command PosY contains the scroll value
  163. //The scroll command require a direction byte and a scroll value byte
  164. scrollValue := cmd.PosY
  165. if scrollValue < 0 {
  166. //Scroll up
  167. data = append(data, 0x00)
  168. data = append(data, 0x01)
  169. } else {
  170. //Scroll down
  171. data = append(data, 0x01)
  172. data = append(data, 0x01)
  173. }
  174. return data, nil
  175. }
  176. //Entry function for converting a HIDCommand to bytes that can be sent over the USBKVM device
  177. func ConvHIDCommandToBytes(cmd HIDCommand) ([]byte, error) {
  178. // Convert the HID command to bytes
  179. var data []byte
  180. if cmd.EventType == FRONTEND_OPR_TYPE_KEYBOARD_WRITE {
  181. /* Keyboard Write Event */
  182. data = []byte{OPR_TYPE_KEYBOARD_WRITE}
  183. return appendKeyboardEventSubtypes(data, cmd)
  184. } else if cmd.EventType == FRONTEND_OPR_TYPE_MOUSE_WRITE {
  185. /* Mouse Write Event */
  186. data = []byte{OPR_TYPE_MOUSE_WRITE}
  187. return appendMouseClickEventSubtypes(data, cmd)
  188. } else if cmd.EventType == FRONTEND_OPR_TYPE_MOUSE_MOVE {
  189. /* Mouse Move Event */
  190. data = []byte{OPR_TYPE_MOUSE_MOVE}
  191. return appendMouseMoveEventSubtypes(data, cmd)
  192. } else if cmd.EventType == FRONTEND_OPR_TYPE_MOUSE_SCROLL {
  193. /* Mouse Scroll Event */
  194. data = []byte{OPR_TYPE_MOUSE_SCROLL}
  195. return appendMouseScrollEventSubtypes(data, cmd)
  196. }
  197. return nil, fmt.Errorf("invalid HID command type: %s", cmd.EventType)
  198. }