summaryrefslogtreecommitdiff
path: root/bsp/at32/libraries/usbd_library/src
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/at32/libraries/usbd_library/src')
-rw-r--r--bsp/at32/libraries/usbd_library/src/usbd_core.c689
-rw-r--r--bsp/at32/libraries/usbd_library/src/usbd_int.c347
-rw-r--r--bsp/at32/libraries/usbd_library/src/usbd_sdr.c533
3 files changed, 1569 insertions, 0 deletions
diff --git a/bsp/at32/libraries/usbd_library/src/usbd_core.c b/bsp/at32/libraries/usbd_library/src/usbd_core.c
new file mode 100644
index 0000000000..b6bd0ca9c4
--- /dev/null
+++ b/bsp/at32/libraries/usbd_library/src/usbd_core.c
@@ -0,0 +1,689 @@
+/**
+ **************************************************************************
+ * @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"
+#include "usbd_int.h"
+
+/** @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
+ {
+
+ usbd_ctrl_recv_status(udev);
+
+ }
+ usbd_data_in_stage_callback(udev,0);
+ }
+ }
+ else if(udev->class_handler->in_handler != 0 &&
+ udev->conn_state == USB_CONN_STATE_CONFIGURED)
+ {
+ /* other user define endpoint */
+ usbd_data_in_stage_callback(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
+ {
+ usbd_ctrl_send_status(udev);
+ }
+
+ usbd_data_out_stage_callback(udev, 0);
+ }
+ }
+ else if(udev->class_handler->out_handler != 0 &&
+ udev->conn_state == USB_CONN_STATE_CONFIGURED)
+ {
+ /* other user define endpoint */
+ usbd_data_out_stage_callback(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;
+}
+
+/**
+ * @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_SET_TXSTS(ept_info->eptn, USB_TX_VALID);
+ }
+ else
+ {
+ /* out endpoint */
+ ept_info = &udev->ept_out[ept_addr & 0x7F];
+ 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)
+{
+ if(address == 0)
+ 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);
+
+ rt_thread_mdelay(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,
+ uint8_t core_id)
+{
+ /* 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/bsp/at32/libraries/usbd_library/src/usbd_int.c b/bsp/at32/libraries/usbd_library/src/usbd_int.c
new file mode 100644
index 0000000000..4684d576ad
--- /dev/null
+++ b/bsp/at32/libraries/usbd_library/src/usbd_int.c
@@ -0,0 +1,347 @@
+/**
+ **************************************************************************
+ * @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"
+
+/** @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_callback(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_data_in_stage_callback(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);
+ usbd_setup_phase_done_callback(udev);
+ }
+ 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_data_out_stage_callback(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 */
+ usbd_reset_callback(udev);
+}
+
+/**
+ * @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);
+}
+
+/**
+ * @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 */
+}
+
+__weak void usbd_reset_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_setup_phase_done_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+}
+
+__weak void usbd_sof_callback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
+{
+}
+
+__weak void usbd_connectCallback(usbd_core_type *udev)
+{
+}
+
+__weak void usbd_disconnectCallback(usbd_core_type *udev)
+{
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/bsp/at32/libraries/usbd_library/src/usbd_sdr.c b/bsp/at32/libraries/usbd_library/src/usbd_sdr.c
new file mode 100644
index 0000000000..3ddf0afac8
--- /dev/null
+++ b/bsp/at32/libraries/usbd_library/src/usbd_sdr.c
@@ -0,0 +1,533 @@
+/**
+ **************************************************************************
+ * @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"
+
+/** @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;
+ uint8_t desc_type = udev->setup.wValue >> 8;
+ usbd_desc_t *desc = NULL, usbd_desc =
+ {
+ .length = 0xA,
+ .descriptor = NULL,
+ };
+
+ switch(desc_type)
+ {
+ case USB_DESCIPTOR_TYPE_DEVICE:
+ case USB_DESCIPTOR_TYPE_CONFIGURATION:
+ desc = &usbd_desc;
+ break;
+ case USB_DESCIPTOR_TYPE_STRING:
+ {
+ uint8_t str_desc = (uint8_t)udev->setup.wValue;
+ switch(str_desc)
+ {
+ case USB_LANGID_STRING:
+ case USB_MFC_STRING:
+ case USB_PRODUCT_STRING:
+ case USB_SERIAL_STRING:
+ case USB_CONFIG_STRING:
+ case USB_INTERFACE_STRING:
+ desc = &usbd_desc;
+ break;
+ default:
+ usbd_ctrl_send(udev, desc->descriptor, len);
+ 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;
+ 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;
+ usbd_ctrl_send_status(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;
+ 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;
+ usbd_ctrl_send_status(udev);
+ }
+ else if(config_value == udev->dev_config)
+ {
+ udev->dev_config = config_value;
+ 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_CONFIGURED:
+ switch(setup->bmRequestType & USB_REQ_TYPE_RESERVED)
+ {
+ case USB_REQ_TYPE_CLASS:
+ if(setup->wLength)
+ {
+ if(setup->bmRequestType & USB_REQ_DIR_DTH)
+ {
+ USB_SET_RXSTS((udev->ept_in[0].ept_address & 0x7F), USB_RX_VALID);
+ }
+ else
+ {
+ usbd_ept_send(udev, 0, 0, 0);
+ USB_SET_TXSTS((udev->ept_in[0].ept_address & 0x7F), USB_TX_VALID);
+ }
+ }
+ default:
+ break;
+ }
+
+ if(setup->wLength == 0)
+ {
+ 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_CLASS)
+ {
+ udev->class_handler->setup_handler(udev, &udev->setup);
+ }
+ 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);
+ }
+ 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;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+