/* ---------------------------------------------------------------------------- * Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved. * Description: LiteOS USB Driver HID Protocol HeadFile * Author: Yannik Li * Create: 2021-02-04 * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------- * Notice of Export Control Law * =============================================== * Huawei LiteOS may be subject to applicable export control laws and regulations, which might * include those applicable to Huawei LiteOS of U.S. and the country in which you are located. * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such * applicable export control laws and regulations. * --------------------------------------------------------------------------- */ #ifndef _F_GENERIC_GADGET_H #define _F_GENERIC_GADGET_H #include "usb_obj.h" #include "gadget/usbdev.h" #include "gadget/composite.h" #ifdef __cplusplus #if __cplusplus //extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ /* Define usb generic function gadget path. */ #define USB_GENERIC_DEV "/dev/generic" #define GENERIC_IOC_MAGIC 'g' #define GENERIC_CMD_FREE_MEM _IO(GENERIC_IOC_MAGIC, 1) #define GENERIC_CMD_CANCEL_REQUEST _IO(GENERIC_IOC_MAGIC, 2) #define GENERIC_CMD_GET_PIPE_INFO _IO(GENERIC_IOC_MAGIC, 3) #define GENERIC_CMD_GET_EP0_EVENT _IO(GENERIC_IOC_MAGIC, 4) #define GENERIC_CMD_ENDPOINT_IO _IO(GENERIC_IOC_MAGIC, 5) #define GENERIC_CMD_GET_REQ_STATUS _IO(GENERIC_IOC_MAGIC, 6) #define USB_GENERIC_EVENTS_NUM 4 #define USB_GENERIC_COMPLETE_EVENT (1 << 0) #define USB_GENERIC_EP0_EVENT (1 << 0) struct event_fifo { uint32_t in; uint32_t out; uint8_t data[USB_GENERIC_EVENTS_NUM]; }; enum generic_state { /* * Waiting for descriptors and strings. */ GENERIC_READ_DESCRIPTORS, GENERIC_READ_STRINGS, /* * We've got descriptors and strings. */ GENERIC_ACTIVE, /* * Function is deactived, all epfiles, except ep0, are deleted * so there is no way to perform any operations on them. */ GENERIC_DEACTIVATED, /* * All endpoints have been closed. */ GENERIC_CLOSING }; enum generic_setup_state { /* There is no setup request pending. */ GENERIC_NO_SETUP, /* * There was a setup request event there, the request * will be handled on the next read/write on ep0. */ GENERIC_SETUP_PENDING, /* * The existing event was canceled. */ GENERIC_SETUP_CANCELLED }; struct generic_memory { size_t size; size_t buf; char storage[]; }; struct IoData { uint32_t aio; /* 0 for sync ,1 for async */ uint32_t read; /* 0 for write ,1 for read */ uint32_t len; /* the len of this io request */ uint32_t timeout; /* sync timeout */ uint32_t buf; /* the address of map buf */ }; struct generic_ep { struct usbdev_ep_s *ep; struct usbdev_req_s *req; EVENT_CB_S event; /* [0]: full speed, [1]: high speed, [2]: super speed */ usb_endpoint_descriptor_t *descs[3]; uint8_t num; int status; void *priv; }; struct usb_memory { struct usb_obj obj; unsigned long mem; unsigned long vm_start; uint32_t size; atomic_t usage; }; struct generic_strings { uint16_t language; struct usbd_string *strings; }; struct generic_dev_s { struct usb_obj obj; struct usbdev_s *usbdev; struct generic_driver_s *drvr; const char *name; int minor; int minor_offset; pthread_mutex_t mutex; struct usbdev_devinfo_s *devinfo; struct list_head ep0_comp_list; struct list_head ep0_req_list; bool inuse; bool desc_ready; bool eps_enbale; /* the number of files are opened (EP0 and others) */ atomic_t opened; /* EP0 state */ enum generic_state state; enum generic_setup_state setup_state; struct usb_device_request setup; uint16_t ep0_can_stall; struct event_fifo efifo; EVENT_CB_S ep0_event; spinlock_t event_lock; struct usb_obj memory_obj; struct usbdev_req_s *ctrlreq; EVENT_CB_S ctrlreq_event; uint32_t event_mask; EVENT_CB_S ep_event_all; uint32_t cur_buff; /* Flags */ unsigned long flags; const void *raw_descs_data; const void *raw_descs; uint32_t raw_descs_length; uint32_t fs_descs_count; uint32_t hs_descs_count; uint32_t ss_descs_count; uint32_t fs_descs_len; uint32_t hs_descs_len; uint32_t ss_descs_len; uint32_t descs_flags; uint32_t strings_count; uint32_t lang_count; const void *raw_strings; struct generic_strings *dev_strings; #define GENERIC_MAX_EPS_COUNT 31 uint8_t eps_addrmap[GENERIC_MAX_EPS_COUNT]; usb_endpoint_descriptor_t *eps_descs[GENERIC_MAX_EPS_COUNT][3]; uint8_t speed; spinlock_t eps_lock; spinlock_t ep0_lock; struct generic_ep *eps; uint8_t eps_revmap[16]; uint32_t alt_setting; uint16_t interfaces_count; uint16_t eps_count; struct usb_obj epfiles_obj; }; struct generic_driver_s { struct usbdevclass_driver_s drvr; struct generic_dev_s *dev; }; struct generic_softc { struct generic_dev_s dev; struct generic_driver_s drvr; }; static inline void event_fifo_reset(struct event_fifo *efifo) { efifo->in = efifo->out = 0; } static inline bool event_fifo_len(struct event_fifo *efifo) { return efifo->in - efifo->out; } static inline bool event_fifo_is_empty(struct event_fifo *efifo) { return efifo->in == efifo->out; } static inline bool event_fifo_is_full(struct event_fifo *efifo) { uint32_t mask = USB_GENERIC_EVENTS_NUM - 1; return event_fifo_len(efifo) > (mask); } static inline int event_fifo_put(struct event_fifo *efifo, uint8_t event) { int ret = !event_fifo_is_full(efifo); if (ret) { uint32_t mask = USB_GENERIC_EVENTS_NUM - 1; efifo->data[efifo->in & mask] = event; efifo->in++; } return ret; } static inline int event_fifo_get(struct event_fifo *efifo, uint8_t *event) { int ret = !event_fifo_is_empty(efifo); if (ret) { uint32_t mask = USB_GENERIC_EVENTS_NUM - 1; *event = efifo->data[efifo->out & mask]; efifo->out++; } return ret; } extern int usbdev_generic_alloc_instance(const char *name); extern int usbdev_generic_free_instance(const char *name); extern void usbdev_generic_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor); extern void generic_dev_closed(struct generic_dev_s *dev); extern void generic_dev_opened(struct generic_dev_s *dev); #ifdef __cplusplus #if __cplusplus //} #endif /* __cplusplus */ #endif /* __cplusplus */ #endif /* _F_GENERIC_GADGET_H */