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