hid_mouse_template.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbd_core.h"
  7. #include "usbd_hid.h"
  8. /*!< endpoint address */
  9. #define HID_INT_EP 0x81
  10. #define HID_INT_EP_SIZE 4
  11. #define HID_INT_EP_INTERVAL 1
  12. #define USBD_VID 0xffff
  13. #define USBD_PID 0xffff
  14. #define USBD_MAX_POWER 100
  15. #define USBD_LANGID_STRING 1033
  16. /*!< config descriptor size */
  17. #define USB_HID_CONFIG_DESC_SIZ 34
  18. /*!< report descriptor size */
  19. #define HID_MOUSE_REPORT_DESC_SIZE 74
  20. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  21. static const uint8_t device_descriptor[] = {
  22. USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01)
  23. };
  24. static const uint8_t config_descriptor[] = {
  25. USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  26. /************** Descriptor of Joystick Mouse interface ****************/
  27. /* 09 */
  28. 0x09, /* bLength: Interface Descriptor size */
  29. USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
  30. 0x00, /* bInterfaceNumber: Number of Interface */
  31. 0x00, /* bAlternateSetting: Alternate setting */
  32. 0x01, /* bNumEndpoints */
  33. 0x03, /* bInterfaceClass: HID */
  34. 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
  35. 0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
  36. 0, /* iInterface: Index of string descriptor */
  37. /******************** Descriptor of Joystick Mouse HID ********************/
  38. /* 18 */
  39. 0x09, /* bLength: HID Descriptor size */
  40. HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
  41. 0x11, /* bcdHID: HID Class Spec release number */
  42. 0x01,
  43. 0x00, /* bCountryCode: Hardware target country */
  44. 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
  45. 0x22, /* bDescriptorType */
  46. HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
  47. 0x00,
  48. /******************** Descriptor of Mouse endpoint ********************/
  49. /* 27 */
  50. 0x07, /* bLength: Endpoint Descriptor size */
  51. USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
  52. HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
  53. 0x03, /* bmAttributes: Interrupt endpoint */
  54. HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
  55. 0x00,
  56. HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
  57. /* 34 */
  58. };
  59. static const uint8_t device_quality_descriptor[] = {
  60. ///////////////////////////////////////
  61. /// device qualifier descriptor
  62. ///////////////////////////////////////
  63. 0x0a,
  64. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  65. 0x00,
  66. 0x02,
  67. 0x00,
  68. 0x00,
  69. 0x00,
  70. 0x40,
  71. 0x00,
  72. 0x00,
  73. };
  74. static const char *string_descriptors[] = {
  75. (const char[]){ 0x09, 0x04 }, /* Langid */
  76. "CherryUSB", /* Manufacturer */
  77. "CherryUSB HID DEMO", /* Product */
  78. "2022123456", /* Serial Number */
  79. };
  80. static const uint8_t *device_descriptor_callback(uint8_t speed)
  81. {
  82. return device_descriptor;
  83. }
  84. static const uint8_t *config_descriptor_callback(uint8_t speed)
  85. {
  86. return config_descriptor;
  87. }
  88. static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
  89. {
  90. return device_quality_descriptor;
  91. }
  92. static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
  93. {
  94. if (index > 3) {
  95. return NULL;
  96. }
  97. return string_descriptors[index];
  98. }
  99. const struct usb_descriptor hid_descriptor = {
  100. .device_descriptor_callback = device_descriptor_callback,
  101. .config_descriptor_callback = config_descriptor_callback,
  102. .device_quality_descriptor_callback = device_quality_descriptor_callback,
  103. .string_descriptor_callback = string_descriptor_callback
  104. };
  105. #else
  106. /*!< global descriptor */
  107. const uint8_t hid_descriptor[] = {
  108. USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
  109. USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
  110. /************** Descriptor of Joystick Mouse interface ****************/
  111. /* 09 */
  112. 0x09, /* bLength: Interface Descriptor size */
  113. USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
  114. 0x00, /* bInterfaceNumber: Number of Interface */
  115. 0x00, /* bAlternateSetting: Alternate setting */
  116. 0x01, /* bNumEndpoints */
  117. 0x03, /* bInterfaceClass: HID */
  118. 0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
  119. 0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
  120. 0, /* iInterface: Index of string descriptor */
  121. /******************** Descriptor of Joystick Mouse HID ********************/
  122. /* 18 */
  123. 0x09, /* bLength: HID Descriptor size */
  124. HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
  125. 0x11, /* bcdHID: HID Class Spec release number */
  126. 0x01,
  127. 0x00, /* bCountryCode: Hardware target country */
  128. 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
  129. 0x22, /* bDescriptorType */
  130. HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
  131. 0x00,
  132. /******************** Descriptor of Mouse endpoint ********************/
  133. /* 27 */
  134. 0x07, /* bLength: Endpoint Descriptor size */
  135. USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
  136. HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
  137. 0x03, /* bmAttributes: Interrupt endpoint */
  138. HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
  139. 0x00,
  140. HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
  141. /* 34 */
  142. ///////////////////////////////////////
  143. /// string0 descriptor
  144. ///////////////////////////////////////
  145. USB_LANGID_INIT(USBD_LANGID_STRING),
  146. ///////////////////////////////////////
  147. /// string1 descriptor
  148. ///////////////////////////////////////
  149. 0x14, /* bLength */
  150. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  151. 'C', 0x00, /* wcChar0 */
  152. 'h', 0x00, /* wcChar1 */
  153. 'e', 0x00, /* wcChar2 */
  154. 'r', 0x00, /* wcChar3 */
  155. 'r', 0x00, /* wcChar4 */
  156. 'y', 0x00, /* wcChar5 */
  157. 'U', 0x00, /* wcChar6 */
  158. 'S', 0x00, /* wcChar7 */
  159. 'B', 0x00, /* wcChar8 */
  160. ///////////////////////////////////////
  161. /// string2 descriptor
  162. ///////////////////////////////////////
  163. 0x26, /* bLength */
  164. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  165. 'C', 0x00, /* wcChar0 */
  166. 'h', 0x00, /* wcChar1 */
  167. 'e', 0x00, /* wcChar2 */
  168. 'r', 0x00, /* wcChar3 */
  169. 'r', 0x00, /* wcChar4 */
  170. 'y', 0x00, /* wcChar5 */
  171. 'U', 0x00, /* wcChar6 */
  172. 'S', 0x00, /* wcChar7 */
  173. 'B', 0x00, /* wcChar8 */
  174. ' ', 0x00, /* wcChar9 */
  175. 'H', 0x00, /* wcChar10 */
  176. 'I', 0x00, /* wcChar11 */
  177. 'D', 0x00, /* wcChar12 */
  178. ' ', 0x00, /* wcChar13 */
  179. 'D', 0x00, /* wcChar14 */
  180. 'E', 0x00, /* wcChar15 */
  181. 'M', 0x00, /* wcChar16 */
  182. 'O', 0x00, /* wcChar17 */
  183. ///////////////////////////////////////
  184. /// string3 descriptor
  185. ///////////////////////////////////////
  186. 0x16, /* bLength */
  187. USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
  188. '2', 0x00, /* wcChar0 */
  189. '0', 0x00, /* wcChar1 */
  190. '2', 0x00, /* wcChar2 */
  191. '2', 0x00, /* wcChar3 */
  192. '1', 0x00, /* wcChar4 */
  193. '2', 0x00, /* wcChar5 */
  194. '3', 0x00, /* wcChar6 */
  195. '4', 0x00, /* wcChar7 */
  196. '5', 0x00, /* wcChar8 */
  197. '6', 0x00, /* wcChar9 */
  198. #ifdef CONFIG_USB_HS
  199. ///////////////////////////////////////
  200. /// device qualifier descriptor
  201. ///////////////////////////////////////
  202. 0x0a,
  203. USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
  204. 0x00,
  205. 0x02,
  206. 0x00,
  207. 0x00,
  208. 0x00,
  209. 0x40,
  210. 0x00,
  211. 0x00,
  212. #endif
  213. 0x00
  214. };
  215. #endif
  216. /*!< hid mouse report descriptor */
  217. static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
  218. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  219. 0x09, 0x02, // USAGE (Mouse)
  220. 0xA1, 0x01, // COLLECTION (Application)
  221. 0x09, 0x01, // USAGE (Pointer)
  222. 0xA1, 0x00, // COLLECTION (Physical)
  223. 0x05, 0x09, // USAGE_PAGE (Button)
  224. 0x19, 0x01, // USAGE_MINIMUM (Button 1)
  225. 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
  226. 0x15, 0x00, // LOGICAL_MINIMUM (0)
  227. 0x25, 0x01, // LOGICAL_MAXIMUM (1)
  228. 0x95, 0x03, // REPORT_COUNT (3)
  229. 0x75, 0x01, // REPORT_SIZE (1)
  230. 0x81, 0x02, // INPUT (Data,Var,Abs)
  231. 0x95, 0x01, // REPORT_COUNT (1)
  232. 0x75, 0x05, // REPORT_SIZE (5)
  233. 0x81, 0x01, // INPUT (Cnst,Var,Abs)
  234. 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
  235. 0x09, 0x30, // USAGE (X)
  236. 0x09, 0x31, // USAGE (Y)
  237. 0x09, 0x38,
  238. 0x15, 0x81, // LOGICAL_MINIMUM (-127)
  239. 0x25, 0x7F, // LOGICAL_MAXIMUM (127)
  240. 0x75, 0x08, // REPORT_SIZE (8)
  241. 0x95, 0x03, // REPORT_COUNT (2)
  242. 0x81, 0x06, // INPUT (Data,Var,Rel)
  243. 0xC0, 0x09,
  244. 0x3c, 0x05,
  245. 0xff, 0x09,
  246. 0x01, 0x15,
  247. 0x00, 0x25,
  248. 0x01, 0x75,
  249. 0x01, 0x95,
  250. 0x02, 0xb1,
  251. 0x22, 0x75,
  252. 0x06, 0x95,
  253. 0x01, 0xb1,
  254. 0x01, 0xc0 // END_COLLECTION
  255. };
  256. /*!< mouse report struct */
  257. struct hid_mouse {
  258. uint8_t buttons;
  259. int8_t x;
  260. int8_t y;
  261. int8_t wheel;
  262. };
  263. /*!< mouse report */
  264. static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct hid_mouse mouse_cfg;
  265. #define HID_STATE_IDLE 0
  266. #define HID_STATE_BUSY 1
  267. /*!< hid state ! Data can be sent only when state is idle */
  268. static volatile uint8_t hid_state = HID_STATE_IDLE;
  269. static void usbd_event_handler(uint8_t busid, uint8_t event)
  270. {
  271. switch (event) {
  272. case USBD_EVENT_RESET:
  273. break;
  274. case USBD_EVENT_CONNECTED:
  275. break;
  276. case USBD_EVENT_DISCONNECTED:
  277. break;
  278. case USBD_EVENT_RESUME:
  279. break;
  280. case USBD_EVENT_SUSPEND:
  281. break;
  282. case USBD_EVENT_CONFIGURED:
  283. hid_state = HID_STATE_IDLE;
  284. break;
  285. case USBD_EVENT_SET_REMOTE_WAKEUP:
  286. break;
  287. case USBD_EVENT_CLR_REMOTE_WAKEUP:
  288. break;
  289. default:
  290. break;
  291. }
  292. }
  293. /* function ------------------------------------------------------------------*/
  294. static void usbd_hid_int_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
  295. {
  296. hid_state = HID_STATE_IDLE;
  297. }
  298. /*!< endpoint call back */
  299. static struct usbd_endpoint hid_in_ep = {
  300. .ep_cb = usbd_hid_int_callback,
  301. .ep_addr = HID_INT_EP
  302. };
  303. struct usbd_interface intf0;
  304. void hid_mouse_init(uint8_t busid, uintptr_t reg_base)
  305. {
  306. #ifdef CONFIG_USBDEV_ADVANCE_DESC
  307. usbd_desc_register(busid, &hid_descriptor);
  308. #else
  309. usbd_desc_register(busid, hid_descriptor);
  310. #endif
  311. usbd_add_interface(busid, usbd_hid_init_intf(busid, &intf0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE));
  312. usbd_add_endpoint(busid, &hid_in_ep);
  313. usbd_initialize(busid, reg_base, usbd_event_handler);
  314. /*!< init mouse report data */
  315. mouse_cfg.buttons = 0;
  316. mouse_cfg.wheel = 0;
  317. mouse_cfg.x = 0;
  318. mouse_cfg.y = 0;
  319. }
  320. #define CURSOR_STEP 2U
  321. #define CURSOR_WIDTH 20U
  322. void draw_circle(uint8_t *buf)
  323. {
  324. static int32_t move_cnt = 0;
  325. static uint8_t step_x_y = 0;
  326. static int8_t x = 0, y = 0;
  327. move_cnt++;
  328. if (move_cnt > CURSOR_WIDTH) {
  329. step_x_y++;
  330. step_x_y = step_x_y % 4;
  331. move_cnt = 0;
  332. }
  333. switch (step_x_y) {
  334. case 0: {
  335. y = 0;
  336. x = CURSOR_STEP;
  337. } break;
  338. case 1: {
  339. x = 0;
  340. y = CURSOR_STEP;
  341. } break;
  342. case 2: {
  343. y = 0;
  344. x = (int8_t)(-CURSOR_STEP);
  345. } break;
  346. case 3: {
  347. x = 0;
  348. y = (int8_t)(-CURSOR_STEP);
  349. } break;
  350. }
  351. buf[0] = 0;
  352. buf[1] = x;
  353. buf[2] = y;
  354. buf[3] = 0;
  355. }
  356. /* https://cps-check.com/cn/polling-rate-check */
  357. void hid_mouse_test(uint8_t busid)
  358. {
  359. if(usb_device_is_configured(busid) == false) {
  360. return;
  361. }
  362. int counter = 0;
  363. while (counter < 1000) {
  364. draw_circle((uint8_t *)&mouse_cfg);
  365. hid_state = HID_STATE_BUSY;
  366. usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
  367. while (hid_state == HID_STATE_BUSY) {
  368. }
  369. counter++;
  370. }
  371. }