commit 71bdf968d1040d6fba03287220c4dfe3a01ad1e8 Author: Villuton Date: Mon Oct 27 16:28:59 2025 +0300 Init diff --git a/inc/usb_std.h b/inc/usb_std.h new file mode 100644 index 0000000..f8f5c0c --- /dev/null +++ b/inc/usb_std.h @@ -0,0 +1,402 @@ +/** + ************************************************************************** + * @file usb_std.h + * @brief usb standard header file + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ + +/* define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_STD_H +#define __USB_STD_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* includes ------------------------------------------------------------------*/ +#include "usb_conf.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @addtogroup USB_standard + * @{ + */ + +/** @defgroup USB_standard_define + * @{ + */ + +/** + * @brief usb request recipient + */ +#define USB_REQ_RECIPIENT_DEVICE 0x00 /*!< usb request recipient device */ +#define USB_REQ_RECIPIENT_INTERFACE 0x01 /*!< usb request recipient interface */ +#define USB_REQ_RECIPIENT_ENDPOINT 0x02 /*!< usb request recipient endpoint */ +#define USB_REQ_RECIPIENT_OTHER 0x03 /*!< usb request recipient other */ +#define USB_REQ_RECIPIENT_MASK 0x1F /*!< usb request recipient mask */ + +/** + * @brief usb request type + */ +#define USB_REQ_TYPE_STANDARD 0x00 /*!< usb request type standard */ +#define USB_REQ_TYPE_CLASS 0x20 /*!< usb request type class */ +#define USB_REQ_TYPE_VENDOR 0x40 /*!< usb request type vendor */ +#define USB_REQ_TYPE_RESERVED 0x60 /*!< usb request type reserved */ + +/** + * @brief usb request data transfer direction + */ +#define USB_REQ_DIR_HTD 0x00 /*!< usb request data transfer direction host to device */ +#define USB_REQ_DIR_DTH 0x80 /*!< usb request data transfer direction device to host */ + +/** + * @brief usb standard device requests codes + */ +#define USB_STD_REQ_GET_STATUS 0 /*!< usb request code status */ +#define USB_STD_REQ_CLEAR_FEATURE 1 /*!< usb request code clear feature */ +#define USB_STD_REQ_SET_FEATURE 3 /*!< usb request code feature */ +#define USB_STD_REQ_SET_ADDRESS 5 /*!< usb request code address */ +#define USB_STD_REQ_GET_DESCRIPTOR 6 /*!< usb request code get descriptor */ +#define USB_STD_REQ_SET_DESCRIPTOR 7 /*!< usb request code set descriptor */ +#define USB_STD_REQ_GET_CONFIGURATION 8 /*!< usb request code get configuration */ +#define USB_STD_REQ_SET_CONFIGURATION 9 /*!< usb request code set configuration */ +#define USB_STD_REQ_GET_INTERFACE 10 /*!< usb request code get interface */ +#define USB_STD_REQ_SET_INTERFACE 11 /*!< usb request code set interface */ +#define USB_STD_REQ_SYNCH_FRAME 12 /*!< usb request code synch frame */ + +/** + * @brief usb standard device type + */ +#define USB_DESCIPTOR_TYPE_DEVICE 1 /*!< usb standard device type device */ +#define USB_DESCIPTOR_TYPE_CONFIGURATION 2 /*!< usb standard device type configuration */ +#define USB_DESCIPTOR_TYPE_STRING 3 /*!< usb standard device type string */ +#define USB_DESCIPTOR_TYPE_INTERFACE 4 /*!< usb standard device type interface */ +#define USB_DESCIPTOR_TYPE_ENDPOINT 5 /*!< usb standard device type endpoint */ +#define USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER 6 /*!< usb standard device type qualifier */ +#define USB_DESCIPTOR_TYPE_OTHER_SPEED 7 /*!< usb standard device type other speed */ +#define USB_DESCIPTOR_TYPE_INTERFACE_POWER 8 /*!< usb standard device type interface power */ + +/** + * @brief usb standard string type + */ +#define USB_LANGID_STRING 0 /*!< usb standard string type lang id */ +#define USB_MFC_STRING 1 /*!< usb standard string type mfc */ +#define USB_PRODUCT_STRING 2 /*!< usb standard string type product */ +#define USB_SERIAL_STRING 3 /*!< usb standard string type serial */ +#define USB_CONFIG_STRING 4 /*!< usb standard string type config */ +#define USB_INTERFACE_STRING 5 /*!< usb standard string type interface */ +#define USB_WINUSB_OS_STRING 0xEE /*!< usb microsoft os string */ + +/** + * @brief usb configuration attributes + */ +#define USB_CONF_REMOTE_WAKEUP 2 /*!< usb configuration attributes remote wakeup */ +#define USB_CONF_SELF_POWERED 1 /*!< usb configuration attributes self powered */ + +/** + * @brief usb standard feature selectors + */ +#define USB_FEATURE_EPT_HALT 0 /*!< usb standard feature selectors endpoint halt */ +#define USB_FEATURE_REMOTE_WAKEUP 1 /*!< usb standard feature selectors remote wakeup */ +#define USB_FEATURE_TEST_MODE 2 /*!< usb standard feature selectors test mode */ + +/** + * @brief usb winusb feature id + */ +#define USB_WINUSB_COMPAT_ID 0x04 /*!< usb winusb compat id os descriptor */ +#define USB_WINUSB_PROPERTIES_ID 0x05 /*!< usb winusb properties id os descriptor */ + +/** + * @brief usb device connect state + */ +typedef enum +{ + USB_CONN_STATE_DEFAULT =1, /*!< usb device connect state default */ + USB_CONN_STATE_ADDRESSED, /*!< usb device connect state address */ + USB_CONN_STATE_CONFIGURED, /*!< usb device connect state configured */ + USB_CONN_STATE_SUSPENDED /*!< usb device connect state suspend */ +}usbd_conn_state; + +/** + * @brief endpoint 0 state + */ +#define USB_EPT0_IDLE 0 /*!< usb endpoint state idle */ +#define USB_EPT0_SETUP 1 /*!< usb endpoint state setup */ +#define USB_EPT0_DATA_IN 2 /*!< usb endpoint state data in */ +#define USB_EPT0_DATA_OUT 3 /*!< usb endpoint state data out */ +#define USB_EPT0_STATUS_IN 4 /*!< usb endpoint state status in */ +#define USB_EPT0_STATUS_OUT 5 /*!< usb endpoint state status out */ +#define USB_EPT0_STALL 6 /*!< usb endpoint state stall */ + +/** + * @brief usb descriptor length + */ +#define USB_DEVICE_QUALIFIER_DESC_LEN 0x0A /*!< usb qualifier descriptor length */ +#define USB_DEVICE_DESC_LEN 0x12 /*!< usb device descriptor length */ +#define USB_DEVICE_CFG_DESC_LEN 0x09 /*!< usb configuration descriptor length */ +#define USB_DEVICE_IF_DESC_LEN 0x09 /*!< usb interface descriptor length */ +#define USB_DEVICE_EPT_LEN 0x07 /*!< usb endpoint descriptor length */ +#define USB_DEVICE_OTG_DESC_LEN 0x03 /*!< usb otg descriptor length */ +#define USB_DEVICE_LANGID_STR_DESC_LEN 0x04 /*!< usb lang id string descriptor length */ +#define USB_DEVICE_OTHER_SPEED_DESC_SIZ_LEN 0x09 /*!< usb other speed descriptor length */ + +/** + * @brief usb class code + */ +#define USB_CLASS_CODE_AUDIO 0x01 /*!< usb class code audio */ +#define USB_CLASS_CODE_CDC 0x02 /*!< usb class code cdc */ +#define USB_CLASS_CODE_HID 0x03 /*!< usb class code hid */ +#define USB_CLASS_CODE_PRINTER 0x07 /*!< usb class code printer */ +#define USB_CLASS_CODE_MSC 0x08 /*!< usb class code msc */ +#define USB_CLASS_CODE_HUB 0x09 /*!< usb class code hub */ +#define USB_CLASS_CODE_CDCDATA 0x0A /*!< usb class code cdc data */ +#define USB_CLASS_CODE_CCID 0x0B /*!< usb class code ccid */ +#define USB_CLASS_CODE_VIDEO 0x0E /*!< usb class code video */ +#define USB_CLASS_CODE_VENDOR 0xFF /*!< usb class code vendor */ + +/** + * @brief usb endpoint type + */ +#define USB_EPT_DESC_CONTROL 0x00 /*!< usb endpoint description type control */ +#define USB_EPT_DESC_ISO 0x01 /*!< usb endpoint description type iso */ +#define USB_EPT_DESC_BULK 0x02 /*!< usb endpoint description type bulk */ +#define USB_EPT_DESC_INTERRUPT 0x03 /*!< usb endpoint description type interrupt */ + +#define USB_EPT_DESC_NSYNC 0x00 /*!< usb endpoint description nsync */ +#define USB_ETP_DESC_ASYNC 0x04 /*!< usb endpoint description async */ +#define USB_ETP_DESC_ADAPTIVE 0x08 /*!< usb endpoint description adaptive */ +#define USB_ETP_DESC_SYNC 0x0C /*!< usb endpoint description sync */ + +#define USB_EPT_DESC_DATA_EPT 0x00 /*!< usb endpoint description data */ +#define USB_EPT_DESC_FD_EPT 0x10 /*!< usb endpoint description fd */ +#define USB_EPT_DESC_FDDATA_EPT 0x20 /*!< usb endpoint description fddata */ + +/** + * @brief usb cdc class descriptor define + */ +#define USBD_CDC_CS_INTERFACE 0x24 +#define USBD_CDC_CS_ENDPOINT 0x25 + +/** + * @brief usb cdc class sub-type define + */ +#define USBD_CDC_SUBTYPE_HEADER 0x00 +#define USBD_CDC_SUBTYPE_CMF 0x01 +#define USBD_CDC_SUBTYPE_ACM 0x02 +#define USBD_CDC_SUBTYPE_UFD 0x06 + +/** + * @brief usb cdc class request code define + */ +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 + +/** + * @brief usb cdc class set line coding struct + */ +typedef struct +{ + uint32_t bitrate; /* line coding baud rate */ + uint8_t format; /* line coding foramt */ + uint8_t parity; /* line coding parity */ + uint8_t data; /* line coding data bit */ +}linecoding_type; + +/** + * @brief usb hid class descriptor define + */ +#define HID_CLASS_DESC_HID 0x21 +#define HID_CLASS_DESC_REPORT 0x22 +#define HID_CLASS_DESC_PHYSICAL 0x23 + +/** + * @brief usb hid class request code define + */ +#define HID_REQ_SET_PROTOCOL 0x0B +#define HID_REQ_GET_PROTOCOL 0x03 +#define HID_REQ_SET_IDLE 0x0A +#define HID_REQ_GET_IDLE 0x02 +#define HID_REQ_SET_REPORT 0x09 +#define HID_REQ_GET_REPORT 0x01 +#define HID_DESCRIPTOR_TYPE 0x21 +#define HID_REPORT_DESC 0x22 + +/** + * @brief endpoint 0 max size + */ +#define USB_MAX_EP0_SIZE 64 /*!< usb endpoint 0 max size */ + +/** + * @brief usb swap address + */ +#define SWAPBYTE(addr) (uint16_t)(((uint16_t)(*((uint8_t *)(addr)))) + \ + (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) /*!< swap address */ + +/** + * @brief min and max define + */ +#ifndef MIN +#define MIN(a, b) (uint16_t)(((a) < (b)) ? (a) : (b)) /*!< min define*/ +#endif + +#ifndef MAX +#define MAX(a, b) (uint16_t)(((a) > (b)) ? (a) : (b)) /*!< max define*/ +#endif + +/** + * @brief low byte and high byte define + */ +#define LBYTE(x) ((uint8_t)(x & 0x00FF)) /*!< low byte define */ +#define HBYTE(x) ((uint8_t)((x & 0xFF00) >>8)) /*!< high byte define*/ + +/** + * @} + */ + +/** @defgroup USB_standard_exported_types + * @{ + */ + +/** + * @brief usb return status + */ +typedef enum +{ + USB_OK, /*!< usb status ok */ + USB_FAIL, /*!< usb status fail */ + USB_WAIT, /*!< usb status wait */ + USB_NOT_SUPPORT, /*!< usb status not support */ + USB_ERROR, /*!< usb status error */ +}usb_sts_type; + +/** + * @brief format of usb setup data + */ +typedef struct +{ + uint8_t bmRequestType; /*!< characteristics of request */ + uint8_t bRequest; /*!< specific request */ + uint16_t wValue; /*!< word-sized field that varies according to request */ + uint16_t wIndex; /*!< word-sized field that varies according to request + typically used to pass an index or offset */ + uint16_t wLength; /*!< number of bytes to transfer if there is a data stage */ +}usb_setup_type; + +/** + * @brief format of standard device descriptor + */ +typedef struct +{ + uint8_t bLength; /*!< size of this descriptor in bytes */ + uint8_t bDescriptorType; /*!< device descriptor type */ + uint16_t bcdUSB; /*!< usb specification release number */ + uint8_t bDeviceClass; /*!< class code (assigned by the usb-if) */ + uint8_t bDeviceSubClass; /*!< subclass code (assigned by the usb-if) */ + uint8_t bDeviceProtocol; /*!< protocol code ((assigned by the usb-if)) */ + uint8_t bMaxPacketSize0; /*!< maximum packet size for endpoint zero */ + uint16_t idVendor; /*!< verndor id ((assigned by the usb-if)) */ + uint16_t idProduct; /*!< product id ((assigned by the usb-if)) */ + uint16_t bcdDevice; /*!< device release number in binary-coded decimal */ + uint8_t iManufacturer; /*!< index of string descriptor describing manufacturer */ + uint8_t iProduct; /*!< index of string descriptor describing product */ + uint8_t iSerialNumber; /*!< index of string descriptor describing serial number */ + uint8_t bNumConfigurations; /*!< number of possible configurations */ +}usb_device_desc_type; + +/** + * @brief format of standard configuration descriptor + */ +typedef struct +{ + uint8_t bLength; /*!< size of this descriptor in bytes */ + uint8_t bDescriptorType; /*!< configuration descriptor type */ + uint16_t wTotalLength; /*!< total length of data returned for this configuration */ + uint8_t bNumInterfaces; /*!< number of interfaces supported by this configuration */ + uint8_t bConfigurationValue; /*!< value to use as an argument to the SetConfiguration() request */ + uint8_t iConfiguration; /*!< index of string descriptor describing this configuration */ + uint8_t bmAttributes; /*!< configuration characteristics + D7 reserved + D6 self-powered + D5 remote wakeup + D4~D0 reserved */ + uint8_t bMaxPower; /*!< maximum power consumption of the usb device from the bus */ + + +}usb_configuration_desc_type; + +/** + * @brief format of standard interface descriptor + */ +typedef struct +{ + uint8_t bLength; /*!< size of this descriptor in bytes */ + uint8_t bDescriptorType; /*!< interface descriptor type */ + uint8_t bInterfaceNumber; /*!< number of this interface */ + uint8_t bAlternateSetting; /*!< value used to select this alternate setting for the interface */ + uint8_t bNumEndpoints; /*!< number of endpoints used by this interface */ + uint8_t bInterfaceClass; /*!< class code (assigned by the usb-if) */ + uint8_t bInterfaceSubClass; /*!< subclass code (assigned by the usb-if) */ + uint8_t bInterfaceProtocol; /*!< protocol code (assigned by the usb-if) */ + uint8_t iInterface; /*!< index of string descriptor describing this interface */ +}usb_interface_desc_type; + +/** + * @brief format of standard endpoint descriptor + */ +typedef struct +{ + uint8_t bLength; /*!< size of this descriptor in bytes */ + uint8_t bDescriptorType; /*!< endpoint descriptor type */ + uint8_t bEndpointAddress; /*!< the address of the endpoint on the usb device described by this descriptor */ + uint8_t bmAttributes; /*!< describes the endpoints attributes when it is configured using bConfiguration value */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint */ + uint8_t bInterval; /*!< interval for polling endpoint for data transfers */ +}usb_endpoint_desc_type; + +/** + * @brief format of header + */ +typedef struct +{ + uint8_t bLength; /*!< size of this descriptor in bytes */ + uint8_t bDescriptorType; /*!< descriptor type */ +}usb_header_desc_type; + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/inc/usbd_core.h b/inc/usbd_core.h new file mode 100644 index 0000000..83e7323 --- /dev/null +++ b/inc/usbd_core.h @@ -0,0 +1,196 @@ +/** + ************************************************************************** + * @file usbd_core.h + * @brief usb device core header file + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ + +/* define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "usb_conf.h" +#include "usb_std.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @addtogroup USBD_drivers_core + * @{ + */ + +/** @defgroup USBD_core_exported_types + * @{ + */ + +/** + * @brief usb device event + */ +typedef enum +{ + USBD_NOP_EVENT, /*!< usb device event nop */ + USBD_RESET_EVENT, /*!< usb device event reset */ + USBD_SUSPEND_EVENT, /*!< usb device event suspend */ + USBD_WAKEUP_EVENT, /*!< usb device event wakeup */ + USBD_ERR_EVENT /*!< usb device event error */ +}usbd_event_type; + +/** + * @brief usb device descriptor struct + */ +typedef struct +{ + uint16_t length; /*!< descriptor length */ + uint8_t *descriptor; /*!< descriptor string */ +}usbd_desc_t; + +/** + * @brief usb device descriptor handler + */ +typedef struct +{ + usbd_desc_t *(*get_device_descriptor)(void); /*!< get device descriptor callback */ + usbd_desc_t *(*get_device_qualifier)(void); /*!< get device qualifier callback */ + usbd_desc_t *(*get_device_configuration)(void); /*!< get device configuration callback */ + usbd_desc_t *(*get_device_other_speed)(void); /*!< get device other speed callback */ + usbd_desc_t *(*get_device_lang_id)(void); /*!< get device lang id callback */ + usbd_desc_t *(*get_device_manufacturer_string)(void); /*!< get device manufacturer callback */ + usbd_desc_t *(*get_device_product_string)(void); /*!< get device product callback */ + usbd_desc_t *(*get_device_serial_string)(void); /*!< get device serial callback */ + usbd_desc_t *(*get_device_interface_string)(void); /*!< get device interface string callback */ + usbd_desc_t *(*get_device_config_string)(void); /*!< get device device config callback */ +#if (USBD_SUPPORT_WINUSB == 1) + usbd_desc_t *(*get_device_winusb_os_string)(void); /*!< get winusb os string */ + usbd_desc_t *(*get_device_winusb_os_feature)(void); /*!< get winusb os feature */ + usbd_desc_t *(*get_device_winusb_os_property)(void); /*!< get winusb os property */ +#endif +}usbd_desc_handler; + +/** + * @brief usb device class handler + */ +typedef struct +{ + usb_sts_type (*init_handler)(void *udev); /*!< usb class init handler */ + usb_sts_type (*clear_handler)(void *udev); /*!< usb class clear handler */ + usb_sts_type (*setup_handler)(void *udev, usb_setup_type *setup); /*!< usb class setup handler */ + usb_sts_type (*ept0_tx_handler)(void *udev); /*!< usb class endpoint 0 tx complete handler */ + usb_sts_type (*ept0_rx_handler)(void *udev); /*!< usb class endpoint 0 rx complete handler */ + usb_sts_type (*in_handler)(void *udev, uint8_t ept_num); /*!< usb class in transfer complete handler */ + usb_sts_type (*out_handler)(void *udev, uint8_t ept_num); /*!< usb class out transfer complete handler */ + usb_sts_type (*sof_handler)(void *udev); /*!< usb class sof handler */ + usb_sts_type (*event_handler)(void *udev, usbd_event_type event); /*!< usb class event handler */ + void *pdata; /*!< usb class data pointer */ +}usbd_class_handler; + +/** + * @brief usb device core struct type + */ +typedef struct +{ + usb_reg_type *usb_reg; /*!< usb register pointer */ + + usbd_class_handler *class_handler; /*!< usb device class handler pointer */ + usbd_desc_handler *desc_handler; /*!< usb device descriptor handler pointer */ + + usb_ept_info ept_in[USB_EPT_MAX_NUM]; /*!< usb in endpoint infomation struct */ + usb_ept_info ept_out[USB_EPT_MAX_NUM]; /*!< usb out endpoint infomation struct */ + + usb_setup_type setup; /*!< usb setup type struct */ + uint8_t setup_buffer[12]; /*!< usb setup request buffer */ + + uint8_t ept0_sts; /*!< usb control endpoint 0 state */ + uint8_t speed; /*!< usb speed */ + uint16_t ept0_wlength; /*!< usb endpoint 0 transfer length */ + + usbd_conn_state conn_state; /*!< usb current connect state */ + usbd_conn_state old_conn_state; /*!< usb save the previous connect state */ + + uint8_t device_addr; /*!< device address */ + uint8_t remote_wakup; /*!< remote wakeup state */ + uint8_t default_config; /*!< usb default config state */ + uint8_t dev_config; /*!< usb device config state */ + uint16_t config_status; /*!< usb configure status */ +}usbd_core_type; + +/** + * @} + */ + +/** @defgroup USBD_core_exported_functions + * @{ + */ +void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_num); +void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_num); +void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num); +void usbd_ctrl_unsupport(usbd_core_type *udev); +void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len); +void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len); +void usbd_ctrl_send_status(usbd_core_type *udev); +void usbd_ctrl_recv_status(usbd_core_type *udev); +void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr); +void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr); +void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket); +void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr); +void usbd_ept_send(usbd_core_type *udev, uint8_t ept_num, uint8_t *buffer, uint16_t len); +void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_num, uint8_t *buffer, uint16_t len); +void usbd_connect(usbd_core_type *udev); +void usbd_disconnect(usbd_core_type *udev); +void usbd_set_device_addr(usbd_core_type *udev, uint8_t address); +uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr); +usbd_conn_state usbd_connect_state_get(usbd_core_type *udev); +void usbd_ept_dbuffer_enable(usbd_core_type *udev, uint8_t ept_addr); +void usbd_ept_buf_auto_define(usb_ept_info *ept_info); +void usbd_ept_buf_custom_define( usbd_core_type *udev, uint8_t ept_addr, + uint32_t addr); +void usbd_ept_defaut_init(usbd_core_type *udev); +void usbd_remote_wakeup(usbd_core_type *udev); +void usbd_enter_suspend(usbd_core_type *udev); +void usbd_core_init(usbd_core_type *udev, + usb_reg_type *usb_reg, + usbd_class_handler *dev_handler, + usbd_desc_handler *desc_handler, + uint8_t core_id); + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/inc/usbd_int.h b/inc/usbd_int.h new file mode 100644 index 0000000..c30734d --- /dev/null +++ b/inc/usbd_int.h @@ -0,0 +1,72 @@ +/** + ************************************************************************** + * @file usb_int.h + * @brief usb header file + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ + +/* define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_INT_H +#define __USB_INT_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @addtogroup USBD_drivers_interrupt + * @{ + */ + +/** @defgroup USBD_int_exported_functions + * @{ + */ +void usbd_irq_handler(usbd_core_type *udev); +void usbd_ept_loop_handler(usbd_core_type *udev); +void usbd_eptn_handler(usbd_core_type *udev, usb_ept_number_type ept_num); +void usbd_reset_handler(usbd_core_type *udev); +void usbd_sof_handler(usbd_core_type *udev); +void usbd_suspend_handler(usbd_core_type *udev); +void usbd_wakeup_handler(usbd_core_type *udev); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/inc/usbd_sdr.h b/inc/usbd_sdr.h new file mode 100644 index 0000000..0316238 --- /dev/null +++ b/inc/usbd_sdr.h @@ -0,0 +1,72 @@ +/** + ************************************************************************** + * @file usbd_sdr.h + * @brief usb standard request header file + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ + +/* define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_SDR_H +#define __USBD_SDR_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @addtogroup USBD_drivers_standard_request + * @{ + */ + +/** @defgroup USBD_sdr_exported_functions + * @{ + */ + +void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf); +usb_sts_type usbd_device_request(usbd_core_type *udev); +usb_sts_type usbd_interface_request(usbd_core_type *udev); +usb_sts_type usbd_endpoint_request(usbd_core_type *udev); + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..94181f5 --- /dev/null +++ b/modular.json @@ -0,0 +1,10 @@ +{ + "cmake": { + "inc_dirs": [ + "inc" + ], + "srcs": [ + "src/**.c" + ] + } +} \ No newline at end of file diff --git a/src/usbd_core.c b/src/usbd_core.c new file mode 100644 index 0000000..5ac5a77 --- /dev/null +++ b/src/usbd_core.c @@ -0,0 +1,713 @@ +/** + ************************************************************************** + * @file usbd_core.c + * @brief usb driver + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ +#include "usbd_core.h" +#include "usbd_sdr.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @defgroup USBD_drivers_core + * @brief usb device drivers core + * @{ + */ + +/** @defgroup USBD_core_private_functions + * @{ + */ + +/** + * @brief usb core in transfer complete handler + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_core_in_handler(usbd_core_type *udev, uint8_t ept_addr) +{ + /* get endpoint info*/ + usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F]; + + if(ept_addr == 0) + { + if(udev->ept0_sts == USB_EPT0_DATA_IN) + { + if(ept_info->rem0_len > ept_info->maxpacket) + { + ept_info->rem0_len -= ept_info->maxpacket; + usbd_ept_send(udev, 0, ept_info->trans_buf, + MIN(ept_info->rem0_len, ept_info->maxpacket)); + } + /* endpoint 0 */ + else if(ept_info->last_len == ept_info->maxpacket + && ept_info->ept0_slen >= ept_info->maxpacket + && ept_info->ept0_slen < udev->ept0_wlength) + { + ept_info->last_len = 0; + usbd_ept_send(udev, 0, 0, 0); + usbd_ept_recv(udev, ept_addr, 0, 0); + } + else + { + + if(udev->class_handler->ept0_tx_handler != 0 && + udev->conn_state == USB_CONN_STATE_CONFIGURED) + { + udev->class_handler->ept0_tx_handler(udev); + } + usbd_ctrl_recv_status(udev); + + } + } + } + else if(udev->class_handler->in_handler != 0 && + udev->conn_state == USB_CONN_STATE_CONFIGURED) + { + /* other user define endpoint */ + udev->class_handler->in_handler(udev, ept_addr); + } +} + +/** + * @brief usb core out transfer complete handler + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_core_out_handler(usbd_core_type *udev, uint8_t ept_addr) +{ + /* get endpoint info*/ + usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F]; + + if(ept_addr == 0) + { + /* endpoint 0 */ + if(udev->ept0_sts == USB_EPT0_DATA_OUT) + { + if(ept_info->rem0_len > ept_info->maxpacket) + { + ept_info->rem0_len -= ept_info->maxpacket; + usbd_ept_recv(udev, ept_addr, ept_info->trans_buf, + MIN(ept_info->rem0_len, ept_info->maxpacket)); + } + else + { + if(udev->class_handler->ept0_rx_handler != 0) + { + udev->class_handler->ept0_rx_handler(udev); + } + usbd_ctrl_send_status(udev); + } + } + } + else if(udev->class_handler->out_handler != 0 && + udev->conn_state == USB_CONN_STATE_CONFIGURED) + { + /* other user define endpoint */ + udev->class_handler->out_handler(udev, ept_addr); + } +} + +/** + * @brief usb core setup transfer complete handler + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_core_setup_handler(usbd_core_type *udev, uint8_t ept_num) +{ + /* setup parse */ + usbd_setup_request_parse(&udev->setup, udev->setup_buffer); + + /* set ept0 status */ + udev->ept0_sts = USB_EPT0_SETUP; + udev->ept0_wlength = udev->setup.wLength; + + switch(udev->setup.bmRequestType & USB_REQ_RECIPIENT_MASK) + { + case USB_REQ_RECIPIENT_DEVICE: + /* recipient device request */ + usbd_device_request(udev); + break; + case USB_REQ_RECIPIENT_INTERFACE: + /* recipient interface request */ + usbd_interface_request(udev); + break; + case USB_REQ_RECIPIENT_ENDPOINT: + /* recipient endpoint request */ + usbd_endpoint_request(udev); + break; + default: + break; + } +} + +/** + * @brief usb control endpoint send data + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @param buffer: send data buffer + * @param len: send data length + * @retval none + */ +void usbd_ctrl_send(usbd_core_type *udev, uint8_t *buffer, uint16_t len) +{ + usb_ept_info *ept_info = &udev->ept_in[0]; + + ept_info->ept0_slen = len; + ept_info->rem0_len = len; + udev->ept0_sts = USB_EPT0_DATA_IN; + + usbd_ept_send(udev, 0, buffer, len); +} + +/** + * @brief usb control endpoint receive data + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @param buffer: recv data buffer + * @param len: recv data length + * @retval none + */ +void usbd_ctrl_recv(usbd_core_type *udev, uint8_t *buffer, uint16_t len) +{ + usb_ept_info *ept_info = &udev->ept_out[0]; + + ept_info->ept0_slen = len; + ept_info->rem0_len = len; + udev->ept0_sts = USB_EPT0_DATA_OUT; + + usbd_ept_recv(udev, 0, buffer, len); +} + +/** + * @brief usb control endpoint send in status + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_ctrl_send_status(usbd_core_type *udev) +{ + udev->ept0_sts = USB_EPT0_STATUS_IN; + + usbd_ept_send(udev, 0, 0, 0); +} + +/** + * @brief usb control endpoint send out status + * @param udev: usb device core handler type + * @retval none + */ +void usbd_ctrl_recv_status(usbd_core_type *udev) +{ + udev->ept0_sts = USB_EPT0_STATUS_OUT; + + usbd_ept_recv(udev, 0, 0, 0); +} + +/** + * @brief clear endpoint stall + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_clear_stall(usbd_core_type *udev, uint8_t ept_addr) +{ + usb_ept_info *ept_info; + + if(ept_addr & 0x80) + { + /* in endpoint */ + ept_info = &udev->ept_in[ept_addr & 0x7F]; + USB_CLEAR_TXDTS(ept_info->eptn); + if(USB->ept_bit[ept_info->eptn].txsts == USB_TX_STALL) + USB_SET_TXSTS(ept_info->eptn, USB_TX_NAK); + } + else + { + /* out endpoint */ + ept_info = &udev->ept_out[ept_addr & 0x7F]; + USB_CLEAR_RXDTS(ept_info->eptn); + if(USB->ept_bit[ept_info->eptn].rxsts == USB_RX_STALL) + USB_SET_RXSTS(ept_info->eptn, USB_RX_VALID); + } + ept_info->stall = 0; +} + +/** + * @brief usb set endpoint to stall. + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_set_stall(usbd_core_type *udev, uint8_t ept_addr) +{ + usb_ept_info *ept_info; + + if(ept_addr & 0x80) + { + /* in endpoint */ + ept_info = &udev->ept_in[ept_addr & 0x7F]; + USB_SET_TXSTS(ept_info->eptn, USB_TX_STALL); + } + else + { + /* out endpoint */ + ept_info = &udev->ept_out[ept_addr & 0x7F]; + USB_SET_RXSTS(ept_info->eptn, USB_RX_STALL) + } + + ept_info->stall = 1; +} + +/** + * @brief un-support device request + * @param udev: usb device core handler type + * @retval none + */ +void usbd_ctrl_unsupport(usbd_core_type *udev) +{ + /* return stall status */ + usbd_set_stall(udev, 0x00); + usbd_set_stall(udev, 0x80); +} + +/** + * @brief usb endpoint send data + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @param buffer: send data buffer + * @param len: send data length + * @retval none + */ +void usbd_ept_send(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len) +{ + /* get endpoint info struct and register */ + usb_ept_info *ept_info = &udev->ept_in[ept_addr & 0x7F]; + uint16_t trs_len = 0; + usbd_type *usbx = udev->usb_reg; + + /* set send data buffer and length */ + ept_info->trans_buf = buffer; + ept_info->total_len = len; + ept_info->trans_len = 0; + + if(ept_info->total_len > ept_info->maxpacket) + { + trs_len = ept_info->maxpacket; + ept_info->total_len -= trs_len; + } + else + { + trs_len = len; + ept_info->total_len = 0; + } + + ept_info->last_len = trs_len; + + if(ept_info->is_double_buffer == 0) + { + /* write data to endpoint buffer */ + usb_write_packet(ept_info->trans_buf, ept_info->tx_addr, trs_len); + + /* set send data length */ + USB_SET_TXLEN((ept_addr & 0x7F), trs_len); + } + else + { + if(usbx->ept_bit[ept_addr & 0x7F].txdts) + { + USB_SET_EPT_DOUBLE_BUF1_LEN((ept_addr & 0x7F), trs_len, DATA_TRANS_IN); + usb_write_packet(ept_info->trans_buf, ept_info->rx_addr, trs_len); + } + else + { + USB_SET_EPT_DOUBLE_BUF0_LEN((ept_addr & 0x7F), trs_len, DATA_TRANS_IN); + usb_write_packet(ept_info->trans_buf, ept_info->tx_addr, trs_len); + } + USB_FREE_DB_USER_BUFFER((ept_addr & 0x7F), DATA_TRANS_IN); + } + + /* set tx status valid */ + USB_SET_TXSTS((ept_addr & 0x7F), USB_TX_VALID); +} + +/** + * @brief usb endpoint receive data + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @param buffer: receive data buffer + * @param len: receive data length + * @retval none + */ +void usbd_ept_recv(usbd_core_type *udev, uint8_t ept_addr, uint8_t *buffer, uint16_t len) +{ + /* get endpoint info struct and register */ + usb_ept_info *ept_info = &udev->ept_out[ept_addr & 0x7F]; + uint32_t trs_len = 0; + + /* set receive data buffer and length */ + ept_info->trans_buf = buffer; + ept_info->total_len = len; + ept_info->trans_len = 0; + + if(ept_info->total_len > ept_info->maxpacket) + { + trs_len = ept_info->maxpacket; + ept_info->total_len -= trs_len; + } + else + { + trs_len = len; + ept_info->total_len = 0; + } + + /* set rx status valid */ + USB_SET_RXSTS((ept_addr & 0x7F), USB_RX_VALID); +} + + +/** + * @brief usb endpoint get receive data length + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +uint32_t usbd_get_recv_len(usbd_core_type *udev, uint8_t ept_addr) +{ + usb_ept_info *ept = &udev->ept_out[ept_addr & 0x7F]; + return ept->trans_len; +} + +/** + * @brief enable endpoint double buffer. + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_ept_dbuffer_enable(usbd_core_type *udev, uint8_t ept_addr) +{ + usb_ept_info *ept_info; + if((ept_addr & 0x80) == 0) + { + /* out endpoint info */ + ept_info = &udev->ept_out[ept_addr & 0x7F]; + } + else + { + /* in endpoint info */ + ept_info = &udev->ept_in[ept_addr & 0x7F]; + } + ept_info->is_double_buffer = TRUE; +} + +/** + * @brief usb auto define endpoint buffer + * @param usb_ept_info: endpoint information + * @retval none + */ +void usbd_ept_buf_auto_define(usb_ept_info *ept_info) +{ + if(ept_info->is_double_buffer == 0) + { + if( ept_info->inout == DATA_TRANS_IN ) + { + if(ept_info->tx_addr == 0) + ept_info->tx_addr = usb_buffer_malloc(ept_info->maxpacket); + } + else + { + if(ept_info->rx_addr == 0) + ept_info->rx_addr = usb_buffer_malloc(ept_info->maxpacket); + } + } + else + { + /* double buffer auto define */ + if(ept_info->tx_addr == 0) + ept_info->tx_addr = usb_buffer_malloc(ept_info->maxpacket); + if(ept_info->rx_addr == 0) + ept_info->rx_addr = usb_buffer_malloc(ept_info->maxpacket); + } +} + + + +/** + * @brief usb custom define endpoint buffer + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @param addr: usb fifo offset address + * @retval none + */ +void usbd_ept_buf_custom_define(usbd_core_type *udev, uint8_t ept_addr, + uint32_t addr) +{ + usb_ept_info *ept_info; + if((ept_addr & 0x80) == 0) + { + /* out endpoint info */ + ept_info = &udev->ept_out[ept_addr & 0x7F]; + } + else + { + /* in endpoint info */ + ept_info = &udev->ept_in[ept_addr & 0x7F]; + } + + if(ept_info->is_double_buffer == 0) + { + if( ept_info->inout == DATA_TRANS_IN ) + { + ept_info->tx_addr = addr; + } + else + { + ept_info->rx_addr = addr; + } + } + else + { + /* double buffer malloc */ + ept_info->tx_addr = addr & 0xFFFF; + ept_info->rx_addr = (addr >> 16) & 0xFFFF; + } +} + +/** + * @brief usb open endpoint + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @param ept_type: endpoint type + * @param maxpacket: endpoint support max buffer size + * @retval none + */ +void usbd_ept_open(usbd_core_type *udev, uint8_t ept_addr, uint8_t ept_type, uint16_t maxpacket) +{ + usbd_type *usbx = udev->usb_reg; + usb_ept_info *ept_info; + + if((ept_addr & 0x80) == 0) + { + /* out endpoint info */ + ept_info = &udev->ept_out[ept_addr & 0x7F]; + ept_info->inout = DATA_TRANS_OUT; + } + else + { + /* in endpoint info */ + ept_info = &udev->ept_in[ept_addr & 0x7F]; + ept_info->inout = DATA_TRANS_IN; + } + + /* set endpoint maxpacket and type */ + ept_info->maxpacket = (maxpacket + 1) & 0xFFFE; + ept_info->trans_type = ept_type; + +#ifdef USB_EPT_AUTO_MALLOC_BUFFER + usbd_ept_buf_auto_define(ept_info); +#endif + /* open endpoint */ + usb_ept_open(usbx, ept_info); +} + +/** + * @brief usb close endpoint + * @param udev: to the structure of usbd_core_type + * @param ept_addr: endpoint number + * @retval none + */ +void usbd_ept_close(usbd_core_type *udev, uint8_t ept_addr) +{ + usb_ept_info *ept_info; + if(ept_addr & 0x80) + { + /* in endpoint */ + ept_info = &udev->ept_in[ept_addr & 0x7F]; + } + else + { + /* out endpoint */ + ept_info = &udev->ept_out[ept_addr & 0x7F]; + } + + /* close endpoint */ + usb_ept_close(udev->usb_reg, ept_info); +} + +/** + * @brief usb device connect to host + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_connect(usbd_core_type *udev) +{ + usb_connect(udev->usb_reg); +} + +/** + * @brief usb device disconnect to host + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_disconnect(usbd_core_type *udev) +{ + usb_disconnect(udev->usb_reg); +} + +/** + * @brief usb device set device address. + * @param udev: to the structure of usbd_core_type + * @param address: host assignment address + * @retval none + */ +void usbd_set_device_addr(usbd_core_type *udev, uint8_t address) +{ + usb_set_address(udev->usb_reg, address); +} + +/** + * @brief get usb connect state + * @param udev: to the structure of usbd_core_type + * @retval usb connect state + */ +usbd_conn_state usbd_connect_state_get(usbd_core_type *udev) +{ + return udev->conn_state; +} + +/** + * @brief usb device remote wakeup + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_remote_wakeup(usbd_core_type *udev) +{ + /* set connect state */ + udev->conn_state = udev->old_conn_state; + + usb_exit_suspend(udev->usb_reg); + + usb_remote_wkup_set(udev->usb_reg); + + usb_delay_ms(10); + + usb_remote_wkup_clear(udev->usb_reg); + +} + +/** + * @brief usb device enter suspend mode + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_enter_suspend(usbd_core_type *udev) +{ + usb_enter_suspend(udev->usb_reg); +} + +/** + * @brief usb endpoint structure initialization + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_ept_defaut_init(usbd_core_type *udev) +{ + uint8_t i_index = 0; + /* init in endpoint info structure */ + for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++) + { + udev->ept_in[i_index].eptn = i_index; + udev->ept_in[i_index].ept_address = i_index; + udev->ept_in[i_index].inout = DATA_TRANS_IN; + udev->ept_in[i_index].maxpacket = 0; + udev->ept_in[i_index].trans_buf = 0; + udev->ept_in[i_index].total_len = 0; + udev->ept_in[i_index].tx_addr = 0; + udev->ept_in[i_index].rx_addr = 0; + } + + /* init out endpoint info structure */ + for(i_index = 0; i_index < USB_EPT_MAX_NUM; i_index ++) + { + udev->ept_out[i_index].eptn = i_index; + udev->ept_out[i_index].ept_address = i_index; + udev->ept_out[i_index].inout = DATA_TRANS_OUT; + udev->ept_out[i_index].maxpacket = 0; + udev->ept_out[i_index].trans_buf = 0; + udev->ept_out[i_index].total_len = 0; + udev->ept_out[i_index].rx_addr = 0; + udev->ept_out[i_index].tx_addr = 0; + } + return; +} + +/** + * @brief initializes the usb core + * @param udev: to the structure of usbd_core_type + * @param usb_reg: usb register pointer (USB) + * @param class_handler: usb class handler + * @param desc_handler: device config handler + * @param core_id: usb core id number + * @retval none + */ +void usbd_core_init(usbd_core_type *udev, + usb_reg_type *usb_reg, + usbd_class_handler *class_handler, + usbd_desc_handler *desc_handler, + uint8_t core_id) +{ + /* usb class handler */ + udev->class_handler = class_handler; + + /* usb description handler */ + udev->desc_handler = desc_handler; + + /* set usb register type */ + udev->usb_reg = usb_reg; + + /* set usb connect state to default */ + udev->conn_state = USB_CONN_STATE_DEFAULT; + + /* init in endpoint info structure */ + usbd_ept_defaut_init(udev); + +#ifdef USB_BUFFER_SIZE_EX + /* usb buffer size extend 768-1280 byte */ + usb_usbbufs_enable(usb_reg, TRUE); +#endif + + /*usb register config */ + usb_dev_init(udev->usb_reg); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/usbd_int.c b/src/usbd_int.c new file mode 100644 index 0000000..a422c74 --- /dev/null +++ b/src/usbd_int.c @@ -0,0 +1,331 @@ +/** + ************************************************************************** + * @file usbd_int.c + * @brief usb interrupt request + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ +#include "usbd_int.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @defgroup USBD_drivers_interrupt + * @brief usb device interrupt + * @{ + */ + +/** @defgroup USBD_int_private_functions + * @{ + */ + +/** + * @brief usb device interrput request handler. + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_irq_handler(usbd_core_type *udev) +{ + usbd_type *usbx = udev->usb_reg; + uint32_t sts_val = usbx->intsts; + uint32_t sts_ien = usbx->ctrl; + + if(sts_val & USB_TC_FLAG) + { + /* endpoint tc interrupt handler */ + usbd_ept_loop_handler(udev); + } + + if(sts_val & USB_RST_FLAG) + { + /* clear reset flag */ + usb_flag_clear(usbx, USB_RST_FLAG); + + /* reset interrupt handler */ + usbd_reset_handler(udev); + } + + if((sts_val & USB_SOF_FLAG) && + (sts_ien & USB_SOF_INT)) + { + /* clear sof flag */ + usb_flag_clear(usbx, USB_SOF_FLAG); + + /* sof interrupt handler */ + usbd_sof_handler(udev); + } + + if((sts_val & USB_LSOF_FLAG) && + (sts_ien & USB_LSOF_INT)) + { + /* clear lsof flag */ + usb_flag_clear(usbx, USB_LSOF_FLAG); + } + + if((sts_val & USB_SP_FLAG) && + (sts_ien & USB_SP_INT)) + { + /* clear suspend flag */ + usb_flag_clear(usbx, USB_SP_FLAG); + + /* usb suspend interrupt handler */ + usbd_suspend_handler(udev); + } + + if((sts_val & USB_WK_FLAG) && + (sts_ien & USB_WK_INT)) + { + /* usb wakeup interrupt handler */ + usbd_wakeup_handler(udev); + + /* clear wakeup flag */ + usb_flag_clear(usbx, USB_WK_FLAG); + } +} + +/** + * @brief usb device endpoint request handler. + * @param udev: to the structure of usbd_core_type + * @param ept_num: endpoint number + * @retval none + */ +void usbd_eptn_handler(usbd_core_type *udev, usb_ept_number_type ept_num) +{ + usbd_type *usbx = udev->usb_reg; + usb_ept_info *ept_info; + uint32_t ept_val = usbx->ept[ept_num]; + uint16_t length; + + /* in interrupt request */ + if(ept_val & USB_TXTC) + { + /* get endpoint register and in transfer info struct */ + ept_info = &udev->ept_in[ept_num]; + + /* clear endpoint tc flag */ + USB_CLEAR_TXTC(ept_num); + + /* get endpoint tx length */ + ept_info->trans_len = USB_GET_TX_LEN(ept_num); + + /* offset the trans buffer */ + ept_info->trans_buf += ept_info->trans_len; + + if(ept_info->total_len == 0 || ept_num == USB_EPT0) + { + /* in transfer complete */ + usbd_core_in_handler(udev, ept_num); + } + else + { + /* endpoint continue send data */ + usbd_ept_send(udev, ept_num, ept_info->trans_buf, ept_info->total_len); + } + /* set the host assignment address */ + if(udev->conn_state == USB_CONN_STATE_ADDRESSED && udev->device_addr > 0) + { + usb_set_address(udev->usb_reg, udev->device_addr); + udev->device_addr = 0; + } + } + else + { + /* setup and out interrupt request */ + + /* get endpoint register and out transfer info struct */ + ept_info = &udev->ept_out[ept_num]; + + if((ept_val & USB_SETUPTC) != 0) + { + /* endpoint setup interrupt request */ + + /* get endpoint received data length */ + ept_info->trans_len = USB_GET_RX_LEN(ept_num); + + /* read endpoint received data */ + usb_read_packet(udev->setup_buffer, ept_info->rx_addr, ept_info->trans_len); + + /* clear endpoint rx tc flag */ + USB_CLEAR_RXTC(USB_EPT0); + + /* endpoint setup complete handler */ + usbd_core_setup_handler(udev, ept_num); + } + else if(ept_val & USB_RXTC ) + { + /* endpoint out interrupt request */ + USB_CLEAR_RXTC(ept_num); + + if(ept_info->is_double_buffer == 0) + { + /* get endpoint received data length */ + length = USB_GET_RX_LEN(ept_num); + + /* read endpoint received data */ + usb_read_packet(ept_info->trans_buf, ept_info->rx_addr, length); + } + else + { + if( ept_val & USB_RXDTS) + { + length = USB_DBUF0_GET_LEN(ept_num); + usb_read_packet(ept_info->trans_buf, ept_info->tx_addr, length); + } + else + { + length = USB_DBUF1_GET_LEN(ept_num); + usb_read_packet(ept_info->trans_buf, ept_info->rx_addr, length); + } + USB_FREE_DB_USER_BUFFER(ept_num, DATA_TRANS_OUT); + } + + /* set received data length */ + ept_info->trans_len += length; + ept_info->trans_buf += length; + + if(ept_info->total_len == 0 || length < ept_info->maxpacket || ept_num == USB_EPT0) + { + /* out transfer complete */ + usbd_core_out_handler(udev, ept_num); + } + else + { + /* endpoint continue receive data */ + usbd_ept_recv(udev, ept_num, ept_info->trans_buf, ept_info->total_len); + } + } + } +} + +/** + * @brief usb device endpoint loop handler. + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_ept_loop_handler(usbd_core_type *udev) +{ + usbd_type *usbx = udev->usb_reg; + usb_ept_number_type ept_num = USB_EPT0; + uint32_t sts_val; + + while((sts_val = usbx->intsts) & USB_TC_FLAG) + { + /* get the interrupt endpoint number */ + ept_num = (usb_ept_number_type)(sts_val & USB_EPT_NUM_FLAG); + + usbd_eptn_handler(udev, ept_num); + } +} + +/** + * @brief usb device reset interrupt request handler. + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_reset_handler(usbd_core_type *udev) +{ + /* free usb buffer */ + usb_buffer_free(); + + usbd_ept_defaut_init(udev); +#ifndef USB_EPT_AUTO_MALLOC_BUFFER + usbd_ept_buf_custom_define(udev, 0x80, EPT0_TX_ADDR); + usbd_ept_buf_custom_define(udev, 0x00, EPT0_RX_ADDR); +#endif + + /* open endpoint 0 out */ + usbd_ept_open(udev, 0x00, EPT_CONTROL_TYPE, 0x40); + + /* open endpoint 0 in */ + usbd_ept_open(udev, 0x80, EPT_CONTROL_TYPE, 0x40); + + /* set device address to 0 */ + usb_set_address(udev->usb_reg, 0); + + /* usb connect state set to default */ + udev->conn_state = USB_CONN_STATE_DEFAULT; + + /* user define reset event */ + if(udev->class_handler->event_handler) + udev->class_handler->event_handler(udev, USBD_RESET_EVENT); +} + +/** + * @brief usb device sof interrupt request handler. + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_sof_handler(usbd_core_type *udev) +{ + /* user sof handler in class define*/ + if(udev->class_handler->sof_handler) + udev->class_handler->sof_handler(udev); +} + +/** + * @brief usb device suspend interrupt request handler. + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_suspend_handler(usbd_core_type *udev) +{ + /* save connect state */ + udev->old_conn_state = udev->conn_state; + + /* set current state to suspend */ + udev->conn_state = USB_CONN_STATE_SUSPENDED; + + /* enter suspend mode */ + usbd_enter_suspend(udev); + + /* user define suspend event */ + if(udev->class_handler->event_handler) + udev->class_handler->event_handler(udev, USBD_SUSPEND_EVENT); +} + +/** + * @brief usb device wakup interrupt request handler. + * @param udev: to the structure of usbd_core_type + * @retval none + */ +void usbd_wakeup_handler(usbd_core_type *udev) +{ + /* exit suspend mode */ + usb_exit_suspend(udev->usb_reg); + + /* restore connect state */ + udev->conn_state = udev->old_conn_state; + + /* user define wakeup event */ + if(udev->class_handler->event_handler) + udev->class_handler->event_handler(udev, USBD_WAKEUP_EVENT); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/usbd_sdr.c b/src/usbd_sdr.c new file mode 100644 index 0000000..ec86a65 --- /dev/null +++ b/src/usbd_sdr.c @@ -0,0 +1,565 @@ +/** + ************************************************************************** + * @file usbd_sdr.c + * @brief usb standard device request + ************************************************************************** + * Copyright notice & Disclaimer + * + * The software Board Support Package (BSP) that is made available to + * download from Artery official website is the copyrighted work of Artery. + * Artery authorizes customers to use, copy, and distribute the BSP + * software and its related documentation for the purpose of design and + * development in conjunction with Artery microcontrollers. Use of the + * software is governed by this copyright notice and the following disclaimer. + * + * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, + * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, + * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR + * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, + * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * + ************************************************************************** + */ +#include "usbd_sdr.h" + +/** @addtogroup AT32F403A_407_middlewares_usbd_drivers + * @{ + */ + +/** @defgroup USBD_drivers_standard_request + * @brief usb device standard_request + * @{ + */ + +/** @defgroup USBD_sdr_private_functions + * @{ + */ + +static usb_sts_type usbd_get_descriptor(usbd_core_type *udev); +static usb_sts_type usbd_set_address(usbd_core_type *udev); +static usb_sts_type usbd_get_status(usbd_core_type *udev); +static usb_sts_type usbd_clear_feature(usbd_core_type *udev); +static usb_sts_type usbd_set_feature(usbd_core_type *udev); +static usb_sts_type usbd_get_configuration(usbd_core_type *udev); +static usb_sts_type usbd_set_configuration(usbd_core_type *udev); + +/** + * @brief usb parse standard setup request + * @param setup: setup structure + * @param buf: setup buffer + * @retval none + */ +void usbd_setup_request_parse(usb_setup_type *setup, uint8_t *buf) +{ + setup->bmRequestType = *(uint8_t *) buf; + setup->bRequest = *(uint8_t *) (buf + 1); + setup->wValue = SWAPBYTE(buf + 2); + setup->wIndex = SWAPBYTE(buf + 4); + setup->wLength = SWAPBYTE(buf + 6); +} + +/** + * @brief get usb standard device description request + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_get_descriptor(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + uint16_t len = 0; + usbd_desc_t *desc = NULL; + uint8_t desc_type = udev->setup.wValue >> 8; + switch(desc_type) + { + case USB_DESCIPTOR_TYPE_DEVICE: + desc = udev->desc_handler->get_device_descriptor(); + break; + case USB_DESCIPTOR_TYPE_CONFIGURATION: + desc = udev->desc_handler->get_device_configuration(); + break; + case USB_DESCIPTOR_TYPE_STRING: + { + uint8_t str_desc = (uint8_t)udev->setup.wValue; + switch(str_desc) + { + case USB_LANGID_STRING: + desc = udev->desc_handler->get_device_lang_id(); + break; + case USB_MFC_STRING: + desc = udev->desc_handler->get_device_manufacturer_string(); + break; + case USB_PRODUCT_STRING: + desc = udev->desc_handler->get_device_product_string(); + break; + case USB_SERIAL_STRING: + desc = udev->desc_handler->get_device_serial_string(); + break; + case USB_CONFIG_STRING: + desc = udev->desc_handler->get_device_config_string(); + break; + case USB_INTERFACE_STRING: + desc = udev->desc_handler->get_device_interface_string(); + break; + case USB_WINUSB_OS_STRING: +#if (USBD_SUPPORT_WINUSB == 1) + if(udev->desc_handler->get_device_winusb_os_string != NULL) + { + desc = udev->desc_handler->get_device_winusb_os_string(); + } + else + { + usbd_ctrl_unsupport(udev); + } +#else + usbd_ctrl_unsupport(udev); +#endif + break; + default: + udev->class_handler->setup_handler(udev, &udev->setup); + return ret; + } + break; + } + case USB_DESCIPTOR_TYPE_DEVICE_QUALIFIER: + usbd_ctrl_unsupport(udev); + break; + case USB_DESCIPTOR_TYPE_OTHER_SPEED: + usbd_ctrl_unsupport(udev); + return ret; + default: + usbd_ctrl_unsupport(udev); + return ret; + } + + if(desc != NULL) + { + if((desc->length != 0) && (udev->setup.wLength != 0)) + { + len = MIN(desc->length , udev->setup.wLength); + usbd_ctrl_send(udev, desc->descriptor, len); + } + } + return ret; +} + +/** + * @brief this request sets the device address + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_set_address(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + uint8_t dev_addr; + + /* if wIndex or wLength are non-zero, then the behavior of + the device is not specified + */ + if(setup->wIndex == 0 && setup->wLength == 0) + { + dev_addr = (uint8_t)(setup->wValue) & 0x7f; + + /* device behavior when this request is received + while the device is in the configured state is not specified.*/ + if(udev->conn_state == USB_CONN_STATE_CONFIGURED ) + { + usbd_ctrl_unsupport(udev); + } + else + { + udev->device_addr = dev_addr; + + if(dev_addr != 0) + { + udev->conn_state = USB_CONN_STATE_ADDRESSED; + } + else + { + udev->conn_state = USB_CONN_STATE_DEFAULT; + } + usbd_ctrl_send_status(udev); + } + } + else + { + usbd_ctrl_unsupport(udev); + } + return ret; +} + +/** + * @brief get usb status request + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_get_status(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + case USB_CONN_STATE_CONFIGURED: + if(udev->remote_wakup) + { + udev->config_status |= USB_CONF_REMOTE_WAKEUP; + } + usbd_ctrl_send(udev, (uint8_t *)(&udev->config_status), 2); + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + return ret; +} + +/** + * @brief clear usb feature request + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_clear_feature(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + case USB_CONN_STATE_CONFIGURED: + if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + udev->remote_wakup = 0; + udev->config_status &= ~USB_CONF_REMOTE_WAKEUP; + udev->class_handler->setup_handler(udev, &udev->setup); + usbd_ctrl_send_status(udev); + } + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + return ret; +} + +/** + * @brief set usb feature request + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_set_feature(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + if(setup->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + udev->remote_wakup = 1; + udev->class_handler->setup_handler(udev, &udev->setup); + usbd_ctrl_send_status(udev); + } + else + { + usbd_ctrl_unsupport(udev); + } + return ret; +} + +/** + * @brief get usb configuration request + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_get_configuration(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + if(setup->wLength != 1) + { + usbd_ctrl_unsupport(udev); + } + else + { + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + udev->default_config = 0; + usbd_ctrl_send(udev, (uint8_t *)(&udev->default_config), 1); + break; + case USB_CONN_STATE_CONFIGURED: + usbd_ctrl_send(udev, (uint8_t *)(&udev->dev_config), 1); + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + } + return ret; +} + +/** + * @brief sets the usb device configuration request + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +static usb_sts_type usbd_set_configuration(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + static uint8_t config_value; + usb_setup_type *setup = &udev->setup; + config_value = (uint8_t)setup->wValue; + + if(setup->wIndex == 0 && setup->wLength == 0) + { + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + if(config_value) + { + udev->dev_config = config_value; + udev->conn_state = USB_CONN_STATE_CONFIGURED; + udev->class_handler->init_handler(udev); + usbd_ctrl_send_status(udev); + } + else + { + usbd_ctrl_send_status(udev); + } + + break; + case USB_CONN_STATE_CONFIGURED: + if(config_value == 0) + { + udev->conn_state = USB_CONN_STATE_ADDRESSED; + udev->dev_config = config_value; + udev->class_handler->clear_handler(udev); + usbd_ctrl_send_status(udev); + } + else if(config_value != udev->dev_config) + { + udev->class_handler->clear_handler(udev); + udev->dev_config = config_value; + udev->class_handler->init_handler(udev); + usbd_ctrl_send_status(udev); + } + else + { + usbd_ctrl_send_status(udev); + } + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + } + else + { + usbd_ctrl_unsupport(udev); + } + return ret; +} + +/** + * @brief standard usb device requests + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +usb_sts_type usbd_device_request(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) != USB_REQ_TYPE_STANDARD) + { + udev->class_handler->setup_handler(udev, &udev->setup); + return ret; + } + switch(udev->setup.bRequest) + { + case USB_STD_REQ_GET_STATUS: + usbd_get_status(udev); + break; + case USB_STD_REQ_CLEAR_FEATURE: + usbd_clear_feature(udev); + break; + case USB_STD_REQ_SET_FEATURE: + usbd_set_feature(udev); + break; + case USB_STD_REQ_SET_ADDRESS: + usbd_set_address(udev); + break; + case USB_STD_REQ_GET_DESCRIPTOR: + usbd_get_descriptor(udev); + break; + case USB_STD_REQ_GET_CONFIGURATION: + usbd_get_configuration(udev); + break; + case USB_STD_REQ_SET_CONFIGURATION: + usbd_set_configuration(udev); + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + return ret; +} + +/** + * @brief standard usb interface requests + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +usb_sts_type usbd_interface_request(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + switch(udev->conn_state) + { + case USB_CONN_STATE_DEFAULT: + case USB_CONN_STATE_ADDRESSED: + case USB_CONN_STATE_CONFIGURED: + ret = udev->class_handler->setup_handler(udev, &udev->setup); + if(setup->wLength == 0 && ret == USB_OK) + { + usbd_ctrl_send_status(udev); + } + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + return ret; +} + +/** + * @brief standard usb endpoint requests + * @param udev: to the structure of usbd_core_type + * @retval status of usb_sts_type + */ +usb_sts_type usbd_endpoint_request(usbd_core_type *udev) +{ + usb_sts_type ret = USB_OK; + usb_setup_type *setup = &udev->setup; + uint8_t ept_addr = LBYTE(setup->wIndex); + usb_ept_info *ept_info; + + if((setup->bmRequestType & USB_REQ_TYPE_RESERVED) != USB_REQ_TYPE_STANDARD) + { + udev->class_handler->setup_handler(udev, &udev->setup); + return ret; + } + switch(setup->bRequest) + { + case USB_STD_REQ_GET_STATUS: + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + if((ept_addr & 0x7F) != 0) + { + usbd_set_stall(udev, ept_addr); + } + if((ept_addr & 0x80) != 0) + { + ept_info = &udev->ept_in[ept_addr & 0x7F]; + } + else + { + ept_info = &udev->ept_out[ept_addr & 0x7F]; + } + ept_info->status = 0x0000; + usbd_ctrl_send(udev, (uint8_t *)(&ept_info->status), 2); + + break; + case USB_CONN_STATE_CONFIGURED: + { + if((ept_addr & 0x80) != 0) + { + ept_info = &udev->ept_in[ept_addr & 0x7F]; + } + else + { + ept_info = &udev->ept_out[ept_addr & 0x7F]; + } + if(ept_info->stall == 1) + { + ept_info->status = 0x0001; + } + else + { + ept_info->status = 0x0000; + } + usbd_ctrl_send(udev, (uint8_t *)(&ept_info->status), 2); + } + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + break; + case USB_STD_REQ_CLEAR_FEATURE: + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + if((ept_addr != 0x00) && (ept_addr != 0x80)) + { + usbd_set_stall(udev, ept_addr); + } + break; + case USB_CONN_STATE_CONFIGURED: + if(setup->wValue == USB_FEATURE_EPT_HALT) + { + if((ept_addr & 0x7F) != 0x00 ) + { + usbd_clear_stall(udev, ept_addr); + udev->class_handler->setup_handler(udev, &udev->setup); + } + usbd_ctrl_send_status(udev); + } + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + break; + case USB_STD_REQ_SET_FEATURE: + switch(udev->conn_state) + { + case USB_CONN_STATE_ADDRESSED: + if((ept_addr != 0x00) && (ept_addr != 0x80)) + { + usbd_set_stall(udev, ept_addr); + } + break; + case USB_CONN_STATE_CONFIGURED: + if(setup->wValue == USB_FEATURE_EPT_HALT) + { + if((ept_addr != 0x00) && (ept_addr != 0x80)) + { + usbd_set_stall(udev, ept_addr); + } + } + udev->class_handler->setup_handler(udev, &udev->setup); + usbd_ctrl_send_status(udev); + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + break; + default: + usbd_ctrl_unsupport(udev); + break; + } + return ret; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +