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
47extern "C" {
48#endif /* __cplusplus */
49#endif /* __cplusplus */
50
51int usbdev_hid_initialize(struct module *mod, int n, void *arg);
52
53/* device driver structure definition */
54
55static 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
64static devclass_t g_fhid_devclass;
65DRIVER_MODULE(fhid, simple, g_fhid_driver, g_fhid_devclass, usbdev_hid_initialize, 0);
66
67static int usbclass_hid_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
68static int usbclass_hid_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
69static 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);
71static void usbclass_hid_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
72
73/* USB driver operations */
74
75static 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
85static 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
92static 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
100static 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
108struct 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
118static 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
134static 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
146static 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
159static 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
173static 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
183static 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
193const 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
203void 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
210int 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
269errout:
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
280int 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
307static 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
327static 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
368static 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
410static 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
419static 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;
507errout:
508  (void)usbclass_hid_unbind(driver, dev);
509  return -1;
510}
511
512static 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
561static 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
612errout:
613  usbclass_hid_disconnect(driver, dev);
614}
615
616static 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
632static 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
747static 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
774static 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
828static 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
838static 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
864static 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
894static 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
927static 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
964static 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
990static 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
1015int 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 */