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