You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

HIDKeyboard.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include <stdint.h>
  2. #include "USBHID.h"
  3. #include "USBHID_Types.h"
  4. #include "USBDescriptor.h"
  5. #include "HIDKeyboard.h"
  6. #define DEFAULT_CONFIGURATION (1)
  7. HIDKeyboard::HIDKeyboard(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release)
  8. {
  9. USBDevice::connect();
  10. }
  11. bool HIDKeyboard::sendReport(report_keyboard_t report) {
  12. USBDevice::write(EP1IN, report.raw, sizeof(report), MAX_PACKET_SIZE_EP1);
  13. return true;
  14. }
  15. uint8_t HIDKeyboard::leds() {
  16. return led_state;
  17. }
  18. bool HIDKeyboard::USBCallback_setConfiguration(uint8_t configuration) {
  19. if (configuration != DEFAULT_CONFIGURATION) {
  20. return false;
  21. }
  22. // Configure endpoints > 0
  23. addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
  24. //addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
  25. // We activate the endpoint to be able to recceive data
  26. //readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
  27. return true;
  28. }
  29. uint8_t * HIDKeyboard::stringImanufacturerDesc() {
  30. static uint8_t stringImanufacturerDescriptor[] = {
  31. 0x18, /*bLength*/
  32. STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
  33. 't',0,'m',0,'k',0,'-',0,'k',0,'b',0,'d',0,'.',0,'c',0,'o',0,'m',0 /*bString iManufacturer*/
  34. };
  35. return stringImanufacturerDescriptor;
  36. }
  37. uint8_t * HIDKeyboard::stringIproductDesc() {
  38. static uint8_t stringIproductDescriptor[] = {
  39. 0x0a, /*bLength*/
  40. STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
  41. 'm',0,'b',0,'e',0,'d',0 /*bString iProduct*/
  42. };
  43. return stringIproductDescriptor;
  44. }
  45. uint8_t * HIDKeyboard::stringIserialDesc() {
  46. static uint8_t stringIserialDescriptor[] = {
  47. 0x04, /*bLength*/
  48. STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
  49. '0',0 /*bString iSerial*/
  50. };
  51. return stringIserialDescriptor;
  52. }
  53. uint8_t * HIDKeyboard::reportDesc() {
  54. static uint8_t reportDescriptor[] = {
  55. USAGE_PAGE(1), 0x01, // Generic Desktop
  56. USAGE(1), 0x06, // Keyboard
  57. COLLECTION(1), 0x01, // Application
  58. USAGE_PAGE(1), 0x07, // Key Codes
  59. USAGE_MINIMUM(1), 0xE0,
  60. USAGE_MAXIMUM(1), 0xE7,
  61. LOGICAL_MINIMUM(1), 0x00,
  62. LOGICAL_MAXIMUM(1), 0x01,
  63. REPORT_SIZE(1), 0x01,
  64. REPORT_COUNT(1), 0x08,
  65. INPUT(1), 0x02, // Data, Variable, Absolute
  66. REPORT_COUNT(1), 0x01,
  67. REPORT_SIZE(1), 0x08,
  68. INPUT(1), 0x01, // Constant
  69. REPORT_COUNT(1), 0x05,
  70. REPORT_SIZE(1), 0x01,
  71. USAGE_PAGE(1), 0x08, // LEDs
  72. USAGE_MINIMUM(1), 0x01,
  73. USAGE_MAXIMUM(1), 0x05,
  74. OUTPUT(1), 0x02, // Data, Variable, Absolute
  75. REPORT_COUNT(1), 0x01,
  76. REPORT_SIZE(1), 0x03,
  77. OUTPUT(1), 0x01, // Constant
  78. REPORT_COUNT(1), 0x06,
  79. REPORT_SIZE(1), 0x08,
  80. LOGICAL_MINIMUM(1), 0x00,
  81. LOGICAL_MAXIMUM(2), 0xFF, 0x00,
  82. USAGE_PAGE(1), 0x07, // Key Codes
  83. USAGE_MINIMUM(1), 0x00,
  84. USAGE_MAXIMUM(1), 0xFF,
  85. INPUT(1), 0x00, // Data, Array
  86. END_COLLECTION(0),
  87. };
  88. reportLength = sizeof(reportDescriptor);
  89. return reportDescriptor;
  90. }
  91. uint16_t HIDKeyboard::reportDescLength() {
  92. reportDesc();
  93. return reportLength;
  94. }
  95. #define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
  96. + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
  97. + (1 * HID_DESCRIPTOR_LENGTH) \
  98. + (1 * ENDPOINT_DESCRIPTOR_LENGTH))
  99. uint8_t * HIDKeyboard::configurationDesc() {
  100. static uint8_t configurationDescriptor[] = {
  101. CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
  102. CONFIGURATION_DESCRIPTOR, // bDescriptorType
  103. LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
  104. MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
  105. 0x01, // bNumInterfaces
  106. DEFAULT_CONFIGURATION, // bConfigurationValue
  107. 0x00, // iConfiguration
  108. C_RESERVED | C_REMOTE_WAKEUP, // bmAttributes
  109. C_POWER(100), // bMaxPowerHello World from Mbed
  110. INTERFACE_DESCRIPTOR_LENGTH, // bLength
  111. INTERFACE_DESCRIPTOR, // bDescriptorType
  112. 0x00, // bInterfaceNumber
  113. 0x00, // bAlternateSetting
  114. 0x01, // bNumEndpoints
  115. HID_CLASS, // bInterfaceClass
  116. 1, // bInterfaceSubClass (boot)
  117. 1, // bInterfaceProtocol (keyboard)
  118. 0x00, // iInterface
  119. HID_DESCRIPTOR_LENGTH, // bLength
  120. HID_DESCRIPTOR, // bDescriptorType
  121. LSB(HID_VERSION_1_11), // bcdHID (LSB)
  122. MSB(HID_VERSION_1_11), // bcdHID (MSB)
  123. 0x00, // bCountryCode
  124. 0x01, // bNumDescriptors
  125. REPORT_DESCRIPTOR, // bDescriptorType
  126. (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB)
  127. (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB)
  128. ENDPOINT_DESCRIPTOR_LENGTH, // bLength
  129. ENDPOINT_DESCRIPTOR, // bDescriptorType
  130. PHY_TO_DESC(EP1IN), // bEndpointAddress
  131. E_INTERRUPT, // bmAttributes
  132. LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
  133. MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
  134. 1, // bInterval (milliseconds)
  135. };
  136. return configurationDescriptor;
  137. }
  138. #if 0
  139. uint8_t * HIDKeyboard::deviceDesc() {
  140. static uint8_t deviceDescriptor[] = {
  141. DEVICE_DESCRIPTOR_LENGTH, /* bLength */
  142. DEVICE_DESCRIPTOR, /* bDescriptorType */
  143. LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
  144. MSB(USB_VERSION_2_0), /* bcdUSB (MSB) */
  145. 0x00, /* bDeviceClass */
  146. 0x00, /* bDeviceSubClass */
  147. 0x00, /* bDeviceprotocol */
  148. MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
  149. (uint8_t)(LSB(0xfeed)), /* idVendor (LSB) */
  150. (uint8_t)(MSB(0xfeed)), /* idVendor (MSB) */
  151. (uint8_t)(LSB(0x1bed)), /* idProduct (LSB) */
  152. (uint8_t)(MSB(0x1bed)), /* idProduct (MSB) */
  153. (uint8_t)(LSB(0x0002)), /* bcdDevice (LSB) */
  154. (uint8_t)(MSB(0x0002)), /* bcdDevice (MSB) */
  155. 0, /* iManufacturer */
  156. 0, /* iProduct */
  157. 0, /* iSerialNumber */
  158. 0x01 /* bNumConfigurations */
  159. };
  160. return deviceDescriptor;
  161. }
  162. #endif
  163. bool HIDKeyboard::USBCallback_request() {
  164. bool success = false;
  165. CONTROL_TRANSFER * transfer = getTransferPtr();
  166. uint8_t *hidDescriptor;
  167. // Process additional standard requests
  168. if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
  169. {
  170. switch (transfer->setup.bRequest)
  171. {
  172. case GET_DESCRIPTOR:
  173. switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
  174. {
  175. case REPORT_DESCRIPTOR:
  176. if ((reportDesc() != NULL) \
  177. && (reportDescLength() != 0))
  178. {
  179. transfer->remaining = reportDescLength();
  180. transfer->ptr = reportDesc();
  181. transfer->direction = DEVICE_TO_HOST;
  182. success = true;
  183. }
  184. break;
  185. case HID_DESCRIPTOR:
  186. // Find the HID descriptor, after the configuration descriptor
  187. hidDescriptor = findDescriptor(HID_DESCRIPTOR);
  188. if (hidDescriptor != NULL)
  189. {
  190. transfer->remaining = HID_DESCRIPTOR_LENGTH;
  191. transfer->ptr = hidDescriptor;
  192. transfer->direction = DEVICE_TO_HOST;
  193. success = true;
  194. }
  195. break;
  196. default:
  197. break;
  198. }
  199. break;
  200. default:
  201. break;
  202. }
  203. }
  204. // Process class-specific requests
  205. if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
  206. {
  207. switch (transfer->setup.bRequest) {
  208. case SET_REPORT:
  209. // LED indicator
  210. // TODO: check Interface and Report length?
  211. // if (transfer->setup.wIndex == INTERFACE_KEYBOAD) { }
  212. // if (transfer->setup.wLength == 1)
  213. transfer->remaining = 1;
  214. //transfer->ptr = ?? what ptr should be set when OUT(not used?)
  215. transfer->direction = HOST_TO_DEVICE;
  216. transfer->notify = true; /* notify with USBCallback_requestCompleted */
  217. success = true;
  218. default:
  219. break;
  220. }
  221. }
  222. return success;
  223. }
  224. void HIDKeyboard::USBCallback_requestCompleted(uint8_t * buf, uint32_t length)
  225. {
  226. if (length > 0) {
  227. CONTROL_TRANSFER *transfer = getTransferPtr();
  228. if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
  229. switch (transfer->setup.bRequest) {
  230. case SET_REPORT:
  231. led_state = buf[0];
  232. break;
  233. default:
  234. break;
  235. }
  236. }
  237. }
  238. }