hidcomm.go 7.3 KB

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