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 */