1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved.
3 * Description: LiteOS USB Driver HID Protocol
4 * Author: wanghongxu
5 * Create: 2019-10-24
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28 /* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36
37 #include "gadget/f_hid.h"
38 #include "gadget/usbd_hid.h"
39 #include "core/usbhid.h"
40 #include "implementation/global_implementation.h"
41 #ifdef LOSCFG_DRIVERS_USB2_DEVICE_CONTROLLER
42 #include "controller/usb_device/dwc_otg_pcd.h"
43 #endif
44
45 #ifdef __cplusplus
46 #if __cplusplus
47 extern "C" {
48 #endif /* __cplusplus */
49 #endif /* __cplusplus */
50
51 int usbdev_hid_initialize(struct module *mod, int n, void *arg);
52
53 /* device driver structure definition */
54
55 static const driver_t g_fhid_driver =
56 {
57 .name = "fhid",
58 .methods = NULL,
59 .size = sizeof(struct hid_softc)
60 };
61
62 /* private device class information */
63
64 static devclass_t g_fhid_devclass;
65 DRIVER_MODULE(fhid, simple, g_fhid_driver, g_fhid_devclass, usbdev_hid_initialize, 0);
66
67 static int usbclass_hid_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
68 static int usbclass_hid_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
69 static int usbclass_hid_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
70 const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen);
71 static void usbclass_hid_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
72
73 /* USB driver operations */
74
75 static const struct usbdevclass_driverops_s g_hid_driverops =
76 {
77 usbclass_hid_bind,
78 usbclass_hid_unbind,
79 usbclass_hid_setup,
80 usbclass_hid_disconnect,
81 NULL,
82 NULL
83 };
84
85 static struct dev_report_desc g_fhid_report_desc;
86
87 #define HID_STRING_HEAD_LEN 2
88 #define HID_STRING_DESC_NUM 3
89 #define HID_STRING_LEN_MAX 0xFF
90
91 #define HID_STR_LANG 4
92 static const char g_fhid_str_lang[HID_STR_LANG] =
93 {
94 HID_STR_LANG,
95 UDESC_STRING,
96 0x09, 0x04
97 };
98
99 #define HID_STR_IDX_INTERFACE 28
100 static const char g_fhid_str_interface[HID_STR_IDX_INTERFACE] =
101 {
102 HID_STR_IDX_INTERFACE,
103 UDESC_STRING,
104 'H', 0, 'I', 0, 'D', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0,
105 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0
106 };
107
108 struct usbd_string g_fhid_device_strings[6] =
109 {
110 { 0, g_fhid_str_lang },
111 { 1, NULL },
112 { 2, NULL },
113 { 3, NULL },
114 { 4, g_fhid_str_interface },
115 USBD_DEVICE_STRINGS_END
116 };
117
118 static struct usb_device_descriptor g_fhid_device_desc =
119 {
120 .bLength = sizeof(struct usb_device_descriptor),
121 .bDescriptorType = UDESC_DEVICE, /* Constant for device descriptor */
122 HSETW(.bcdUSB, UD_BCD_USB), /* USB version required: 2.0 */
123 .bDeviceClass = 0x00, /* Miscellaneous Device Class */
124 .bDeviceSubClass = 0x00, /* Common Class */
125 .bDeviceProtocol = 0x00, /* Interface Association Descriptor */
126 .bMaxPacketSize = UD_USB_MPS, /* Control Endpoint packet size */
127 HSETW(.bcdDevice, 0x0100), /* Device release code */
128 .iManufacturer = 1, /* Manufacturer name, string index */
129 .iProduct = 2, /* Product name, string index */
130 .iSerialNumber = 3, /* Used */
131 .bNumConfigurations = 1 /* One Configuration */
132 };
133
134 static struct usb_config_descriptor g_fhid_config_desc =
135 {
136 .bLength = sizeof(struct usb_config_descriptor),
137 .bDescriptorType = UDESC_CONFIG,
138 HSETW(.wTotalLength, 0x0029), /* Size of all descriptors, set later */
139 .bNumInterface = 0x1, /* Number of Interfaces */
140 .bConfigurationValue = 0x1, /* ID of this configuration */
141 .iConfiguration = 0x0, /* Index of string descriptor */
142 .bmAttributes = 0xc0, /* Self-powered */
143 .bMaxPower = 0x32 /* Maximum power consumption from the bus */
144 };
145
146 static const struct usb_interface_descriptor g_fhid_intf_desc =
147 {
148 .bLength = sizeof(struct usb_interface_descriptor),
149 .bDescriptorType = UDESC_INTERFACE,
150 .bInterfaceNumber = 0, /* index number of this interface */
151 .bAlternateSetting = 0, /* index of this settings */
152 .bNumEndpoints = 2, /* Number of endpoint */
153 .bInterfaceClass = 0x03, /* bInterfaceClass: HID */
154 .bInterfaceSubClass = 0, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
155 .bInterfaceProtocol = 0, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
156 .iInterface = 4 /* index of string descriptor */
157 };
158
159 static struct usb_hid_descriptor g_fhid_desc =
160 {
161 .bLength = sizeof(struct usb_hid_descriptor),
162 .bDescriptorType = UDESC_HID, /* HID type is 0x21 */
163 HSETW(.bcdHID, 0x0110), /* bcdHID: HID Class Spec release number HID 1.1 */
164 .bCountryCode = 0x00, /* bCountryCode: Hardware target country */
165 .bNumDescriptors = 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
166 {
167 {
168 .bDescriptorType = 0x22, /* bDescriptorType */
169 }
170 }
171 };
172
173 static const struct hid_endpoint_descriptor g_fhid_in_ep_desc =
174 {
175 .bLength = sizeof(struct hid_endpoint_descriptor),
176 .bDescriptorType = UDESC_ENDPOINT,
177 .bEndpointAddress = UE_DIR_IN | 0x01,
178 .bmAttributes = 0x03, /* bmAttributes = 00000011b */
179 HSETW(.wMaxPacketSize, HID_IN_DATA_SIZE), /* wMaxPacketSize = 64 */
180 .bInterval = 0x04 /* bInterval = 4ms */
181 };
182
183 static const struct hid_endpoint_descriptor g_fhid_out_ep_desc =
184 {
185 .bLength = sizeof(struct hid_endpoint_descriptor),
186 .bDescriptorType = UDESC_ENDPOINT,
187 .bEndpointAddress = UE_DIR_OUT | 0x01,
188 .bmAttributes = 0x03,
189 HSETW(.wMaxPacketSize, HID_OUT_DATA_SIZE),
190 .bInterval = 0x04
191 };
192
193 const uint8_t *g_fhid_desc_array[] =
194 {
195 (const uint8_t *)&g_fhid_config_desc,
196 (const uint8_t *)&g_fhid_intf_desc,
197 (const uint8_t *)&g_fhid_desc,
198 (const uint8_t *)&g_fhid_in_ep_desc,
199 (const uint8_t *)&g_fhid_out_ep_desc,
200 NULL,
201 };
202
hid_deviceid_info(uint16_t vendorid,uint16_t productid)203 void hid_deviceid_info(uint16_t vendorid, uint16_t productid)
204 {
205 USETW(g_fhid_device_desc.idVendor, vendorid);
206
207 USETW(g_fhid_device_desc.idProduct, productid);
208 }
209
hid_device_string_info(const struct dev_string_desc * str_manufacturer,const struct dev_string_desc * str_product,const struct dev_string_desc * str_serial_number)210 int hid_device_string_info(const struct dev_string_desc *str_manufacturer,
211 const struct dev_string_desc *str_product,
212 const struct dev_string_desc *str_serial_number)
213 {
214 char *buf[HID_STRING_DESC_NUM] = {NULL};
215 const struct dev_string_desc *str_desc[HID_STRING_DESC_NUM];
216 int i;
217 uint32_t len;
218
219 if (str_manufacturer == NULL || str_product == NULL || str_serial_number == NULL)
220 {
221 usb_err("%s failed, invalid param!\n", __FUNCTION__);
222 return -1;
223 }
224
225 if (str_manufacturer->str == NULL || str_manufacturer->len == 0 ||
226 str_serial_number->str == NULL || str_serial_number->len == 0 ||
227 str_product->str == NULL || str_product->len == 0)
228 {
229 usb_err("%s failed, str is NULL or len is 0\n", __FUNCTION__);
230 return -1;
231 }
232
233 if (str_manufacturer->len > (HID_STRING_LEN_MAX - HID_STRING_HEAD_LEN) ||
234 str_serial_number->len > (HID_STRING_LEN_MAX - HID_STRING_HEAD_LEN) ||
235 str_product->len > (HID_STRING_LEN_MAX - HID_STRING_HEAD_LEN))
236 {
237 usb_err("%s failed, len exceeds maximum limit! str_manufacturer->len = %u"
238 "str_serial_number->len = %u str_product->len = %u\n", __FUNCTION__,
239 str_manufacturer->len, str_serial_number->len, str_product->len);
240 return -1;
241 }
242
243 str_desc[0] = str_manufacturer;
244 str_desc[1] = str_product;
245 str_desc[2] = str_serial_number;
246
247 for (i = 0; i < HID_STRING_DESC_NUM; i++)
248 {
249 len = str_desc[i]->len + HID_STRING_HEAD_LEN;
250 buf[i] = (char *)malloc(len);
251 if (buf[i] == NULL)
252 {
253 usb_err("%s malloc failed\n", __FUNCTION__);
254 goto errout;
255 }
256 g_fhid_device_strings[i + 1].s = buf[i];
257
258 *buf[i] = (char)len;
259 *(buf[i] + 1) = UDESC_STRING;
260
261 /* len represents the size of the string */
262
263 (void)memcpy_s(buf[i] + HID_STRING_HEAD_LEN, (size_t)str_desc[i]->len,
264 str_desc[i]->str, (size_t)str_desc[i]->len);
265 }
266
267 return 0;
268
269 errout:
270 for (i = 0; i < HID_STRING_DESC_NUM; i++)
271 {
272 if (buf[i] != NULL)
273 {
274 free(buf[i]);
275 }
276 }
277 return -1;
278 }
279
hid_report_descriptor_info(const void * buf,size_t len)280 int hid_report_descriptor_info(const void *buf, size_t len)
281 {
282 uint8_t *report_desc;
283
284 if (buf == NULL || len == 0)
285 {
286 usb_err("%s failed, buf is NULL or len is 0\n", __FUNCTION__);
287 return -1;
288 }
289
290 report_desc = (uint8_t *)malloc(len);
291 if (report_desc == NULL)
292 {
293 usb_err("%s malloc failed\n", __FUNCTION__);
294 return -1;
295 }
296
297 g_fhid_report_desc.report_size = len;
298 g_fhid_report_desc.report_desc = report_desc;
299
300 /* len represents the size of the report */
301
302 (void)memcpy_s(report_desc, len, buf, len);
303
304 return 0;
305 }
306
usbdev_hid_free(void)307 static void usbdev_hid_free(void)
308 {
309 int i;
310
311 if (g_fhid_report_desc.report_desc != NULL)
312 {
313 free(g_fhid_report_desc.report_desc);
314 g_fhid_report_desc.report_desc = NULL;
315 }
316
317 for (i = 1; i <= HID_STRING_DESC_NUM; i++)
318 {
319 if (g_fhid_device_strings[i].s != NULL)
320 {
321 free((void *)g_fhid_device_strings[i].s);
322 g_fhid_device_strings[i].s = NULL;
323 }
324 }
325 }
326
fhid_output_request_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)327 static void fhid_output_request_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
328 {
329 struct hid_dev_s *hid;
330 errno_t ret;
331 uint32_t ret_event;
332
333 if (ep == NULL || ep->priv == NULL || req == NULL)
334 {
335 usb_err("Illegal request or ep!\n");
336 return;
337 }
338
339 if (req->result != 0)
340 {
341 return;
342 }
343
344 hid = (struct hid_dev_s *)ep->priv;
345 spin_lock(&hid->hid_lock);
346
347 /* Save private data of read request */
348
349 hid->read_len = req->xfrd;
350 ret = memcpy_s(hid->read_buf, HID_OUT_DATA_SIZE, req->buf, req->xfrd);
351 if (ret != EOK)
352 {
353 spin_unlock(&hid->hid_lock);
354 usb_err("memcpy fail!\n");
355 return;
356 }
357 spin_unlock(&hid->hid_lock);
358
359 ret_event = LOS_EventWrite(&hid->read_event, USB_HID_READ_EVENT);
360 if (ret_event != LOS_OK)
361 {
362 usb_err("write event failed!\r\n");
363 }
364
365 (void)EP_SUBMIT(hid->out_ep, req);
366 }
367
fhid_input_req_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)368 static void fhid_input_req_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
369 {
370 struct hid_dev_s *hid = (struct hid_dev_s *)ep->priv;
371 struct hid_queue_node *node_temp;
372
373 spin_lock(&hid->hid_lock);
374 atomic_set(&hid->busy_flag, 0);
375
376 if (req->result != 0)
377 {
378 hid_queue_free(hid);
379 spin_unlock(&hid->hid_lock);
380 return;
381 }
382
383 if (hid->cur_node != NULL)
384 {
385 node_temp = hid->cur_node;
386 if (node_temp->buf_len == 0)
387 {
388 hid_queue_node_free(node_temp);
389 hid->cur_node = NULL;
390 }
391 else
392 {
393 hid_send_data_sub(hid);
394 spin_unlock(&hid->hid_lock);
395 return;
396 }
397 }
398
399 if (!list_empty(&hid->hid_queue))
400 {
401 node_temp = list_first_entry(&hid->hid_queue, struct hid_queue_node, irqqueue);
402 hid->cur_node = node_temp;
403 list_del_init(&node_temp->irqqueue);
404 hid->hid_queue_len--;
405 hid_send_data_sub(hid);
406 }
407 spin_unlock(&hid->hid_lock);
408 }
409
fhid_source_free(struct hid_dev_s * hid,struct usbdev_s * dev)410 static void fhid_source_free(struct hid_dev_s *hid, struct usbdev_s *dev)
411 {
412 if (hid != NULL)
413 {
414 DEV_FREEEP(dev, hid->out_ep);
415 DEV_FREEEP(dev, hid->in_ep);
416 }
417 }
418
usbclass_hid_bind(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)419 static int usbclass_hid_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
420 {
421 struct usbdev_ep_s *ep;
422 struct hid_driver_s *drvr;
423 struct composite_dev_s *cdev;
424 struct hid_dev_s *hid;
425 struct composite_devobj_s *devobj;
426 struct usbdev_devinfo_s *devinfo;
427 int ret;
428
429 if (driver == NULL || dev == NULL)
430 {
431 return -1;
432 }
433
434 cdev = dev->ep0->priv;
435 drvr = (struct hid_driver_s *)driver;
436 hid = drvr->dev;
437 if (hid == NULL)
438 {
439 return -1;
440 }
441
442 INIT_LIST_HEAD(&hid->hid_queue);
443 hid->busy_flag = 0;
444 hid->hid_queue_len = 0;
445 hid->cur_node = NULL;
446
447 devobj = usbclass_devobj_get(cdev, DEV_HID);
448 if (devobj == NULL)
449 {
450 return -1;
451 }
452 devinfo = &devobj->compdesc.devinfo;
453
454 /* Initialize the interrupt output endpoint */
455
456 ep = DEV_ALLOCEP(dev, g_fhid_out_ep_desc.bEndpointAddress, (struct usb_endpoint_descriptor *)&g_fhid_out_ep_desc);
457 if (ep == NULL)
458 {
459 return -1;
460 }
461
462 (void)memset_s(&(hid->outputreq), sizeof(struct usbdev_req_s), 0, sizeof(struct usbdev_req_s));
463 hid->outputreq.callback = fhid_output_request_complete;
464 hid->outputreq.priv = (void *)hid;
465 hid->outputreq.buf = NULL;
466 ep->priv = (void *)hid;
467 ep->handle_req = &hid->outputreq;
468 hid->out_ep = ep;
469 devinfo->epno[0] = ep->eplog;
470
471 (VOID)LOS_EventInit(&hid->read_event);
472 spin_lock_init(&hid->hid_lock);
473 hid->read_len = 0;
474 hid->read_buf = memalign(USB_CACHE_ALIGN_SIZE, HID_OUT_DATA_SIZE);
475 if (hid->read_buf == NULL)
476 {
477 usb_err("Malloc failed!\n");
478 goto errout;
479 }
480
481 /* Initialize the interrupt input endpoint */
482
483 ep = DEV_ALLOCEP(dev, g_fhid_in_ep_desc.bEndpointAddress, (struct usb_endpoint_descriptor *)&g_fhid_in_ep_desc);
484 if (ep == NULL)
485 {
486 goto errout;
487 }
488
489 (void)memset_s(&hid->inputreq, sizeof(struct usbdev_req_s), 0, sizeof(struct usbdev_req_s));
490 hid->inputreq.callback = fhid_input_req_complete;
491 hid->inputreq.priv = (void *)hid;
492 hid->inputreq.buf = NULL;
493 ep->priv = (void *)hid;
494 ep->handle_req = &hid->inputreq;
495 hid->in_ep = ep;
496 devinfo->epno[1] = ep->eplog;
497
498 /* Registered character device */
499
500 ret = hid_fops_init(hid);
501 if (ret != LOS_OK)
502 {
503 goto errout;
504 }
505
506 return 0;
507 errout:
508 (void)usbclass_hid_unbind(driver, dev);
509 return -1;
510 }
511
usbclass_hid_unbind(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)512 static int usbclass_hid_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
513 {
514 struct composite_dev_s *cdev;
515 struct composite_devobj_s *devobj;
516 struct usbdev_devinfo_s *devinfo;
517 struct hid_driver_s *drvr;
518 struct hid_dev_s *hid;
519
520 if (driver == NULL || dev == NULL)
521 {
522 return -1;
523 }
524
525 drvr = (struct hid_driver_s *)driver;
526 hid = drvr->dev;
527
528 if (atomic_read(&hid->open_flag))
529 {
530 usb_err("HID device is busy!\n");
531 return -1;
532 }
533
534 (void)hid_fops_deinit(hid);
535
536 usbclass_hid_disconnect(driver, dev);
537
538 /* Destroy read event */
539
540 (VOID)LOS_EventDestroy(&hid->read_event);
541 if (hid->read_buf != NULL)
542 {
543 free(hid->read_buf);
544 hid->read_buf = NULL;
545 }
546
547 fhid_source_free(hid, dev);
548
549 cdev = dev->ep0->priv;
550 devobj = usbclass_devobj_get(cdev, DEV_HID);
551 if (devobj == NULL)
552 {
553 return -1;
554 }
555 devinfo = &devobj->compdesc.devinfo;
556 (void)memset_s(devinfo, sizeof(struct usbdev_devinfo_s), 0, sizeof(struct usbdev_devinfo_s));
557
558 return 0;
559 }
560
usbclass_hid_set_endpoint(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)561 static void usbclass_hid_set_endpoint(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
562 {
563 struct usbdev_req_s *req;
564 struct hid_driver_s *drvr;
565 struct hid_dev_s *hid;
566 int ret;
567
568 drvr = (struct hid_driver_s *)driver;
569 hid = drvr->dev;
570
571 hid->busy_flag = 0;
572 if (hid->in_ep_enabled == true)
573 {
574 (void)EP_DISABLE(hid->in_ep);
575 hid->in_ep_enabled = false;
576 }
577
578 ret = EP_CONFIGURE(hid->in_ep, (const usb_endpoint_descriptor_t *)&g_fhid_in_ep_desc, 0);
579 if (ret < 0)
580 {
581 usb_err("Config interrupt in_ep failed!\n");
582 goto errout;
583 }
584 hid->in_ep_enabled = true;
585
586 if (hid->out_ep_enabled == true)
587 {
588 (void)EP_DISABLE(hid->out_ep);
589 hid->out_ep_enabled = false;
590 }
591
592 ret = EP_CONFIGURE(hid->out_ep, (const usb_endpoint_descriptor_t *)&g_fhid_out_ep_desc, 0);
593 if (ret < 0)
594 {
595 usb_err("Config interrupt out_ep failed!\n");
596 goto errout;
597 }
598 hid->out_ep_enabled = true;
599
600 req = hid->out_ep->handle_req;
601 req->buf = (uint8_t *)hid->read_buf;
602 req->len = HID_OUT_DATA_SIZE;
603 ret = EP_SUBMIT(hid->out_ep, req);
604 if (ret != OK)
605 {
606 usb_err("out_ep submit failed!\n");
607 goto errout;
608 }
609
610 return;
611
612 errout:
613 usbclass_hid_disconnect(driver, dev);
614 }
615
usbclass_hid_get_report(struct usbdev_s * dev,uint32_t len)616 static void usbclass_hid_get_report(struct usbdev_s *dev, uint32_t len)
617 {
618 struct usbdev_req_s *req = dev->ep0->handle_req;
619 errno_t ret;
620
621 ret = memcpy_s(req->buf, USB_COMP_EP0_BUFSIZ,
622 g_fhid_report_desc.report_desc, g_fhid_report_desc.report_size);
623 if (ret != EOK)
624 {
625 usb_err("memcpy fail\n");
626 return;
627 }
628
629 req->len = MIN(len, g_fhid_report_desc.report_size);
630 }
631
usbclass_hid_setup(struct usbdevclass_driver_s * driver,struct usbdev_s * dev,const struct usb_device_request * ctrl,uint8_t * dataout,size_t outlen)632 static int usbclass_hid_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
633 const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen)
634 {
635 uint8_t req_type;
636 uint16_t w_value;
637 struct hid_dev_s *hid;
638 struct hid_driver_s *drvr;
639 struct usbdev_req_s *req;
640 int ret;
641 int new_req = 0;
642
643 (void)dataout; (void)outlen;
644
645 if (dev == NULL || driver == NULL || ctrl == NULL)
646 {
647 return -1;
648 }
649
650 drvr = (struct hid_driver_s *)driver;
651 hid = drvr->dev;
652 if (hid == NULL)
653 {
654 return -1;
655 }
656
657 w_value = UGETW(ctrl->wValue);
658 req = dev->ep0->handle_req;
659 req_type = ctrl->bmRequestType;
660 req->priv = hid;
661
662 if (UT_GET_TYPE(req_type) == UT_STANDARD)
663 {
664 switch (ctrl->bRequest)
665 {
666 case USB_REQ_SET_CONFIGURATION:
667 case USB_REQ_SET_INTERFACE:
668 usbclass_hid_set_endpoint(driver, dev);
669 break;
670
671 case UR_GET_HID_DESCRIPTOR:
672 {
673 if ((w_value >> 8) == UDESC_REPORT)
674 {
675 usbclass_hid_get_report(dev, UGETW(ctrl->wLength));
676 new_req = 1;
677 }
678 }
679 break;
680
681 default:
682 break;
683 }
684 }
685 else
686 {
687 switch (ctrl->bRequest)
688 {
689 case UR_SET_IDLE:
690 {
691 req->len = 0;
692 new_req = 1;
693 }
694 break;
695
696 case UR_SET_REPORT:
697 {
698 req->len = MIN(UGETW(ctrl->wLength), HID_IN_DATA_SIZE);
699 ret = memset_s(req->buf, req->len, 0, req->len);
700 if (ret != EOK)
701 {
702 usb_err("memset fail!\n");
703 return -1;
704 }
705 new_req = 1;
706 }
707 break;
708
709 case UR_GET_IDLE:
710 {
711 req->len = 0;
712 new_req = 1;
713 }
714 break;
715
716 case UR_GET_REPORT:
717 {
718 req->len = MIN(UGETW(ctrl->wLength), HID_IN_DATA_SIZE);
719 ret = memset_s(req->buf, req->len, 0, req->len);
720 if (ret != EOK)
721 {
722 usb_err("memset fail!\n");
723 return -1;
724 }
725 new_req = 1;
726 }
727 break;
728
729 default:
730 break;
731 }
732 }
733
734 if (new_req)
735 {
736 ret = EP_SUBMIT(dev->ep0, req);
737 if (ret != OK)
738 {
739 usb_err("Endpoint send fail!\n");
740 req->result = 0;
741 return -1;
742 }
743 }
744 return 0;
745 }
746
usbclass_hid_disconnect(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)747 static void usbclass_hid_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
748 {
749 struct hid_driver_s *hid_drvr;
750 struct hid_dev_s *hid_dev;
751
752 (void)dev;
753
754 hid_drvr = (struct hid_driver_s *)driver;
755 hid_dev = hid_drvr->dev;
756 if (hid_dev == NULL)
757 {
758 return;
759 }
760
761 if (hid_dev->in_ep_enabled == true)
762 {
763 (void)EP_DISABLE(hid_dev->in_ep);
764 hid_dev->in_ep_enabled = false;
765 }
766
767 if (hid_dev->out_ep_enabled == true)
768 {
769 (void)EP_DISABLE(hid_dev->out_ep);
770 hid_dev->out_ep_enabled = false;
771 }
772 }
773
linkg_fhid_descriptors(const uint8_t * prefer,uint16_t ps,uint16_t * total_size)774 static uint8_t *linkg_fhid_descriptors(const uint8_t *prefer, uint16_t ps, uint16_t *total_size)
775 {
776 int i;
777 uint8_t *des;
778 uint8_t *pdes;
779 uint16_t ds = 0;
780 errno_t ret;
781
782 (void)prefer;
783 (void)ps;
784
785 /* Add the length of descriptors one by one */
786
787 for (i = 0; g_fhid_desc_array[i] != NULL; ++i)
788 {
789 ds += (uint16_t)(*g_fhid_desc_array[i]);
790 }
791
792 if (total_size != NULL)
793 {
794 *total_size = ds;
795 }
796
797 des = memalign(64, SKB_DATA_ALIGN(ds));
798 if (des == NULL)
799 {
800 usb_err("System out of memory! Descriptors length: %u\n", ds);
801 return NULL;
802 }
803 (void)memset_s((void *)des, SKB_DATA_ALIGN(ds), 0, SKB_DATA_ALIGN(ds));
804
805 pdes = des;
806
807 /* configuration descriptor needs to have the full length of rest of descriptors */
808
809 USETW(g_fhid_config_desc.wTotalLength, ds);
810
811 for (i = 0; g_fhid_desc_array[i] != NULL; ++i)
812 {
813 const uint8_t *des_src = g_fhid_desc_array[i];
814 uint8_t des_len = *des_src;
815 ret = memcpy_s(pdes, SKB_DATA_ALIGN(ds), des_src, des_len);
816 if (ret != EOK)
817 {
818 usb_err("memcpy fail!\n");
819 free(des);
820 return NULL;
821 }
822 pdes += des_len;
823 }
824
825 return des;
826 }
827
hid_mkdevdesc(uint8_t * buf)828 static void hid_mkdevdesc(uint8_t *buf)
829 {
830 errno_t ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_fhid_device_desc, sizeof(g_fhid_device_desc));
831 if (ret != EOK)
832 {
833 usb_err("memcpy_s fail!, ret:%d\n", ret);
834 return;
835 }
836 }
837
hid_mkcfgdesc(uint8_t * buf,struct usbdev_devinfo_s * devinfo)838 static int16_t hid_mkcfgdesc(uint8_t *buf, struct usbdev_devinfo_s *devinfo)
839 {
840 uint16_t total_len;
841 uint8_t *des;
842 errno_t ret;
843
844 (void)devinfo;
845
846 USETW(g_fhid_desc.descrs[0].wDescriptorLength, g_fhid_report_desc.report_size);
847
848 des = linkg_fhid_descriptors(NULL, 0, &total_len);
849 if (des != NULL)
850 {
851 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, des, total_len);
852 if (ret != EOK)
853 {
854 usb_err("memcpy_s fail!, ret:%d\n", ret);
855 free(des);
856 return 0;
857 }
858 free(des);
859 }
860
861 return (int16_t)total_len;
862 }
863
hid_mkstrdesc(uint8_t id,uint8_t * buf)864 static int hid_mkstrdesc(uint8_t id, uint8_t *buf)
865 {
866 errno_t ret;
867 const char *str;
868 int i;
869
870 for (i = 0; g_fhid_device_strings[i].s != NULL; i++)
871 {
872 str = g_fhid_device_strings[i].s;
873 if (g_fhid_device_strings[i].id == id)
874 {
875 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, (const void *)str, (uint32_t)str[0]);
876 if (ret != EOK)
877 {
878 usb_err("memcpy_s failed, ret = %d\n", ret);
879 return -1;
880 }
881 return str[0];
882 }
883 }
884
885 usb_err("Can not find the id = %u of string\n", id);
886 return -1;
887 }
888
889 #define HID_NCONFIGS 1
890 #define HID_CONFIGID 0
891 #define HID_NINTERFACES 1
892 #define HID_NSTRIDS 5
893 #define HID_NUM_EPS 2
hid_get_composite_devdesc(struct composite_devdesc_s * dev)894 static void hid_get_composite_devdesc(struct composite_devdesc_s *dev)
895 {
896 (void)memset_s(dev, sizeof(struct composite_devdesc_s), 0, sizeof(struct composite_devdesc_s));
897
898 dev->mkdevdesc = hid_mkdevdesc;
899 dev->mkconfdesc = hid_mkcfgdesc;
900 dev->mkstrdesc = hid_mkstrdesc;
901
902 dev->nconfigs = HID_NCONFIGS; /* Number of configurations supported */
903 dev->configid = HID_CONFIGID; /* The only supported configuration ID */
904
905 /* Interfaces.
906 *
907 * ifnobase must be provided by board-specific logic
908 */
909
910 dev->devinfo.ninterfaces = HID_NINTERFACES; /* Number of interfaces in the configuration */
911
912 /* Strings.
913 *
914 * strbase must be provided by board-specific logic
915 */
916
917 dev->devinfo.nstrings = HID_NSTRIDS; /* Number of Strings */
918
919 /* Endpoints.
920 *
921 * Endpoint numbers must be provided by board-specific logic.
922 */
923
924 dev->devinfo.nendpoints = HID_NUM_EPS;
925 }
926
hid_classobject(int minor,struct usbdev_devinfo_s * devinfo,struct usbdevclass_driver_s ** classdev)927 static int hid_classobject(int minor, struct usbdev_devinfo_s *devinfo,
928 struct usbdevclass_driver_s **classdev)
929 {
930 struct hid_softc *hid_s;
931 struct hid_dev_s *priv;
932 struct hid_driver_s *drvr;
933
934 (void)minor;
935 (void)devinfo;
936
937 /* Allocate the structures needed */
938
939 hid_s = (struct hid_softc *)malloc(sizeof(struct hid_softc));
940 if (hid_s == NULL)
941 {
942 return -1;
943 }
944
945 /* Convenience pointers into the allocated blob */
946
947 priv = &hid_s->dev;
948 drvr = &hid_s->drvr;
949
950 /* Initialize the USB serial driver structure */
951
952 (void)memset_s(priv, sizeof(struct hid_dev_s), 0, sizeof(struct hid_dev_s));
953
954 /* Initialize the USB class driver structure */
955
956 drvr->drvr.speed = USB_SPEED_HIGH;
957 drvr->drvr.ops = &g_hid_driverops;
958 drvr->dev = priv;
959
960 *classdev = &drvr->drvr;
961 return 0;
962 }
963
hid_uninitialize(struct usbdevclass_driver_s * classdev)964 static void hid_uninitialize(struct usbdevclass_driver_s *classdev)
965 {
966 struct hid_driver_s *hid_drvr = (struct hid_driver_s *)classdev;
967 struct hid_dev_s *priv;
968 struct hid_softc *hid_s;
969
970 usbdev_hid_free();
971
972 if (hid_drvr == NULL)
973 {
974 return;
975 }
976
977 priv = hid_drvr->dev;
978 if (priv == NULL)
979 {
980 return;
981 }
982
983 hid_s = container_of(hid_drvr, struct hid_softc, drvr);
984 if (hid_s != NULL)
985 {
986 free(hid_s);
987 }
988 }
989
usbdev_hid_initialize_sub(struct composite_devdesc_s * dev,int ifnobase,int minor)990 static void usbdev_hid_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor)
991 {
992 /* Ask the HID driver to fill in the constants we didn't
993 * know here.
994 */
995
996 hid_get_composite_devdesc(dev);
997
998 /* Overwrite and correct some values. */
999
1000 /* The callback functions for the HID class */
1001
1002 dev->classobject = hid_classobject;
1003 dev->uninitialize = hid_uninitialize;
1004
1005 /* Interfaces */
1006
1007 dev->devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */
1008 dev->minor = minor; /* The minor interface number */
1009
1010 /* Strings */
1011
1012 dev->devinfo.strbase = 0; /* Offset to String Numbers */
1013 }
1014
usbdev_hid_initialize(struct module * mod,int n,void * arg)1015 int usbdev_hid_initialize(struct module *mod, int n, void *arg)
1016 {
1017 struct composite_softc *com_s = (struct composite_softc *)arg;
1018 struct composite_devdesc_s dev;
1019 int ret;
1020
1021 (void)mod;
1022 (void)n;
1023 if (com_s == NULL)
1024 {
1025 return -1;
1026 }
1027
1028 usbdev_hid_initialize_sub(&dev, 0, DEV_HID);
1029
1030 ret = composite_initialize(com_s, 1, &dev);
1031 if (ret < 0)
1032 {
1033 return -1;
1034 }
1035
1036 PRINTK(" ** hid device initialized successfully! **\n");
1037 return 0;
1038 }
1039
1040 #ifdef __cplusplus
1041 #if __cplusplus
1042 }
1043 #endif /* __cplusplus */
1044 #endif /* __cplusplus */