aboutsummaryrefslogtreecommitdiffstats
path: root/usb
diff options
context:
space:
mode:
authorKévin Redon <kredon@sysmocom.de>2018-12-11 17:43:40 +0100
committerKévin Redon <kredon@sysmocom.de>2019-01-09 15:33:36 +0100
commit8476b94ab008805db1e91d74fc47b1619953f48b (patch)
treeaed8d9f0aaab2a07dc5c3c7d1bf7fae8ff396ead /usb
use USB CDC Echo example project
this is the USB CDC Echo example project source code, for the Microchip SAM E54 Xplained Pro development board, based on the ATSAME54P20A micro-controller, exported from the Atmel START website, using the ASFv4 library. Change-Id: Ic0e58e42d1a4076bc84a0a8d3509ec4b09a37f46
Diffstat (limited to 'usb')
-rw-r--r--usb/class/cdc/device/atmel_devices_cdc.catbin0 -> 8352 bytes
-rw-r--r--usb/class/cdc/device/atmel_devices_cdc.inf182
-rw-r--r--usb/class/cdc/device/cdcdf_acm.c379
-rw-r--r--usb/class/cdc/device/cdcdf_acm.h108
-rw-r--r--usb/class/cdc/device/cdcdf_acm_desc.h131
-rw-r--r--usb/class/cdc/usb_protocol_cdc.h426
-rw-r--r--usb/device/usbdc.c1027
-rw-r--r--usb/device/usbdc.h249
-rw-r--r--usb/usb_atmel.h179
-rw-r--r--usb/usb_debug.h41
-rw-r--r--usb/usb_includes.h131
-rw-r--r--usb/usb_protocol.c161
-rw-r--r--usb/usb_protocol.h782
13 files changed, 3796 insertions, 0 deletions
diff --git a/usb/class/cdc/device/atmel_devices_cdc.cat b/usb/class/cdc/device/atmel_devices_cdc.cat
new file mode 100644
index 0000000..09a0673
--- /dev/null
+++ b/usb/class/cdc/device/atmel_devices_cdc.cat
Binary files differ
diff --git a/usb/class/cdc/device/atmel_devices_cdc.inf b/usb/class/cdc/device/atmel_devices_cdc.inf
new file mode 100644
index 0000000..d2df608
--- /dev/null
+++ b/usb/class/cdc/device/atmel_devices_cdc.inf
@@ -0,0 +1,182 @@
+; Windows 2000, XP, Vista, 7 and 8 (x32 and x64) setup file for Atmel CDC Devices
+; Copyright (c) 2000-2013 ATMEL, Inc.
+
+[Version]
+Signature = "$Windows NT$"
+Class = Ports
+ClassGuid = {4D36E978-E325-11CE-BFC1-08002BE10318}
+
+Provider = %Manufacturer%
+LayoutFile = layout.inf
+CatalogFile = atmel_devices_cdc.cat
+DriverVer = 01/08/2013,6.0.0.0
+
+;----------------------------------------------------------
+; Targets
+;----------------------------------------------------------
+[Manufacturer]
+%Manufacturer%=DeviceList, NTAMD64, NTIA64, NT
+
+[DeviceList]
+%ATMEL_CDC_XPLAINED%=DriverInstall, USB\VID_03EB&PID_2122
+%ATMEL_CDC_USB_ZIGBIT_Sub%=DriverInstall, USB\VID_03EB&PID_214B
+%ATMEL_CDC_USB_ZIGBIT_2_4%=DriverInstall, USB\VID_03EB&PID_214A
+%ATMEL_CDC_SFW_EXAMPLE%=DriverInstall, USB\VID_03EB&PID_2307
+%ATMEL_CDC_EVK1XXX%=DriverInstall, USB\VID_03EB&PID_2310
+%ATMEL_CDC_ASF_EXAMPLE%=DriverInstall, USB\VID_03EB&PID_2404
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2%=DriverInstall, USB\VID_03EB&PID_2421&MI_00
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4%=DriverInstall, USB\VID_03EB&PID_2424&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM1%=DriverInstall, USB\VID_03EB&PID_2425&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM2%=DriverInstall, USB\VID_03EB&PID_2425&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM1%=DriverInstall, USB\VID_03EB&PID_2426&MI_00
+%ATMEL_CDC_ASF_EXAMPLE3_COM2%=DriverInstall, USB\VID_03EB&PID_2426&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM3%=DriverInstall, USB\VID_03EB&PID_2426&MI_04
+%ATMEL_CDC_ASF_EXAMPLE3_COM4%=DriverInstall, USB\VID_03EB&PID_2426&MI_06
+%ATMEL_CDC_ASF_EXAMPLE3_COM5%=DriverInstall, USB\VID_03EB&PID_2426&MI_08
+%ATMEL_CDC_ASF_EXAMPLE3_COM6%=DriverInstall, USB\VID_03EB&PID_2426&MI_0A
+%ATMEL_CDC_ASF_EXAMPLE3_COM7%=DriverInstall, USB\VID_03EB&PID_2426&MI_0C
+
+[DeviceList.NTAMD64]
+%ATMEL_CDC_XPLAINED%=DriverInstall.NTamd64, USB\VID_03EB&PID_2122
+%ATMEL_CDC_USB_ZIGBIT_Sub%=DriverInstall.NTamd64, USB\VID_03EB&PID_214B
+%ATMEL_CDC_USB_ZIGBIT_2_4%=DriverInstall.NTamd64, USB\VID_03EB&PID_214A
+%ATMEL_CDC_SFW_EXAMPLE%=DriverInstall.NTamd64, USB\VID_03EB&PID_2307
+%ATMEL_CDC_EVK1XXX%=DriverInstall.NTamd64, USB\VID_03EB&PID_2310
+%ATMEL_CDC_ASF_EXAMPLE%=DriverInstall.NTamd64, USB\VID_03EB&PID_2404
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2%=DriverInstall.NTamd64, USB\VID_03EB&PID_2421&MI_00
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4%=DriverInstall.NTamd64, USB\VID_03EB&PID_2424&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM1%=DriverInstall.NTamd64, USB\VID_03EB&PID_2425&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM2%=DriverInstall.NTamd64, USB\VID_03EB&PID_2425&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM1%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_00
+%ATMEL_CDC_ASF_EXAMPLE3_COM2%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM3%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_04
+%ATMEL_CDC_ASF_EXAMPLE3_COM4%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_06
+%ATMEL_CDC_ASF_EXAMPLE3_COM5%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_08
+%ATMEL_CDC_ASF_EXAMPLE3_COM6%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_0A
+%ATMEL_CDC_ASF_EXAMPLE3_COM7%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_0C
+
+[DeviceList.NTIA64]
+%ATMEL_CDC_XPLAINED%=DriverInstall.NTamd64, USB\VID_03EB&PID_2122
+%ATMEL_CDC_USB_ZIGBIT_Sub%=DriverInstall.NTamd64, USB\VID_03EB&PID_214B
+%ATMEL_CDC_USB_ZIGBIT_2_4%=DriverInstall.NTamd64, USB\VID_03EB&PID_214A
+%ATMEL_CDC_SFW_EXAMPLE%=DriverInstall.NTamd64, USB\VID_03EB&PID_2307
+%ATMEL_CDC_EVK1XXX%=DriverInstall.NTamd64, USB\VID_03EB&PID_2310
+%ATMEL_CDC_ASF_EXAMPLE%=DriverInstall.NTamd64, USB\VID_03EB&PID_2404
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2%=DriverInstall.NTamd64, USB\VID_03EB&PID_2421&MI_00
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4%=DriverInstall.NTamd64, USB\VID_03EB&PID_2424&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM1%=DriverInstall.NTamd64, USB\VID_03EB&PID_2425&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM2%=DriverInstall.NTamd64, USB\VID_03EB&PID_2425&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM1%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_00
+%ATMEL_CDC_ASF_EXAMPLE3_COM2%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM3%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_04
+%ATMEL_CDC_ASF_EXAMPLE3_COM4%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_06
+%ATMEL_CDC_ASF_EXAMPLE3_COM5%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_08
+%ATMEL_CDC_ASF_EXAMPLE3_COM6%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_0A
+%ATMEL_CDC_ASF_EXAMPLE3_COM7%=DriverInstall.NTamd64, USB\VID_03EB&PID_2426&MI_0C
+
+[DeviceList.NT]
+%ATMEL_CDC_XPLAINED%=DriverInstall.NT, USB\VID_03EB&PID_2122
+%ATMEL_CDC_USB_ZIGBIT_Sub%=DriverInstall.NT, USB\VID_03EB&PID_214B
+%ATMEL_CDC_USB_ZIGBIT_2_4%=DriverInstall.NT, USB\VID_03EB&PID_214A
+%ATMEL_CDC_SFW_EXAMPLE%=DriverInstall.NT, USB\VID_03EB&PID_2307
+%ATMEL_CDC_EVK1XXX%=DriverInstall.NT, USB\VID_03EB&PID_2310
+%ATMEL_CDC_ASF_EXAMPLE%=DriverInstall.NT, USB\VID_03EB&PID_2404
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2%=DriverInstall.NT, USB\VID_03EB&PID_2421&MI_00
+%ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4%=DriverInstall.NT, USB\VID_03EB&PID_2424&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM1%=DriverInstall.NT, USB\VID_03EB&PID_2425&MI_00
+%ATMEL_CDC_ASF_EXAMPLE2_COM2%=DriverInstall.NT, USB\VID_03EB&PID_2425&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM1%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_00
+%ATMEL_CDC_ASF_EXAMPLE3_COM2%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_02
+%ATMEL_CDC_ASF_EXAMPLE3_COM3%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_04
+%ATMEL_CDC_ASF_EXAMPLE3_COM4%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_06
+%ATMEL_CDC_ASF_EXAMPLE3_COM5%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_08
+%ATMEL_CDC_ASF_EXAMPLE3_COM6%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_0A
+%ATMEL_CDC_ASF_EXAMPLE3_COM7%=DriverInstall.NT, USB\VID_03EB&PID_2426&MI_0C
+
+;----------------------------------------------------------
+; Windows 2000, XP, Vista, Windows 7, Windows 8 - 32bit
+;----------------------------------------------------------
+[Reader_Install.NTx86]
+
+
+[DestinationDirs]
+DefaultDestDir=12
+DriverInstall.NT.Copy=12
+
+[DriverInstall.NT]
+include=mdmcpq.inf
+CopyFiles=DriverInstall.NT.Copy
+AddReg=DriverInstall.NT.AddReg
+
+[DriverInstall.NT.Copy]
+usbser.sys
+
+[DriverInstall.NT.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,usbser.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[DriverInstall.NT.Services]
+AddService = usbser, 0x00000002, DriverService.NT
+
+[DriverService.NT]
+DisplayName = %Serial.SvcDesc%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %12%\usbser.sys
+LoadOrderGroup = Base
+
+;----------------------------------------------------------
+; Windows XP, Vista, Windows 7, Windows 8 - 64bit
+;----------------------------------------------------------
+
+[DriverInstall.NTamd64]
+include=mdmcpq.inf
+CopyFiles=DriverCopyFiles.NTamd64
+AddReg=DriverInstall.NTamd64.AddReg
+
+[DriverCopyFiles.NTamd64]
+usbser.sys,,,0x20
+
+[DriverInstall.NTamd64.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,usbser.sys
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
+
+[DriverInstall.NTamd64.Services]
+AddService=usbser, 0x00000002, DriverService.NTamd64
+
+[DriverService.NTamd64]
+DisplayName=%Serial.SvcDesc%
+ServiceType=1
+StartType=3
+ErrorControl=1
+ServiceBinary=%12%\usbser.sys
+
+;----------------------------------------------------------
+; String
+;----------------------------------------------------------
+
+[Strings]
+Manufacturer = "ATMEL, Inc."
+ATMEL_CDC_XPLAINED = "XPLAINED Virtual Com Port"
+ATMEL_CDC_USB_ZIGBIT_Sub = "ZigBit SubGHz USBstick Com Port"
+ATMEL_CDC_USB_ZIGBIT_2_4 = "ZigBit 2.4GHz USBstick Com Port"
+ATMEL_CDC_SFW_EXAMPLE = "Communication Device Class SFW example"
+ATMEL_CDC_EVK1XXX = "EVK1XXX Virtual Com Port"
+ATMEL_CDC_ASF_EXAMPLE = "Communication Device Class ASF example"
+ATMEL_CDC_ASF_COMPOSITE_EXAMPLE2 = "Communication Device Class ASF composite example 2"
+ATMEL_CDC_ASF_COMPOSITE_EXAMPLE4 = "Communication Device Class ASF composite example 4"
+ATMEL_CDC_ASF_EXAMPLE2_COM1 = "Communication Device Class ASF example2, COM1"
+ATMEL_CDC_ASF_EXAMPLE2_COM2 = "Communication Device Class ASF example2, COM2"
+ATMEL_CDC_ASF_EXAMPLE3_COM1 = "Communication Device Class ASF example3, COM1"
+ATMEL_CDC_ASF_EXAMPLE3_COM2 = "Communication Device Class ASF example3, COM2"
+ATMEL_CDC_ASF_EXAMPLE3_COM3 = "Communication Device Class ASF example3, COM3"
+ATMEL_CDC_ASF_EXAMPLE3_COM4 = "Communication Device Class ASF example3, COM4"
+ATMEL_CDC_ASF_EXAMPLE3_COM5 = "Communication Device Class ASF example3, COM5"
+ATMEL_CDC_ASF_EXAMPLE3_COM6 = "Communication Device Class ASF example3, COM6"
+ATMEL_CDC_ASF_EXAMPLE3_COM7 = "Communication Device Class ASF example3, COM7"
+
+Serial.SvcDesc = "USB Serial emulation driver"
+
diff --git a/usb/class/cdc/device/cdcdf_acm.c b/usb/class/cdc/device/cdcdf_acm.c
new file mode 100644
index 0000000..2691cc8
--- /dev/null
+++ b/usb/class/cdc/device/cdcdf_acm.c
@@ -0,0 +1,379 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack CDC ACM Function Implementation.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "cdcdf_acm.h"
+
+#define CDCDF_ACM_VERSION 0x00000001u
+#define CDCDF_ACM_COMM_EP_INDEX 0
+#define CDCDF_ACM_DATA_EP_INDEX 1
+
+/** USB Device CDC ACM Fucntion Specific Data */
+struct cdcdf_acm_func_data {
+ /** CDC Device ACM Interface information */
+ uint8_t func_iface[2];
+ /** CDC Device ACM IN Endpoint */
+ uint8_t func_ep_in[2];
+ /** CDC Device ACM OUT Endpoint */
+ uint8_t func_ep_out;
+ /** CDC Device ACM Enable Flag */
+ bool enabled;
+};
+
+static struct usbdf_driver _cdcdf_acm;
+static struct cdcdf_acm_func_data _cdcdf_acm_funcd;
+static struct usb_cdc_line_coding usbd_cdc_line_coding;
+
+static cdcdf_acm_notify_state_t cdcdf_acm_notify_state = NULL;
+static cdcdf_acm_set_line_coding_t cdcdf_acm_set_line_coding = NULL;
+
+/**
+ * \brief Enable CDC ACM Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB interface descriptor
+ * \return Operation status.
+ */
+static int32_t cdcdf_acm_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ struct cdcdf_acm_func_data *func_data = (struct cdcdf_acm_func_data *)(drv->func_data);
+
+ usb_ep_desc_t ep_desc;
+ usb_iface_desc_t ifc_desc;
+ uint8_t * ifc, *ep;
+ uint8_t i;
+
+ ifc = desc->sod;
+ for (i = 0; i < 2; i++) {
+ if (NULL == ifc) {
+ return ERR_NOT_FOUND;
+ }
+
+ ifc_desc.bInterfaceNumber = ifc[2];
+ ifc_desc.bInterfaceClass = ifc[5];
+
+ if ((CDC_CLASS_COMM == ifc_desc.bInterfaceClass) || (CDC_CLASS_DATA == ifc_desc.bInterfaceClass)) {
+ if (func_data->func_iface[i] == ifc_desc.bInterfaceNumber) { // Initialized
+ return ERR_ALREADY_INITIALIZED;
+ } else if (func_data->func_iface[i] != 0xFF) { // Occupied
+ return ERR_NO_RESOURCE;
+ } else {
+ func_data->func_iface[i] = ifc_desc.bInterfaceNumber;
+ }
+ } else { // Not supported by this function driver
+ return ERR_NOT_FOUND;
+ }
+
+ // Install endpoints
+ ep = usb_find_desc(ifc, desc->eod, USB_DT_ENDPOINT);
+ while (NULL != ep) {
+ ep_desc.bEndpointAddress = ep[2];
+ ep_desc.bmAttributes = ep[3];
+ ep_desc.wMaxPacketSize = usb_get_u16(ep + 4);
+ if (usb_d_ep_init(ep_desc.bEndpointAddress, ep_desc.bmAttributes, ep_desc.wMaxPacketSize)) {
+ return ERR_NOT_INITIALIZED;
+ }
+ if (ep_desc.bEndpointAddress & USB_EP_DIR_IN) {
+ func_data->func_ep_in[i] = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_in[i]);
+ } else {
+ func_data->func_ep_out = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_out);
+ }
+ desc->sod = ep;
+ ep = usb_find_ep_desc(usb_desc_next(desc->sod), desc->eod);
+ }
+ ifc = usb_find_desc(usb_desc_next(desc->sod), desc->eod, USB_DT_INTERFACE);
+ }
+ // Installed
+ _cdcdf_acm_funcd.enabled = true;
+ return ERR_NONE;
+}
+
+/**
+ * \brief Disable CDC ACM Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB device descriptor
+ * \return Operation status.
+ */
+static int32_t cdcdf_acm_disable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ struct cdcdf_acm_func_data *func_data = (struct cdcdf_acm_func_data *)(drv->func_data);
+
+ usb_iface_desc_t ifc_desc;
+ uint8_t i;
+
+ if (desc) {
+ ifc_desc.bInterfaceClass = desc->sod[5];
+ // Check interface
+ if ((ifc_desc.bInterfaceClass != CDC_CLASS_COMM) && (ifc_desc.bInterfaceClass != CDC_CLASS_DATA)) {
+ return ERR_NOT_FOUND;
+ }
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (func_data->func_iface[i] == 0xFF) {
+ continue;
+ } else {
+ func_data->func_iface[i] = 0xFF;
+ if (func_data->func_ep_in[i] != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_in[i]);
+ func_data->func_ep_in[i] = 0xFF;
+ }
+ }
+ }
+
+ if (func_data->func_ep_out != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_out);
+ func_data->func_ep_out = 0xFF;
+ }
+
+ _cdcdf_acm_funcd.enabled = false;
+ return ERR_NONE;
+}
+
+/**
+ * \brief CDC ACM Control Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] ctrl USB device general function control type
+ * \param[in] param Parameter pointer
+ * \return Operation status.
+ */
+static int32_t cdcdf_acm_ctrl(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param)
+{
+ switch (ctrl) {
+ case USBDF_ENABLE:
+ return cdcdf_acm_enable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_DISABLE:
+ return cdcdf_acm_disable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_GET_IFACE:
+ return ERR_UNSUPPORTED_OP;
+
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the CDC class set request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t cdcdf_acm_set_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ struct usb_cdc_line_coding line_coding_tmp;
+ uint16_t len = req->wLength;
+ uint8_t * ctrl_buf = usbdc_get_ctrl_buffer();
+
+ switch (req->bRequest) {
+ case USB_REQ_CDC_SET_LINE_CODING:
+ if (sizeof(struct usb_cdc_line_coding) != len) {
+ return ERR_INVALID_DATA;
+ }
+ if (USB_SETUP_STAGE == stage) {
+ return usbdc_xfer(ep, ctrl_buf, len, false);
+ } else {
+ memcpy(&line_coding_tmp, ctrl_buf, sizeof(struct usb_cdc_line_coding));
+ if ((NULL == cdcdf_acm_set_line_coding) || (true == cdcdf_acm_set_line_coding(&line_coding_tmp))) {
+ usbd_cdc_line_coding = line_coding_tmp;
+ }
+ return ERR_NONE;
+ }
+ case USB_REQ_CDC_SET_CONTROL_LINE_STATE:
+ usbdc_xfer(0, NULL, 0, 0);
+ if (NULL != cdcdf_acm_notify_state) {
+ cdcdf_acm_notify_state(req->wValue);
+ }
+ return ERR_NONE;
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the CDC class get request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t cdcdf_acm_get_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ uint16_t len = req->wLength;
+
+ if (USB_DATA_STAGE == stage) {
+ return ERR_NONE;
+ }
+
+ switch (req->bRequest) {
+ case USB_REQ_CDC_GET_LINE_CODING:
+ if (sizeof(struct usb_cdc_line_coding) != len) {
+ return ERR_INVALID_DATA;
+ }
+ return usbdc_xfer(ep, (uint8_t *)&usbd_cdc_line_coding, len, false);
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the CDC class request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t cdcdf_acm_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ if (0x01 != ((req->bmRequestType >> 5) & 0x03)) { // class request
+ return ERR_NOT_FOUND;
+ }
+ if ((req->wIndex == _cdcdf_acm_funcd.func_iface[0]) || (req->wIndex == _cdcdf_acm_funcd.func_iface[1])) {
+ if (req->bmRequestType & USB_EP_DIR_IN) {
+ return cdcdf_acm_get_req(ep, req, stage);
+ } else {
+ return cdcdf_acm_set_req(ep, req, stage);
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+}
+
+/** USB Device CDC ACM Handler Struct */
+static struct usbdc_handler cdcdf_acm_req_h = {NULL, (FUNC_PTR)cdcdf_acm_req};
+
+/**
+ * \brief Initialize the USB CDC ACM Function Driver
+ */
+int32_t cdcdf_acm_init(void)
+{
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _cdcdf_acm.ctrl = cdcdf_acm_ctrl;
+ _cdcdf_acm.func_data = &_cdcdf_acm_funcd;
+
+ usbdc_register_function(&_cdcdf_acm);
+ usbdc_register_handler(USBDC_HDL_REQ, &cdcdf_acm_req_h);
+ return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize the USB CDC ACM Function Driver
+ */
+void cdcdf_acm_deinit(void)
+{
+ usb_d_ep_deinit(_cdcdf_acm_funcd.func_ep_in[CDCDF_ACM_COMM_EP_INDEX]);
+ usb_d_ep_deinit(_cdcdf_acm_funcd.func_ep_in[CDCDF_ACM_DATA_EP_INDEX]);
+ usb_d_ep_deinit(_cdcdf_acm_funcd.func_ep_out);
+}
+
+/**
+ * \brief USB CDC ACM Function Read Data
+ */
+int32_t cdcdf_acm_read(uint8_t *buf, uint32_t size)
+{
+ if (!cdcdf_acm_is_enabled()) {
+ return ERR_DENIED;
+ }
+ return usbdc_xfer(_cdcdf_acm_funcd.func_ep_out, buf, size, false);
+}
+
+/**
+ * \brief USB CDC ACM Function Write Data
+ */
+int32_t cdcdf_acm_write(uint8_t *buf, uint32_t size)
+{
+ if (!cdcdf_acm_is_enabled()) {
+ return ERR_DENIED;
+ }
+ return usbdc_xfer(_cdcdf_acm_funcd.func_ep_in[CDCDF_ACM_DATA_EP_INDEX], buf, size, true);
+}
+
+/**
+ * \brief USB CDC ACM Stop the data transfer
+ */
+void cdcdf_acm_stop_xfer(void)
+{
+ /* Stop transfer. */
+ usb_d_ep_abort(_cdcdf_acm_funcd.func_ep_in[CDCDF_ACM_DATA_EP_INDEX]);
+ usb_d_ep_abort(_cdcdf_acm_funcd.func_ep_out);
+}
+
+/**
+ * \brief USB CDC ACM Function Register Callback
+ */
+int32_t cdcdf_acm_register_callback(enum cdcdf_acm_cb_type cb_type, FUNC_PTR func)
+{
+ switch (cb_type) {
+ case CDCDF_ACM_CB_READ:
+ usb_d_ep_register_callback(_cdcdf_acm_funcd.func_ep_out, USB_D_EP_CB_XFER, func);
+ break;
+ case CDCDF_ACM_CB_WRITE:
+ usb_d_ep_register_callback(_cdcdf_acm_funcd.func_ep_in[CDCDF_ACM_DATA_EP_INDEX], USB_D_EP_CB_XFER, func);
+ break;
+ case CDCDF_ACM_CB_LINE_CODING_C:
+ cdcdf_acm_set_line_coding = (cdcdf_acm_set_line_coding_t)func;
+ break;
+ case CDCDF_ACM_CB_STATE_C:
+ cdcdf_acm_notify_state = (cdcdf_acm_notify_state_t)func;
+ break;
+ default:
+ return ERR_INVALID_ARG;
+ }
+ return ERR_NONE;
+}
+
+/**
+ * \brief Check whether CDC ACM Function is enabled
+ */
+bool cdcdf_acm_is_enabled(void)
+{
+ return _cdcdf_acm_funcd.enabled;
+}
+
+/**
+ * \brief Return the CDC ACM line coding structure start address
+ */
+const struct usb_cdc_line_coding *cdcdf_acm_get_line_coding(void)
+{
+ return (const struct usb_cdc_line_coding *)&usbd_cdc_line_coding;
+}
+
+/**
+ * \brief Return version
+ */
+uint32_t cdcdf_acm_get_version(void)
+{
+ return CDCDF_ACM_VERSION;
+}
diff --git a/usb/class/cdc/device/cdcdf_acm.h b/usb/class/cdc/device/cdcdf_acm.h
new file mode 100644
index 0000000..ad060bc
--- /dev/null
+++ b/usb/class/cdc/device/cdcdf_acm.h
@@ -0,0 +1,108 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack CDC ACM Function Definition.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#ifndef USBDF_CDC_ACM_SER_H_
+#define USBDF_CDC_ACM_SER_H_
+
+#include "usbdc.h"
+#include "usb_protocol_cdc.h"
+
+/** CDC ACM Class Callback Type */
+enum cdcdf_acm_cb_type { CDCDF_ACM_CB_READ, CDCDF_ACM_CB_WRITE, CDCDF_ACM_CB_LINE_CODING_C, CDCDF_ACM_CB_STATE_C };
+
+/** CDC ACM Notify Line State Callback. */
+typedef void (*cdcdf_acm_notify_state_t)(uint16_t);
+
+/** CDC ACM Set Line Coding Callback. */
+typedef bool (*cdcdf_acm_set_line_coding_t)(struct usb_cdc_line_coding *);
+
+/**
+ * \brief Initialize the USB CDC ACM Function Driver
+ * \return Operation status.
+ */
+int32_t cdcdf_acm_init(void);
+
+/**
+ * \brief Deinitialize the USB CDC ACM Function Driver
+ * \return Operation status.
+ */
+void cdcdf_acm_deinit(void);
+
+/**
+ * \brief USB CDC ACM Function Read Data
+ * \param[in] buf Pointer to the buffer which receives data
+ * \param[in] size the size of data to be received
+ * \return Operation status.
+ */
+int32_t cdcdf_acm_read(uint8_t *buf, uint32_t size);
+
+/**
+ * \brief USB CDC ACM Function Write Data
+ * \param[in] buf Pointer to the buffer which stores data
+ * \param[in] size the size of data to be sent
+ * \return Operation status.
+ */
+int32_t cdcdf_acm_write(uint8_t *buf, uint32_t size);
+
+/**
+ * \brief USB CDC ACM Stop the currnet data transfer
+ */
+void cdcdf_acm_stop_xfer(void);
+
+/**
+ * \brief USB CDC ACM Function Register Callback
+ * \param[in] cb_type Callback type of CDC ACM Function
+ * \param[in] func Pointer to callback function
+ * \return Operation status.
+ */
+int32_t cdcdf_acm_register_callback(enum cdcdf_acm_cb_type cb_type, FUNC_PTR func);
+
+/**
+ * \brief Check whether CDC ACM Function is enabled
+ * \return Operation status.
+ * \return true CDC ACM Function is enabled
+ * \return false CDC ACM Function is disabled
+ */
+bool cdcdf_acm_is_enabled(void);
+
+/**
+ * \brief Return the CDC ACM line coding structure start address
+ * \return Pointer to USB CDC ACM line coding data.
+ */
+const struct usb_cdc_line_coding *cdcdf_acm_get_line_coding(void);
+
+/**
+ * \brief Return version
+ */
+uint32_t cdcdf_acm_get_version(void);
+
+#endif /* USBDF_CDC_ACM_SER_H_ */
diff --git a/usb/class/cdc/device/cdcdf_acm_desc.h b/usb/class/cdc/device/cdcdf_acm_desc.h
new file mode 100644
index 0000000..ca29d33
--- /dev/null
+++ b/usb/class/cdc/device/cdcdf_acm_desc.h
@@ -0,0 +1,131 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack CDC ACM Function Descriptor Setting.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#ifndef USBDF_CDC_ACM_DESC_H_
+#define USBDF_CDC_ACM_DESC_H_
+
+#include "usb_protocol.h"
+#include "usb_protocol_cdc.h"
+#include "usbd_config.h"
+
+#define CDCD_ACM_DEV_DESC \
+ USB_DEV_DESC_BYTES(CONF_USB_CDCD_ACM_BCDUSB, \
+ 0x02, \
+ 0x00, \
+ 0x00, \
+ CONF_USB_CDCD_ACM_BMAXPKSZ0, \
+ CONF_USB_CDCD_ACM_IDVENDER, \
+ CONF_USB_CDCD_ACM_IDPRODUCT, \
+ CONF_USB_CDCD_ACM_BCDDEVICE, \
+ CONF_USB_CDCD_ACM_IMANUFACT, \
+ CONF_USB_CDCD_ACM_IPRODUCT, \
+ CONF_USB_CDCD_ACM_ISERIALNUM, \
+ CONF_USB_CDCD_ACM_BNUMCONFIG)
+
+#define CDCD_ACM_DEV_QUAL_DESC \
+ USB_DEV_QUAL_DESC_BYTES( \
+ CONF_USB_CDCD_ACM_BCDUSB, 0x02, 0x00, 0x00, CONF_USB_CDCD_ACM_BMAXPKSZ0, CONF_USB_CDCD_ACM_BNUMCONFIG)
+
+#define CDCD_ACM_CFG_DESC \
+ USB_CONFIG_DESC_BYTES(67, \
+ 2, \
+ CONF_USB_CDCD_ACM_BCONFIGVAL, \
+ CONF_USB_CDCD_ACM_ICONFIG, \
+ CONF_USB_CDCD_ACM_BMATTRI, \
+ CONF_USB_CDCD_ACM_BMAXPOWER)
+
+#define CDCD_ACM_OTH_SPD_CFG_DESC \
+ USB_OTH_SPD_CFG_DESC_BYTES(67, \
+ 2, \
+ CONF_USB_CDCD_ACM_BCONFIGVAL, \
+ CONF_USB_CDCD_ACM_ICONFIG, \
+ CONF_USB_CDCD_ACM_BMATTRI, \
+ CONF_USB_CDCD_ACM_BMAXPOWER)
+
+#define CDCD_ACM_COMM_IFACE_DESCES \
+ USB_IFACE_DESC_BYTES(CONF_USB_CDCD_ACM_COMM_BIFCNUM, \
+ CONF_USB_CDCD_ACM_COMM_BALTSET, \
+ 1, \
+ 0x2, \
+ 0x2, \
+ 0x0, \
+ CONF_USB_CDCD_ACM_COMM_IIFC), \
+ USB_CDC_HDR_DESC_BYTES(0x1001), USB_CDC_CALL_MGMT_DESC_BYTES(0x01, 0x00), USB_CDC_ACM_DESC_BYTES(0x02), \
+ USB_CDC_UNION_DESC_BYTES(CONF_USB_CDCD_ACM_COMM_BIFCNUM, 0x01), \
+ USB_ENDP_DESC_BYTES(CONF_USB_CDCD_ACM_COMM_INT_EPADDR, \
+ 3, \
+ CONF_USB_CDCD_ACM_COMM_INT_MAXPKSZ, \
+ CONF_USB_CDCD_ACM_COMM_INT_INTERVAL)
+
+#define CDCD_ACM_DATA_IFACE_DESCES \
+ USB_IFACE_DESC_BYTES(CONF_USB_CDCD_ACM_DATA_BIFCNUM, \
+ CONF_USB_CDCD_ACM_DATA_BALTSET, \
+ 2, \
+ 0x0A, \
+ 0x0, \
+ 0x0, \
+ CONF_USB_CDCD_ACM_DATA_IIFC), \
+ USB_ENDP_DESC_BYTES(CONF_USB_CDCD_ACM_DATA_BULKOUT_EPADDR, 2, CONF_USB_CDCD_ACM_DATA_BULKOUT_MAXPKSZ, 0), \
+ USB_ENDP_DESC_BYTES(CONF_USB_CDCD_ACM_DATA_BULKIN_EPADDR, 2, CONF_USB_CDCD_ACM_DATA_BULKIN_MAXPKSZ, 0)
+
+#define CDCD_ACM_DATA_IFACE_DESCES_HS \
+ USB_IFACE_DESC_BYTES(CONF_USB_CDCD_ACM_DATA_BIFCNUM, \
+ CONF_USB_CDCD_ACM_DATA_BALTSET, \
+ 2, \
+ 0x0A, \
+ 0x0, \
+ 0x0, \
+ CONF_USB_CDCD_ACM_DATA_IIFC), \
+ USB_ENDP_DESC_BYTES(CONF_USB_CDCD_ACM_DATA_BULKOUT_EPADDR, 2, CONF_USB_CDCD_ACM_DATA_BULKOUT_MAXPKSZ_HS, 0), \
+ USB_ENDP_DESC_BYTES(CONF_USB_CDCD_ACM_DATA_BULKIN_EPADDR, 2, CONF_USB_CDCD_ACM_DATA_BULKIN_MAXPKSZ_HS, 0)
+
+#define CDCD_ACM_STR_DESCES \
+ CONF_USB_CDCD_ACM_LANGID_DESC \
+ CONF_USB_CDCD_ACM_IMANUFACT_STR_DESC \
+ CONF_USB_CDCD_ACM_IPRODUCT_STR_DESC \
+ CONF_USB_CDCD_ACM_ISERIALNUM_STR_DESC \
+ CONF_USB_CDCD_ACM_ICONFIG_STR_DESC
+
+/** USB Device descriptors and configuration descriptors */
+#define CDCD_ACM_DESCES_LS_FS \
+ CDCD_ACM_DEV_DESC, CDCD_ACM_CFG_DESC, CDCD_ACM_COMM_IFACE_DESCES, CDCD_ACM_DATA_IFACE_DESCES, CDCD_ACM_STR_DESCES
+
+#define CDCD_ACM_HS_DESCES_LS_FS \
+ CDCD_ACM_DEV_DESC, CDCD_ACM_DEV_QUAL_DESC, CDCD_ACM_CFG_DESC, CDCD_ACM_COMM_IFACE_DESCES, \
+ CDCD_ACM_DATA_IFACE_DESCES, CDCD_ACM_OTH_SPD_CFG_DESC, CDCD_ACM_COMM_IFACE_DESCES, \
+ CDCD_ACM_DATA_IFACE_DESCES_HS, CDCD_ACM_STR_DESCES
+
+#define CDCD_ACM_HS_DESCES_HS \
+ CDCD_ACM_CFG_DESC, CDCD_ACM_COMM_IFACE_DESCES, CDCD_ACM_DATA_IFACE_DESCES_HS, CDCD_ACM_OTH_SPD_CFG_DESC, \
+ CDCD_ACM_COMM_IFACE_DESCES, CDCD_ACM_DATA_IFACE_DESCES
+
+#endif /* USBDF_CDC_ACM_DESC_H_ */
diff --git a/usb/class/cdc/usb_protocol_cdc.h b/usb/class/cdc/usb_protocol_cdc.h
new file mode 100644
index 0000000..29d882a
--- /dev/null
+++ b/usb/class/cdc/usb_protocol_cdc.h
@@ -0,0 +1,426 @@
+/**
+ * \file
+ *
+ * \brief USB Communication Device Class (CDC) protocol definitions
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+#ifndef _USB_PROTOCOL_CDC_H_
+#define _USB_PROTOCOL_CDC_H_
+
+#include "usb_includes.h"
+
+/**
+ * \ingroup usb_protocol_group
+ * \defgroup cdc_protocol_group Communication Device Class Definitions
+ * @{
+ */
+
+/**
+ * \name Possible values of class
+ */
+//@{
+#define CDC_CLASS_DEVICE 0x02 //!< USB Communication Device Class
+#define CDC_CLASS_COMM 0x02 //!< CDC Communication Class Interface
+#define CDC_CLASS_DATA 0x0A //!< CDC Data Class Interface
+//@}
+
+//! \name USB CDC Subclass IDs
+//@{
+#define CDC_SUBCLASS_DLCM 0x01 //!< Direct Line Control Model
+#define CDC_SUBCLASS_ACM 0x02 //!< Abstract Control Model
+#define CDC_SUBCLASS_TCM 0x03 //!< Telephone Control Model
+#define CDC_SUBCLASS_MCCM 0x04 //!< Multi-Channel Control Model
+#define CDC_SUBCLASS_CCM 0x05 //!< CAPI Control Model
+#define CDC_SUBCLASS_ETH 0x06 //!< Ethernet Networking Control Model
+#define CDC_SUBCLASS_ATM 0x07 //!< ATM Networking Control Model
+//@}
+
+//! \name USB CDC Communication Interface Protocol IDs
+//@{
+#define CDC_PROTOCOL_V25TER 0x01 //!< Common AT commands
+//@}
+
+//! \name USB CDC Data Interface Protocol IDs
+//@{
+#define CDC_PROTOCOL_I430 0x30 //!< ISDN BRI
+#define CDC_PROTOCOL_HDLC 0x31 //!< HDLC
+#define CDC_PROTOCOL_TRANS 0x32 //!< Transparent
+#define CDC_PROTOCOL_Q921M 0x50 //!< Q.921 management protocol
+#define CDC_PROTOCOL_Q921 0x51 //!< Q.931 [sic] Data link protocol
+#define CDC_PROTOCOL_Q921TM 0x52 //!< Q.921 TEI-multiplexor
+#define CDC_PROTOCOL_V42BIS 0x90 //!< Data compression procedures
+#define CDC_PROTOCOL_Q931 0x91 //!< Euro-ISDN protocol control
+#define CDC_PROTOCOL_V120 0x92 //!< V.24 rate adaption to ISDN
+#define CDC_PROTOCOL_CAPI20 0x93 //!< CAPI Commands
+#define CDC_PROTOCOL_HOST 0xFD //!< Host based driver
+/**
+ * \brief Describes the Protocol Unit Functional Descriptors [sic]
+ * on Communication Class Interface
+ */
+#define CDC_PROTOCOL_PUFD 0xFE
+//@}
+
+//! \name USB CDC Functional Descriptor Types
+//@{
+#define CDC_CS_INTERFACE 0x24 //!< Interface Functional Descriptor
+#define CDC_CS_ENDPOINT 0x25 //!< Endpoint Functional Descriptor
+//@}
+
+//! \name USB CDC Functional Descriptor Subtypes
+//@{
+#define CDC_SCS_HEADER 0x00 //!< Header Functional Descriptor
+#define CDC_SCS_CALL_MGMT 0x01 //!< Call Management
+#define CDC_SCS_ACM 0x02 //!< Abstract Control Management
+#define CDC_SCS_UNION 0x06 //!< Union Functional Descriptor
+//@}
+
+//! \name USB CDC Request IDs
+//@{
+#define USB_REQ_CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define USB_REQ_CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define USB_REQ_CDC_SET_COMM_FEATURE 0x02
+#define USB_REQ_CDC_GET_COMM_FEATURE 0x03
+#define USB_REQ_CDC_CLEAR_COMM_FEATURE 0x04
+#define USB_REQ_CDC_SET_AUX_LINE_STATE 0x10
+#define USB_REQ_CDC_SET_HOOK_STATE 0x11
+#define USB_REQ_CDC_PULSE_SETUP 0x12
+#define USB_REQ_CDC_SEND_PULSE 0x13
+#define USB_REQ_CDC_SET_PULSE_TIME 0x14
+#define USB_REQ_CDC_RING_AUX_JACK 0x15
+#define USB_REQ_CDC_SET_LINE_CODING 0x20
+#define USB_REQ_CDC_GET_LINE_CODING 0x21
+#define USB_REQ_CDC_SET_CONTROL_LINE_STATE 0x22
+#define USB_REQ_CDC_SEND_BREAK 0x23
+#define USB_REQ_CDC_SET_RINGER_PARMS 0x30
+#define USB_REQ_CDC_GET_RINGER_PARMS 0x31
+#define USB_REQ_CDC_SET_OPERATION_PARMS 0x32
+#define USB_REQ_CDC_GET_OPERATION_PARMS 0x33
+#define USB_REQ_CDC_SET_LINE_PARMS 0x34
+#define USB_REQ_CDC_GET_LINE_PARMS 0x35
+#define USB_REQ_CDC_DIAL_DIGITS 0x36
+#define USB_REQ_CDC_SET_UNIT_PARAMETER 0x37
+#define USB_REQ_CDC_GET_UNIT_PARAMETER 0x38
+#define USB_REQ_CDC_CLEAR_UNIT_PARAMETER 0x39
+#define USB_REQ_CDC_GET_PROFILE 0x3A
+#define USB_REQ_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define USB_REQ_CDC_SET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x41
+#define USB_REQ_CDC_GET_ETHERNET_POWER_MANAGEMENT_PATTERNFILTER 0x42
+#define USB_REQ_CDC_SET_ETHERNET_PACKET_FILTER 0x43
+#define USB_REQ_CDC_GET_ETHERNET_STATISTIC 0x44
+#define USB_REQ_CDC_SET_ATM_DATA_FORMAT 0x50
+#define USB_REQ_CDC_GET_ATM_DEVICE_STATISTICS 0x51
+#define USB_REQ_CDC_SET_ATM_DEFAULT_VC 0x52
+#define USB_REQ_CDC_GET_ATM_VC_STATISTICS 0x53
+// Added bNotification codes according cdc spec 1.1 chapter 6.3
+#define USB_REQ_CDC_NOTIFY_RING_DETECT 0x09
+#define USB_REQ_CDC_NOTIFY_SERIAL_STATE 0x20
+#define USB_REQ_CDC_NOTIFY_CALL_STATE_CHANGE 0x28
+#define USB_REQ_CDC_NOTIFY_LINE_STATE_CHANGE 0x29
+//@}
+
+/*
+ * Need to pack structures tightly, or the compiler might insert padding
+ * and violate the spec-mandated layout.
+ */
+COMPILER_PACK_SET(1)
+
+//! \name USB CDC Descriptors
+//@{
+
+//! CDC Header Functional Descriptor
+typedef struct usb_cdc_hdr_desc {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ le16_t bcdCDC;
+} usb_cdc_hdr_desc_t;
+
+#define USB_CDC_HDR_DESC_LEN 5
+#define USB_CDC_HDR_DESC_BYTES(bcdCDC) \
+ USB_CDC_HDR_DESC_LEN, /* bFunctionLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_SCS_HEADER, /* bDescriptorSubtype */ \
+ LE_BYTE0(bcdCDC), LE_BYTE1(bcdCDC) /* bcdCDC */
+
+//! CDC Call Management Functional Descriptor
+typedef struct usb_cdc_call_mgmt_desc {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bmCapabilities;
+ uint8_t bDataInterface;
+} usb_cdc_call_mgmt_desc_t;
+
+#define USB_CDC_CALL_MGMT_DESC_LEN 5
+#define USB_CDC_CALL_MGMT_DESC_BYTES(bmCapabilities, bDataInterface) \
+ USB_CDC_CALL_MGMT_DESC_LEN, /* bFunctionLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_SCS_CALL_MGMT, /* bDescriptorSubtype */ \
+ bmCapabilities, bDataInterface
+
+//! CDC ACM Functional Descriptor
+typedef struct usb_cdc_acm_desc {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bmCapabilities;
+} usb_cdc_acm_desc_t;
+
+#define USB_CDC_ACM_DESC_LEN 4
+#define USB_CDC_ACM_DESC_BYTES(bmCapabilities) \
+ USB_CDC_ACM_DESC_LEN, /* bFunctionLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_SCS_ACM, /* bDescriptorSubType */ \
+ bmCapabilities
+
+//! CDC Union Functional Descriptor
+typedef struct usb_cdc_union_desc {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bMasterInterface;
+ uint8_t bSlaveInterface0;
+} usb_cdc_union_desc_t;
+
+#define USB_CDC_UNION_DESC_LEN 5
+#define USB_CDC_UNION_DESC_BYTES(bMasterInterface, bSlaveInterface) \
+ USB_CDC_UNION_DESC_LEN, CDC_CS_INTERFACE, CDC_SCS_UNION, bMasterInterface, bSlaveInterface
+
+//! \name USB CDC Call Management Capabilities
+//@{
+//! Device handles call management itself
+#define CDC_CALL_MGMT_SUPPORTED (1 << 0)
+//! Device can send/receive call management info over a Data Class interface
+#define CDC_CALL_MGMT_OVER_DCI (1 << 1)
+//@}
+
+//! \name USB CDC ACM Capabilities
+//@{
+//! Device supports the request combination of
+//! Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
+#define CDC_ACM_SUPPORT_FEATURE_REQUESTS (1 << 0)
+//! Device supports the request combination of
+//! Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding,
+//! and the notification Serial_State.
+#define CDC_ACM_SUPPORT_LINE_REQUESTS (1 << 1)
+//! Device supports the request Send_Break
+#define CDC_ACM_SUPPORT_SENDBREAK_REQUESTS (1 << 2)
+//! Device supports the notification Network_Connection.
+#define CDC_ACM_SUPPORT_NOTIFY_REQUESTS (1 << 3)
+//@}
+//@}
+
+//! \name USB CDC line control
+//@{
+
+//! \name USB CDC line coding
+//@{
+
+//! Line Coding structure
+typedef struct usb_cdc_line_coding {
+ le32_t dwDTERate; //!< Data rate, bits per second
+ uint8_t bCharFormat; //!< 0-1 Stop bit,1-1.5 Stop bits,2-2 Stop bits
+ uint8_t bParityType; //!< 0-None,1-Odd,2-Even,3-Mark,4-Space
+ uint8_t bDataBits; //!< 5,6,7,8 or 16
+} usb_cdc_line_coding_t;
+
+//! Possible values of bCharFormat
+enum cdc_char_format {
+ CDC_STOP_BITS_1 = 0, //!< 1 stop bit
+ CDC_STOP_BITS_1_5 = 1, //!< 1.5 stop bits
+ CDC_STOP_BITS_2 = 2 //!< 2 stop bits
+};
+
+//! Possible values of bParityType
+enum cdc_parity {
+ CDC_PAR_NONE = 0, //!< No parity
+ CDC_PAR_ODD = 1, //!< Odd parity
+ CDC_PAR_EVEN = 2, //!< Even parity
+ CDC_PAR_MARK = 3, //!< Parity forced to 1 (mark)
+ CDC_PAR_SPACE = 4 //!< Parity forced to 0 (space)
+};
+//@}
+
+//! \name USB CDC control signals
+//! spec 1.1 chapter 6.2.14
+//@{
+
+//! Control signal structure
+typedef struct usb_cdc_control_signal {
+ union {
+ le16_t value;
+ struct {
+ uint8_t dte_present;
+ uint8_t carrier_ctrl;
+ } modem;
+ struct {
+ uint8_t DTR : 1; //!< Data Terminal Ready
+ uint8_t RTS : 1; //!< Request To Send
+ } rs232;
+ struct {
+ uint8_t s108_2 : 1; //!< V.24 signal 108/2
+ uint8_t s105 : 1; //!< V.24 signal 105
+ } v24;
+ };
+} usb_cdc_control_signal_t;
+
+//! \name Possible values in usb_cdc_control_signal_t
+//@{
+//! Carrier control for half duplex modems.
+//! This signal corresponds to V.24 signal 105 and RS-232 signal RTS.
+//! The device ignores the value of this bit
+//! when operating in full duplex mode.
+#define CDC_CTRL_SIGNAL_ACTIVATE_CARRIER (1 << 1)
+//! Indicates to DCE if DTE is present or not.
+//! This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR.
+#define CDC_CTRL_SIGNAL_DTE_PRESENT (1 << 0)
+//@}
+//@}
+
+//! \name USB CDC notification message
+//@{
+
+typedef struct usb_cdc_notify_msg {
+ uint8_t bmRequestType;
+ uint8_t bNotification;
+ union {
+ le16_t wValue;
+ struct {
+ uint8_t low;
+ uint8_t high;
+ } wValueBytes;
+ };
+ union {
+ le16_t wIndex;
+ struct {
+ uint8_t low;
+ uint8_t high;
+ } wIndexBytes;
+ };
+ union {
+ le16_t wLength;
+ struct {
+ uint8_t low;
+ uint8_t high;
+ } wLengthBytes;
+ };
+} usb_cdc_notify_msg_t;
+
+//! \name USB CDC serial state
+//@{*
+
+//! UART State Bitmap (cdc spec 1.1 chapter 6.3.5)
+typedef union usb_cdc_uart_state {
+ le16_t value;
+ struct {
+ uint8_t bRxCarrier : 1;
+ uint8_t bTxCarrier : 1;
+ uint8_t bBreak : 1;
+ uint8_t bRingSignal : 1;
+ uint8_t bFraming : 1;
+ uint8_t bParity : 1;
+ uint8_t bOverRun;
+ } bitmap;
+ struct {
+ uint8_t bDCD : 1;
+ uint8_t bDSR : 1;
+ uint8_t bBreak : 1;
+ uint8_t bRingSignal : 1;
+ uint8_t bFraming : 1;
+ uint8_t bParity : 1;
+ uint8_t bOverRun;
+ } rs232;
+ struct {
+ uint8_t bS109 : 1; //!< V.24 signal 109
+ uint8_t bS106 : 1; //!< V.24 signal 106
+ uint8_t bBreak : 1;
+ uint8_t bRingSignal : 1;
+ uint8_t bFraming : 1;
+ uint8_t bParity : 1;
+ uint8_t bOverRun;
+ } v24;
+} usb_cdc_uart_state_t;
+
+//! Hardware handshake support (cdc spec 1.1 chapter 6.3.5)
+typedef struct usb_cdc_notify_serial_state {
+ usb_cdc_notify_msg_t header;
+ union usb_cdc_uart_state state;
+} usb_cdc_notify_serial_state_t;
+
+//! \name Possible values in usb_cdc_notify_serial_state_t
+//@{
+#define CDC_SERIAL_STATE_DCD CPU_TO_LE16((1 << 0))
+#define CDC_SERIAL_STATE_DSR CPU_TO_LE16((1 << 1))
+#define CDC_SERIAL_STATE_BREAK CPU_TO_LE16((1 << 2))
+#define CDC_SERIAL_STATE_RING CPU_TO_LE16((1 << 3))
+#define CDC_SERIAL_STATE_FRAMING CPU_TO_LE16((1 << 4))
+#define CDC_SERIAL_STATE_PARITY CPU_TO_LE16((1 << 5))
+#define CDC_SERIAL_STATE_OVERRUN CPU_TO_LE16((1 << 6))
+//@}
+//! @}
+
+//! @}
+
+COMPILER_PACK_RESET()
+
+//! @}
+
+/**
+ * \brief Fill a CDC SetLineCoding request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_SetLineCoding_req(struct usb_req *req, uint8_t iface)
+{
+ req->bmRequestType = 0x21;
+ req->bRequest = USB_REQ_CDC_SET_LINE_CODING;
+ req->wValue = 0;
+ req->wIndex = iface;
+ req->wLength = sizeof(usb_cdc_line_coding_t);
+}
+
+/**
+ * \brief Fill a CDC SetControlLineState request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] iface Interface Number
+ * \param[in] ctrl Control Signal Bitmap
+ */
+static inline void usb_fill_SetControlLineState_req(struct usb_req *req, uint8_t iface, uint16_t ctrl)
+{
+ req->bmRequestType = 0x21;
+ req->bRequest = USB_REQ_CDC_SET_CONTROL_LINE_STATE;
+ req->wValue = ctrl;
+ req->wIndex = iface;
+ req->wLength = 0;
+}
+
+#endif // _USB_PROTOCOL_CDC_H_
diff --git a/usb/device/usbdc.c b/usb/device/usbdc.c
new file mode 100644
index 0000000..3cfd7bc
--- /dev/null
+++ b/usb/device/usbdc.c
@@ -0,0 +1,1027 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack Core Layer Implementation.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "usbdc.h"
+
+#define USBDC_VERSION 0x00000001u
+
+/**
+ * \brief USB Device Core Sof Handler
+ */
+struct usbdc_sof_handler {
+ struct usbdc_sof_handler *next;
+ usbdc_sof_cb_t cb;
+};
+
+/**
+ * \brief USB Device Core Request Handler
+ */
+struct usbdc_req_handler {
+ struct usbdc_req_handler *next;
+ usbdc_req_cb_t cb;
+};
+
+/**
+ * \brief USB Device Core Change Handler
+ */
+struct usbdc_change_handler {
+ struct usbdc_change_handler *next;
+ usbdc_change_cb_t cb;
+};
+
+/**
+ * \brief USB Device Core Handler
+ */
+struct usbdc_handlers {
+ struct list_descriptor sof_list;
+ struct list_descriptor req_list;
+ struct list_descriptor change_list;
+};
+
+/**
+ * \brief USB Device Core Driver Structure
+ */
+struct usbdc_driver {
+ /** Pointer to descriptions of descriptors. */
+ struct usbdc_descriptors desces;
+ /** Callback handlers. */
+ struct usbdc_handlers handlers;
+ /** list of function drivers. */
+ struct list_descriptor func_list;
+ /** Control buffer. */
+ uint8_t *ctrl_buf;
+ /** Device status. */
+ uint16_t status;
+ /** Device state. */
+ uint8_t state;
+ /** Configuration value. */
+ uint8_t cfg_value;
+ /** Control endpoint size. */
+ uint8_t ctrl_size;
+ /** Alternate interface used map */
+ uint8_t ifc_alt_map;
+};
+
+/**
+ * \brief USB Device Core Driver Instance
+ */
+static struct usbdc_driver usbdc;
+
+/**
+ * \brief Process the GetDeviceDescriptor request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_dev_desc(const uint8_t ep, struct usb_req *req)
+{
+ uint8_t *dev_desc = NULL;
+ uint16_t length = req->wLength;
+ if (length > 0x12) {
+ length = 0x12;
+ }
+#if CONF_USBD_HS_SP
+ if (usb_d_get_speed() == USB_SPEED_HS && usbdc.desces.hs) {
+ dev_desc = usb_find_desc(usbdc.desces.hs->sod, usbdc.desces.hs->eod, USB_DT_DEVICE);
+ } else {
+ /* Obtain descriptor from FS descriptors */
+ }
+#endif
+ if (!dev_desc) {
+ dev_desc = usb_find_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, USB_DT_DEVICE);
+ }
+ if (!dev_desc) {
+ return false;
+ }
+ if (ERR_NONE != usbdc_xfer(ep, dev_desc, length, false)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * \brief Process the GetConfigurationDescriptor request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_cfg_desc(const uint8_t ep, struct usb_req *req)
+{
+ uint8_t *cfg_desc = NULL;
+ uint16_t total_len;
+ uint16_t length = req->wLength;
+ uint8_t index = req->wValue & 0x00FF;
+ bool need_zlp = !(length & (usbdc.ctrl_size - 1));
+
+#if CONF_USBD_HS_SP
+ if (usb_d_get_speed() == USB_SPEED_HS && usbdc.desces.hs) {
+ cfg_desc = usb_find_cfg_desc(usbdc.desces.hs->sod, usbdc.desces.hs->eod, index + 1);
+ } else {
+ /* Obtain descriptor from FS descriptors */
+ }
+#endif
+ if (!cfg_desc) {
+ cfg_desc = usb_find_cfg_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, index + 1);
+ }
+ if (NULL == cfg_desc) {
+ return false;
+ }
+ total_len = usb_cfg_desc_total_len(cfg_desc);
+ if (length <= total_len) {
+ need_zlp = false;
+ } else {
+ length = total_len;
+ }
+ if (ERR_NONE != usbdc_xfer(ep, cfg_desc, length, need_zlp)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * \brief Process the GetStringDescriptor request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_str_desc(const uint8_t ep, struct usb_req *req)
+{
+ uint8_t *str_desc;
+ uint16_t length = req->wLength;
+ uint8_t index = req->wValue & 0x00FF;
+ bool need_zlp = !(length & (usbdc.ctrl_size - 1));
+ /* All string are in default descriptors block: FS/LS */
+ str_desc = usb_find_str_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, index);
+ if (NULL == str_desc) {
+ return false;
+ }
+ if (length <= str_desc[0]) {
+ need_zlp = false;
+ } else {
+ length = str_desc[0];
+ }
+ if (ERR_NONE != usbdc_xfer(ep, str_desc, length, need_zlp)) {
+ return false;
+ }
+ return true;
+}
+
+#if CONF_USBD_HS_SP
+/**
+ * \brief Process the GetDeviceQualifierDescriptor request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_devqual_desc(const uint8_t ep, struct usb_req *req)
+{
+ uint8_t *dev_desc = NULL;
+ uint16_t length = req->wLength;
+ if (length > 0x12) {
+ length = 0x12;
+ }
+ if (usb_d_get_speed() == USB_SPEED_HS && usbdc.desces.hs) {
+ dev_desc = usb_find_desc(usbdc.desces.hs->sod, usbdc.desces.hs->eod, USB_DT_DEVICE_QUALIFIER);
+ }
+ if (!dev_desc) {
+ dev_desc = usb_find_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, USB_DT_DEVICE_QUALIFIER);
+ }
+ if (!dev_desc) {
+ return false;
+ }
+ if (ERR_NONE != usbdc_xfer(ep, dev_desc, length, false)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * \brief Process the GetOtherSpeedConfigurationDescriptor request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_othspdcfg_desc(const uint8_t ep, struct usb_req *req)
+{
+ uint8_t *cfg_desc = NULL;
+ uint16_t total_len;
+ uint16_t length = req->wLength;
+ uint8_t index = req->wValue & 0x00FF;
+ bool need_zlp = !(length & (usbdc.ctrl_size - 1));
+
+ if (usb_d_get_speed() == USB_SPEED_HS && usbdc.desces.hs) {
+ cfg_desc = usb_find_othspdcfg_desc(usbdc.desces.hs->sod, usbdc.desces.hs->eod, index + 1);
+ } else {
+ /* Obtain descriptor from FS descriptors */
+ }
+ if (!cfg_desc) {
+ cfg_desc = usb_find_othspdcfg_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, index + 1);
+ }
+ if (NULL == cfg_desc) {
+ return false;
+ }
+ total_len = usb_cfg_desc_total_len(cfg_desc);
+ if (length <= total_len) {
+ need_zlp = false;
+ } else {
+ length = total_len;
+ }
+ if (ERR_NONE != usbdc_xfer(ep, cfg_desc, length, need_zlp)) {
+ return false;
+ }
+ return true;
+}
+#endif
+
+/**
+ * \brief Process the GetDescriptor request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_desc_req(const uint8_t ep, struct usb_req *req)
+{
+ uint8_t type = (uint8_t)(req->wValue >> 8);
+ switch (type) {
+ case USB_DT_DEVICE:
+ return usbdc_get_dev_desc(ep, req);
+ case USB_DT_CONFIG:
+ return usbdc_get_cfg_desc(ep, req);
+#if CONF_USBD_HS_SP
+ case USB_DT_DEVICE_QUALIFIER:
+ return usbdc_get_devqual_desc(ep, req);
+ case USB_DT_OTHER_SPEED_CONFIG:
+ return usbdc_get_othspdcfg_desc(ep, req);
+#endif
+ case USB_DT_STRING:
+ return usbdc_get_str_desc(ep, req);
+ default:
+ break;
+ }
+ return false;
+}
+
+/**
+ * \brief Process the GetStatus request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_status_req(const uint8_t ep, const struct usb_req *req)
+{
+ int32_t st;
+ (void)ep;
+
+ switch (req->bmRequestType & USB_REQT_RECIP_MASK) {
+ case USB_REQT_RECIP_DEVICE:
+ case USB_REQT_RECIP_INTERFACE:
+ st = 0;
+ break;
+ case USB_REQT_RECIP_ENDPOINT:
+ st = usb_d_ep_halt(req->wIndex & 0xFF, USB_EP_HALT_GET);
+ if (st < 0) {
+ return false;
+ }
+ st = st & 0x1;
+ break;
+ default:
+ return false;
+ }
+ memcpy(usbdc.ctrl_buf, &st, 2);
+ usbdc_xfer(ep, usbdc.ctrl_buf, 2, false);
+ return true;
+}
+
+/**
+ * \brief Process the standard Get Interface
+ * \param[in] req Point to usb request struct.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_interface(struct usb_req *req)
+{
+ struct usbdf_driver *func = (struct usbdf_driver *)usbdc.func_list.head;
+ int32_t rc;
+
+ if (!(usbdc.ifc_alt_map & (1 << req->wIndex))) {
+ /* Return 0 if alternate is not used */
+ usbdc.ctrl_buf[0] = 0;
+ usbdc_xfer(0, usbdc.ctrl_buf, 1, false);
+ return true;
+ }
+ /* Check function drivers only if alternate is used */
+ while (NULL != func) {
+ if (0 > (rc = func->ctrl(func, USBDF_GET_IFACE, req))) {
+ func = func->next;
+ } else {
+ usbdc.ctrl_buf[0] = (uint8_t)rc;
+ usbdc_xfer(0, usbdc.ctrl_buf, 1, false);
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * \brief Process the standard Get request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_get_req(const uint8_t ep, struct usb_req *req)
+{
+ switch (req->bRequest) {
+ case USB_REQ_GET_DESC:
+ return usbdc_get_desc_req(ep, req);
+ case USB_REQ_GET_CONFIG:
+ *(uint8_t *)usbdc.ctrl_buf = usbdc.cfg_value;
+ usbdc_xfer(ep, usbdc.ctrl_buf, 1, false);
+ return true;
+ case USB_REQ_GET_STATUS:
+ return usbdc_get_status_req(ep, req);
+ case USB_REQ_GET_INTERFACE:
+ return usbdc_get_interface(req);
+ default:
+ return false;
+ }
+}
+
+/**
+ * \brief Process the standard ClearFeature request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_clear_ftr_req(const uint8_t ep, const struct usb_req *req)
+{
+ (void)ep;
+ switch (req->bmRequestType & USB_REQT_RECIP_MASK) {
+ case USB_REQT_RECIP_ENDPOINT:
+ if (req->wLength != 0) {
+ return false;
+ }
+ usb_d_ep_halt(req->wIndex & 0xFF, USB_EP_HALT_CLR);
+ usbdc_xfer(ep, NULL, 0, true);
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * \brief Process the standard SetFeature request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_set_ftr_req(const uint8_t ep, const struct usb_req *req)
+{
+ (void)ep;
+ switch (req->bmRequestType & USB_REQT_RECIP_MASK) {
+ case USB_REQT_RECIP_ENDPOINT:
+ if (req->wLength != 0) {
+ return false;
+ }
+ usb_d_ep_halt(req->wIndex & 0xFF, USB_EP_HALT_SET);
+ usbdc_xfer(ep, NULL, 0, true);
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * \brief Unconfig, close all interfaces
+ */
+static void usbdc_unconfig(void)
+{
+ struct usbdf_driver *func = (struct usbdf_driver *)usbdc.func_list.head;
+ while (NULL != func) {
+ func->ctrl(func, USBDF_DISABLE, NULL);
+ func = func->next;
+ }
+}
+
+/**
+ * \brief Apply Set Configuration Value
+ * \param[in] cfg_value Configuration Value
+ * \retval true Set configuration OK.
+ * \retval false Request error.
+ */
+static bool usbdc_set_config(uint8_t cfg_value)
+{
+ struct usbd_descriptors desc;
+ struct usbdf_driver * func;
+ uint8_t * cfg_desc = NULL;
+ uint16_t total_len;
+ uint8_t last_iface = 0xFF;
+
+ if (cfg_value == 0) {
+ usbdc_unconfig();
+ return true;
+ }
+
+#if CONF_USBD_HS_SP
+ if (usb_d_get_speed() == USB_SPEED_HS && usbdc.desces.hs) {
+ cfg_desc = usb_find_cfg_desc(usbdc.desces.hs->sod, usbdc.desces.hs->eod, cfg_value);
+ } else {
+ /* Obtain descriptor from FS descriptors */
+ }
+#endif
+ if (!cfg_desc) {
+ cfg_desc = usb_find_cfg_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, cfg_value);
+ }
+ if (NULL == cfg_desc) {
+ return false;
+ }
+
+ total_len = usb_cfg_desc_total_len(cfg_desc);
+ desc.eod = cfg_desc + total_len;
+ desc.sod = usb_find_desc(cfg_desc, desc.eod, USB_DT_INTERFACE);
+
+ while (NULL != desc.sod) {
+ /* Apply very first alternate setting (must be 0) of the interface */
+ if (last_iface != desc.sod[2] /* bInterfaceNumber */) {
+ last_iface = desc.sod[2];
+ func = (struct usbdf_driver *)usbdc.func_list.head;
+ while (NULL != func) {
+ if (func->ctrl(func, USBDF_ENABLE, &desc)) {
+ func = func->next;
+ } else {
+ break;
+ }
+ }
+ }
+ desc.sod = usb_desc_next(desc.sod);
+ desc.sod = usb_find_desc(desc.sod, desc.eod, USB_DT_INTERFACE);
+ }
+ return true;
+}
+
+/**
+ * \brief Apply the USB device address
+ * \param[in] addr address to be set.
+ */
+static void usbdc_set_address(uint8_t addr)
+{
+ usb_d_set_address(addr);
+}
+
+/**
+ * \brief Process the standard Set Interface
+ * \param[in] alt_set Alternate Setting.
+ * \param[in] ifc_id Interface Index.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_set_interface(uint16_t alt_set, uint16_t ifc_id)
+{
+ struct usbd_descriptors desc;
+ struct usbdf_driver * func;
+ uint8_t * ifc = NULL;
+
+#if CONF_USBD_HS_SP
+ if (usb_d_get_speed() == USB_SPEED_HS && usbdc.desces.hs) {
+ ifc = usb_find_cfg_desc(usbdc.desces.hs->sod, usbdc.desces.hs->eod, usbdc.cfg_value);
+ } else {
+ /* Obtain descriptor from FS descriptors */
+ }
+#endif
+ if (!ifc) {
+ ifc = usb_find_cfg_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, usbdc.cfg_value);
+ }
+ if (NULL == ifc) {
+ return false;
+ }
+ desc.sod = ifc;
+ desc.eod = ifc + usb_cfg_desc_total_len(ifc);
+
+ if (NULL == (ifc = usb_find_desc(desc.sod, desc.eod, USB_DT_INTERFACE))) {
+ return false;
+ }
+
+ while (ifc[2] != ifc_id || ifc[3] != alt_set) {
+ desc.sod = usb_desc_next(desc.sod);
+ ifc = usb_find_desc(desc.sod, desc.eod, USB_DT_INTERFACE);
+ if (NULL == ifc) {
+ return false;
+ }
+ }
+
+ desc.sod = ifc;
+ func = (struct usbdf_driver *)usbdc.func_list.head;
+
+ while (NULL != func) {
+ if (func->ctrl(func, USBDF_DISABLE, &desc)) {
+ func = func->next;
+ } else if (ERR_NONE == func->ctrl(func, USBDF_ENABLE, &desc)) {
+ if (alt_set) {
+ /* Alternate settings are used from now on */
+ usbdc.ifc_alt_map |= 1 << ifc_id;
+ }
+ usbdc_xfer(0, NULL, 0, 0);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * \brief Process the standard Set request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_set_req(const uint8_t ep, struct usb_req *req)
+{
+ switch (req->bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ return (ERR_NONE == usbdc_xfer(ep, NULL, 0, true));
+ case USB_REQ_SET_CONFIG:
+ if (!usbdc_set_config(req->wValue)) {
+ return false;
+ }
+ return (ERR_NONE == usbdc_xfer(ep, NULL, 0, true));
+ case USB_REQ_CLEAR_FTR:
+ return usbdc_clear_ftr_req(ep, req);
+ case USB_REQ_SET_FTR:
+ return usbdc_set_ftr_req(ep, req);
+ case USB_REQ_SET_INTERFACE:
+ return usbdc_set_interface(req->wValue, req->wIndex);
+ default:
+ return false;
+ }
+}
+
+/** Invoke all registered SOF callbacks. */
+static void usbdc_sof_notify(void)
+{
+ struct usbdc_sof_handler *sof = (struct usbdc_sof_handler *)usbdc.handlers.sof_list.head;
+
+ while (sof != NULL) {
+ if (NULL != sof->cb) {
+ sof->cb();
+ }
+ sof = sof->next;
+ }
+}
+
+/** Invoke all registered Change notification callbacks. */
+static void usbdc_change_notify(enum usbdc_change_type change, uint32_t value)
+{
+ struct usbdc_change_handler *cg = (struct usbdc_change_handler *)usbdc.handlers.change_list.head;
+
+ while (cg != NULL) {
+ if (NULL != cg->cb) {
+ cg->cb(change, value);
+ }
+ cg = cg->next;
+ }
+}
+
+/** Invoke all registered request callbacks until request handled. */
+static int32_t usbdc_request_handler(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ struct usbdc_req_handler *h = (struct usbdc_req_handler *)usbdc.handlers.req_list.head;
+ int32_t rc;
+
+ while (h != NULL) {
+ if (NULL != h->cb) {
+ rc = h->cb(ep, req, stage);
+ if (0 == rc) {
+ return true;
+ } else if (ERR_NOT_FOUND != rc) {
+ return -1;
+ }
+ }
+ h = h->next;
+ }
+ return false;
+}
+
+/**
+ * \brief Callback invoked on USB device SOF
+ */
+static void usbd_sof_cb(void)
+{
+ usbdc_sof_notify();
+}
+
+/**
+ * \brief Callback invoked when control request is received
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ * \retval true Request is handled OK.
+ * \retval false Request not supported.
+ */
+static bool usbdc_cb_ctl_req(const uint8_t ep, struct usb_req *req)
+{
+ switch (usbdc_request_handler(ep, req, USB_SETUP_STAGE)) {
+ case true:
+ return true;
+ case -1:
+ return false;
+ default:
+ break;
+ }
+
+ // STD request handling
+ switch (req->bmRequestType & (USB_REQT_TYPE_MASK | USB_REQT_DIR_IN)) {
+ case USB_REQT_TYPE_STANDARD:
+ return usbdc_set_req(ep, req);
+ case (USB_REQT_TYPE_STANDARD | USB_REQT_DIR_IN):
+ return usbdc_get_req(ep, req);
+ default:
+ return false;
+ }
+}
+
+/**
+ * \brief When control status stage is end
+ * \param[in] req Pointer to the request.
+ */
+static void usbdc_ctrl_status_end(const struct usb_req *req)
+{
+ if (req->bmRequestType != USB_REQT_TYPE_STANDARD) {
+ return;
+ }
+ switch (req->bRequest) {
+ case USB_REQ_SET_CONFIG:
+ usbdc.cfg_value = req->wValue;
+ usbdc.state = req->wValue ? USBD_S_CONFIG : USBD_S_ADDRESS;
+ usbdc_change_notify(USBDC_C_STATE, usbdc.state);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ usbdc_set_address(req->wValue);
+ usbdc.state = req->wValue ? USBD_S_ADDRESS : USBD_S_DEFAULT;
+ usbdc_change_notify(USBDC_C_STATE, usbdc.state);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * \brief When control data stage is end
+ * \param[in] req Pointer to the request.
+ */
+static bool usbdc_ctrl_data_end(struct usb_req *req)
+{
+ usbdc_request_handler(0, req, USB_DATA_STAGE);
+ return false;
+}
+
+/**
+ * \brief Callback invoked when control data done or status done
+ * \param[in] ep Endpoint number with direction on bit 8.
+ * \param[in] code Status code.
+ * \param[in] req Pointer to the control setup request.
+ * \return Data has error or not.
+ * \retval true There is data error, protocol error.
+ * \retval false There is no data error.
+ */
+static bool usbdc_cb_ctl_done(const uint8_t ep, const enum usb_xfer_code code, struct usb_req *req)
+{
+ (void)ep;
+
+ switch (code) {
+ case USB_XFER_DONE:
+ usbdc_ctrl_status_end(req);
+ break;
+ case USB_XFER_DATA:
+ return usbdc_ctrl_data_end(req);
+ default:
+ break;
+ }
+ return false;
+}
+
+/**
+ * \brief USB Device Core Reset
+ */
+void usbdc_reset(void)
+{
+ usbdc_unconfig();
+
+ usbdc.state = USBD_S_DEFAULT;
+ usbdc.cfg_value = 0;
+ usbdc.ifc_alt_map = 0;
+
+ // Setup EP0
+ usb_d_ep_deinit(0);
+ usb_d_ep0_init(usbdc.ctrl_size);
+ usb_d_ep_register_callback(0, USB_D_EP_CB_SETUP, (FUNC_PTR)usbdc_cb_ctl_req);
+ usb_d_ep_register_callback(0, USB_D_EP_CB_XFER, (FUNC_PTR)usbdc_cb_ctl_done);
+ usb_d_ep_enable(0);
+}
+
+/**
+ * \brief Callback invoked on USB device events
+ * \param[in] ev Event code.
+ * \param[in] param Event parameter for event handling.
+ */
+static void usbd_event_cb(const enum usb_event ev, const uint32_t param)
+{
+ (void)param;
+
+ switch (ev) {
+ case USB_EV_VBUS:
+ usbdc_change_notify(USBDC_C_CONN, param);
+ break;
+
+ case USB_EV_RESET:
+ usbdc_reset();
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * \brief Issue USB device transfer
+ */
+int32_t usbdc_xfer(uint8_t ep, uint8_t *buf, uint32_t size, bool zlp)
+{
+ struct usb_d_transfer xfer = {(uint8_t *)buf, size, ep, zlp};
+ return usb_d_ep_transfer(&xfer);
+}
+
+/**
+ * \brief Register the handler
+ */
+void usbdc_register_handler(enum usbdc_handler_type type, const struct usbdc_handler *h)
+{
+ switch (type) {
+ case USBDC_HDL_SOF:
+ list_insert_at_end(&usbdc.handlers.sof_list, (void *)h);
+ break;
+ case USBDC_HDL_REQ:
+ list_insert_at_end(&usbdc.handlers.req_list, (void *)h);
+ break;
+ case USBDC_HDL_CHANGE:
+ list_insert_at_end(&usbdc.handlers.change_list, (void *)h);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * \brief Unregister the handler
+ */
+void usbdc_unregister_handler(enum usbdc_handler_type type, const struct usbdc_handler *h)
+{
+ switch (type) {
+ case USBDC_HDL_SOF:
+ list_delete_element(&usbdc.handlers.sof_list, (void *)h);
+ break;
+ case USBDC_HDL_REQ:
+ list_delete_element(&usbdc.handlers.req_list, (void *)h);
+ break;
+ case USBDC_HDL_CHANGE:
+ list_delete_element(&usbdc.handlers.change_list, (void *)h);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * \brief Initialize the USB device core driver
+ */
+int32_t usbdc_init(uint8_t *ctrl_buf)
+{
+ ASSERT(ctrl_buf);
+
+ int32_t rc;
+
+ rc = usb_d_init();
+ if (rc < 0) {
+ return rc;
+ }
+
+ memset(&usbdc, 0, sizeof(usbdc));
+ usbdc.ctrl_buf = ctrl_buf;
+ usb_d_register_callback(USB_D_CB_SOF, (FUNC_PTR)usbd_sof_cb);
+ usb_d_register_callback(USB_D_CB_EVENT, (FUNC_PTR)usbd_event_cb);
+
+ return 0;
+}
+
+/**
+ * \brief De-initialize the USB device core driver
+ */
+int32_t usbdc_deinit(void)
+{
+ usb_d_deinit();
+ return 0;
+}
+
+/**
+ * \brief Register/unregister function support of a USB device function
+ *
+ * Must be invoked when USB device is stopped.
+ */
+void usbdc_register_function(struct usbdf_driver *func)
+{
+ list_insert_at_end(&usbdc.func_list, func);
+}
+
+/**
+ * \brief Unregister function support of a USB device function
+ *
+ * Must be invoked when USB device is stopped.
+ */
+void usbdc_unregister_function(struct usbdf_driver *func)
+{
+ list_delete_element(&usbdc.func_list, func);
+}
+
+/**
+ * \brief Validate the descriptor
+ */
+int32_t usbdc_validate_desces(struct usbd_descriptors *desces)
+{
+ uint8_t *sod, *eod;
+ if (desces == NULL) {
+ return ERR_NOT_FOUND;
+ }
+ sod = usb_find_desc(desces->sod, desces->eod, USB_DT_DEVICE);
+ if (sod == NULL) {
+ return ERR_BAD_DATA;
+ }
+ sod = usb_find_desc(desces->sod, desces->eod, USB_DT_CONFIG);
+ if (sod == NULL) {
+ return ERR_BAD_DATA;
+ }
+ eod = sod + usb_cfg_desc_total_len(sod);
+ if (eod > desces->eod) {
+ return ERR_BAD_DATA;
+ }
+ return 0;
+}
+
+/**
+ * \brief Validate the descriptor
+ */
+int32_t usbdc_check_desces(struct usbdc_descriptors *desces)
+{
+#if CONF_USBD_HS_SP
+ int32_t rc;
+ if (desces->hs == NULL && desces->ls_fs == NULL) {
+ return ERR_NOT_FOUND;
+ }
+ if (desces->hs) {
+ rc = usbdc_validate_desces(desces->hs);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+#endif
+ return usbdc_validate_desces(desces->ls_fs);
+}
+
+/**
+ * \brief Start the USB device driver with specific descriptors set
+ */
+int32_t usbdc_start(struct usbd_descriptors *desces)
+{
+ if (usbdc.state >= USBD_S_POWER) {
+ return ERR_BUSY;
+ }
+
+ if (desces) {
+ usbdc.desces.ls_fs = desces;
+#if CONF_USBD_HS_SP
+ usbdc.desces.hs = &desces[1];
+#endif
+ } else {
+ return ERR_BAD_DATA;
+ }
+
+ usbdc.ctrl_size = desces->sod[7];
+ usbdc.state = USBD_S_POWER;
+ usb_d_enable();
+ return ERR_NONE;
+}
+
+/**
+ * \brief Stop the USB device driver
+ */
+int32_t usbdc_stop(void)
+{
+ usb_d_disable();
+ usbdc.state = USBD_S_OFF;
+ return ERR_NONE;
+}
+
+/**
+ * \brief Attach the USB device to host
+ */
+void usbdc_attach(void)
+{
+ usb_d_attach();
+}
+
+/**
+ * \brief Detach the USB device from host
+ */
+void usbdc_detach(void)
+{
+ usb_d_detach();
+}
+
+/**
+ * \brief Send remote wakeup to host
+ */
+void usbdc_remotewakeup(void)
+{
+ usb_d_send_remotewakeup();
+ usbdc.state = USBD_S_POWER;
+}
+
+/**
+ * \brief Return USB Device endpoint0 buffer
+ */
+uint8_t *usbdc_get_ctrl_buffer(void)
+{
+ return usbdc.ctrl_buf;
+}
+
+/**
+ * \brief Return current USB state
+ */
+uint8_t usbdc_get_state(void)
+{
+ if (usbdc.state & USBD_S_SUSPEND) {
+ return USBD_S_SUSPEND;
+ }
+ return usbdc.state;
+}
+
+/**
+ * \brief Return version
+ */
+uint32_t usbdc_get_version(void)
+{
+ return USBDC_VERSION;
+}
diff --git a/usb/device/usbdc.h b/usb/device/usbdc.h
new file mode 100644
index 0000000..f741939
--- /dev/null
+++ b/usb/device/usbdc.h
@@ -0,0 +1,249 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack Core Layer Definition.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#ifndef _USB_USBDC_H_
+#define _USB_USBDC_H_
+
+#include "usb_includes.h"
+#include "usb_protocol.h"
+#include "hal_usb_device.h"
+#include "usbd_config.h"
+
+/** USB device states. */
+enum usbd_state {
+ USBD_S_OFF = 0,
+ USBD_S_POWER = 1,
+ USBD_S_DEFAULT = 2,
+ USBD_S_ADDRESS = 3,
+ USBD_S_CONFIG = 4,
+ USBD_S_SUSPEND = 0x10
+};
+
+/** USB device core handler type. */
+enum usbdc_handler_type { USBDC_HDL_SOF, USBDC_HDL_REQ, USBDC_HDL_CHANGE };
+
+/** USB device core change notification type. */
+enum usbdc_change_type {
+ /** Change of connection, detected by vbus. */
+ USBDC_C_CONN,
+ /** Change of state, by RESET, SetAddress(), SetConfig(). */
+ USBDC_C_STATE,
+ /** Change of power. */
+ USBDC_C_POWER,
+ /** Change of remote wakeup setting. */
+ USBDC_C_REMOTE_WAKEUP
+};
+
+/** Power change. */
+enum usbdc_power_type { USBDC_ACTIVE, USBDC_SLEEP, USBDC_SUSPEND };
+
+/** USB device general function control code. */
+enum usbdf_control {
+ /** Enable the function.
+ * int32_t ctrl(usbdf, USBDF_ENABLE, struct usbd_descriptors *desc);
+ * Parameter holds interface descriptor and
+ * configuration descriptor end position.
+ */
+ USBDF_ENABLE,
+ /** Disable the function.
+ * int32_t ctrl(usbdf, USBDF_DISABLE, struct usbd_descriptors *desc);
+ * Parameter holds interface descriptor and
+ * configuration descriptor end position.
+ * Input NULL to force disable the function anyway.
+ */
+ USBDF_DISABLE,
+ /** Get interface alternate setting.
+ * int32_t ctrl(usbdf, USBDF_GET_IFACE, struct usb_req *req);
+ * Parameter holds interface number who should return
+ * the alternate setting.
+ */
+ USBDF_GET_IFACE
+};
+
+/** Describes a list of USB descriptors. */
+struct usbd_descriptors {
+ /** Pointer to Start of Descriptors. */
+ uint8_t *sod;
+ /** Pointer to End of Descriptors. */
+ uint8_t *eod;
+};
+
+/** Describes the USB device core descriptors. */
+struct usbdc_descriptors {
+ struct usbd_descriptors *ls_fs;
+#if CONF_USBD_HS_SP
+ struct usbd_descriptors *hs;
+#endif
+};
+
+/** Describes a list of core handler descriptor. */
+struct usbdc_handler {
+ /** Pointer to next handler. */
+ struct usbdc_handler *next;
+ /** Pointer to handler function. */
+ FUNC_PTR func;
+};
+
+/** Forward declaration for USB device function driver. */
+struct usbdf_driver;
+
+/** SOF handling function. */
+typedef void (*usbdc_sof_cb_t)(void);
+
+/** REQ handling function. */
+typedef int32_t (*usbdc_req_cb_t)(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage);
+
+/** Change notification callback function. */
+typedef void (*usbdc_change_cb_t)(enum usbdc_change_type change, uint32_t value);
+
+/** Control function for USB device general function driver. */
+typedef int32_t (*usbdf_control_cb_t)(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param);
+
+/** USB device general function driver descriptor. */
+struct usbdf_driver {
+ /** Pointer to next function.*/
+ struct usbdf_driver *next;
+ /** Pointer to control function.*/
+ usbdf_control_cb_t ctrl;
+ /** Pointer to function driver specific data. */
+ void *func_data;
+};
+
+/**
+ * \brief Register the handler
+ * \param[in] type USB device core handler type.
+ * \param[in] h Pointer to usb device core handler.
+ */
+void usbdc_register_handler(enum usbdc_handler_type type, const struct usbdc_handler *h);
+
+/**
+ * \brief Unregister the handler
+ * \param[in] type USB device core handler type.
+ * \param[in] h Pointer to usb device core handler.
+ */
+void usbdc_unregister_handler(enum usbdc_handler_type type, const struct usbdc_handler *h);
+
+/**
+ * \brief Initialize the USB device core driver
+ * \param[in] ctrl_buf Pointer to a buffer to be used by usb device ctrl endpoint
+ * Note: the size of ctrl_buf should not be less than the size of EP0
+ * \return Operation status.
+ */
+int32_t usbdc_init(uint8_t *ctrl_buf);
+
+/**
+ * \brief Deinitialize the USB device core driver
+ * \return Operation status.
+ */
+int32_t usbdc_deinit(void);
+
+/**
+ * \brief Register function support of a USB device function
+ * \param[in] func Pointer to usb device function driver structure
+ */
+void usbdc_register_function(struct usbdf_driver *func);
+
+/**
+ * \brief Unregister function support of a USB device function
+ * \param[in] func Pointer to usb device function driver structure
+ */
+void usbdc_unregister_function(struct usbdf_driver *func);
+
+/**
+ * \brief Validate the descriptors
+ * \param[in] desces Pointer to usb device core descriptors
+ * \return Operation status.
+ */
+int32_t usbdc_validate_desces(struct usbd_descriptors *desces);
+
+/**
+ * \brief Issue USB device data transfer
+ * \param[in] ep endpointer address.
+ * \param[in] buf Pointer to data transfer buffer.
+ * \param[in] size the size of data transfer.
+ * \param[in] zlp flag to indicate zero length packet.
+ * \return Operation status.
+ */
+int32_t usbdc_xfer(uint8_t ep, uint8_t *buf, uint32_t size, bool zlp);
+
+/**
+ * \brief Start the USB device driver with specific descriptors set
+ * \param[in] desces Pointer to usb device core descriptors (FS/LS),
+ * or pointer to array of core descriptors (HS), the
+ * very first one includes device descriptor, FS/LS
+ * configuration descriptor, string descriptor, and
+ * may include device qualifier and other speed
+ * configuration descriptor; the second one includes
+ * high speed used descriptors.
+ * Note that string descriptor should be included in
+ * first place.
+ * \return Operation status.
+ */
+int32_t usbdc_start(struct usbd_descriptors *desces);
+
+/**
+ * \brief Stop the USB device driver
+ * \return Operation status.
+ */
+int32_t usbdc_stop(void);
+
+/**
+ * \brief Attach the USB device to host
+ */
+void usbdc_attach(void);
+
+/**
+ * \brief Detach the USB device from host
+ */
+void usbdc_detach(void);
+
+/**
+ * \brief Send remote wakeup to host
+ */
+void usbdc_remotewakeup(void);
+
+/**
+ * \brief Return USB device ctrl end pointer buffer start address
+ */
+uint8_t *usbdc_get_ctrl_buffer(void);
+
+/**
+ * \brief Return current USB state
+ */
+uint8_t usbdc_get_state(void);
+
+/**
+ * \brief Return version
+ */
+uint32_t usbdc_get_version(void);
+
+#endif /* USBDC_H_ */
diff --git a/usb/usb_atmel.h b/usb/usb_atmel.h
new file mode 100644
index 0000000..d7bbe59
--- /dev/null
+++ b/usb/usb_atmel.h
@@ -0,0 +1,179 @@
+/**
+ * \file
+ *
+ * \brief All USB VIDs and PIDs from Atmel USB applications
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#ifndef _USB_ATMEL_H_
+#define _USB_ATMEL_H_
+
+/**
+ * \defgroup usb_group USB Stack
+ *
+ * This stack includes the USB Device Stack, USB Host Stack and common
+ * definitions.
+ * @{
+ */
+
+//! @}
+
+/**
+ * \ingroup usb_group
+ * \defgroup usb_atmel_ids_group Atmel USB Identifiers
+ *
+ * This module defines Atmel PID and VIDs constants.
+ *
+ * @{
+ */
+
+//! \name Vendor Identifier assigned by USB org to ATMEL
+#define USB_VID_ATMEL 0x03EB
+
+//! \name Product Identifier assigned by ATMEL to AVR applications
+//! @{
+
+//! \name The range from 2000h to 20FFh is reserved to the old PID for C51, MEGA, and others.
+//! @{
+#define USB_PID_ATMEL_MEGA_HIDGENERIC 0x2013
+#define USB_PID_ATMEL_MEGA_HIDKEYBOARD 0x2017
+#define USB_PID_ATMEL_MEGA_CDC 0x2018
+#define USB_PID_ATMEL_MEGA_AUDIO_IN 0x2019
+#define USB_PID_ATMEL_MEGA_MS 0x201A
+#define USB_PID_ATMEL_MEGA_AUDIO_IN_OUT 0x201B
+#define USB_PID_ATMEL_MEGA_HIDMOUSE 0x201C
+#define USB_PID_ATMEL_MEGA_HIDMOUSE_CERTIF_U4 0x201D
+#define USB_PID_ATMEL_MEGA_CDC_MULTI 0x201E
+#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_USBKEY 0x2022
+#define USB_PID_ATMEL_MEGA_MS_HIDMS_HID_STK525 0x2023
+#define USB_PID_ATMEL_MEGA_MS_2 0x2029
+#define USB_PID_ATMEL_MEGA_MS_HIDMS 0x202A
+#define USB_PID_ATMEL_MEGA_MS_3 0x2032
+#define USB_PID_ATMEL_MEGA_LIBUSB 0x2050
+//! @}
+
+//! \name The range 2100h to 21FFh is reserved to PIDs for AVR Tools.
+//! @{
+#define USB_PID_ATMEL_XPLAINED 0x2122
+#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_2_4GHZ 0x214A
+#define USB_PID_ATMEL_XMEGA_USB_ZIGBIT_SUBGHZ 0x214B
+//! @}
+
+//! \name The range 2300h to 23FFh is reserved to PIDs for demo from ASF1.7=>
+//! @{
+#define USB_PID_ATMEL_UC3_ENUM 0x2300
+#define USB_PID_ATMEL_UC3_MS 0x2301
+#define USB_PID_ATMEL_UC3_MS_SDRAM_LOADER 0x2302
+#define USB_PID_ATMEL_UC3_EVK1100_CTRLPANEL 0x2303
+#define USB_PID_ATMEL_UC3_HID 0x2304
+#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID 0x2305
+#define USB_PID_ATMEL_UC3_EVK1101_CTRLPANEL_HID_MS 0x2306
+#define USB_PID_ATMEL_UC3_CDC 0x2307
+#define USB_PID_ATMEL_UC3_AUDIO_MICRO 0x2308
+#define USB_PID_ATMEL_UC3_CDC_DEBUG 0x2310 // Virtual Com (debug interface) on EVK11xx
+#define USB_PID_ATMEL_UC3_AUDIO_SPEAKER_MICRO 0x2311
+#define USB_PID_ATMEL_UC3_CDC_MSC 0x2312
+//! @}
+
+//! \name The range 2400h to 24FFh is reserved to PIDs for ASF applications
+//! @{
+#define USB_PID_ATMEL_ASF_HIDMOUSE 0x2400
+#define USB_PID_ATMEL_ASF_HIDKEYBOARD 0x2401
+#define USB_PID_ATMEL_ASF_HIDGENERIC 0x2402
+#define USB_PID_ATMEL_ASF_MSC 0x2403
+#define USB_PID_ATMEL_ASF_CDC 0x2404
+#define USB_PID_ATMEL_ASF_PHDC 0x2405
+#define USB_PID_ATMEL_ASF_HIDMTOUCH 0x2406
+#define USB_PID_ATMEL_ASF_MSC_HIDMOUSE 0x2420
+#define USB_PID_ATMEL_ASF_MSC_HIDS_CDC 0x2421
+#define USB_PID_ATMEL_ASF_MSC_HIDKEYBOARD 0x2422
+#define USB_PID_ATMEL_ASF_VENDOR_CLASS 0x2423
+#define USB_PID_ATMEL_ASF_MSC_CDC 0x2424
+#define USB_PID_ATMEL_ASF_TWO_CDC 0x2425
+#define USB_PID_ATMEL_ASF_SEVEN_CDC 0x2426
+#define USB_PID_ATMEL_ASF_XPLAIN_BC_POWERONLY 0x2430
+#define USB_PID_ATMEL_ASF_XPLAIN_BC_TERMINAL 0x2431
+#define USB_PID_ATMEL_ASF_XPLAIN_BC_TOUCH 0x2432
+#define USB_PID_ATMEL_ASF_AUDIO_SPEAKER 0x2433
+#define USB_PID_ATMEL_ASF_XMEGA_B1_XPLAINED 0x2434
+//! @}
+
+//! \name The range 2F00h to 2FFFh is reserved to official PIDs for AVR bootloaders
+//! Note, !!!! don't use this range for demos or examples !!!!
+//! @{
+#define USB_PID_ATMEL_DFU_ATXMEGA64C3 0x2FD6
+#define USB_PID_ATMEL_DFU_ATXMEGA128C3 0x2FD7
+#define USB_PID_ATMEL_DFU_ATXMEGA16C4 0x2FD8
+#define USB_PID_ATMEL_DFU_ATXMEGA32C4 0x2FD9
+#define USB_PID_ATMEL_DFU_ATXMEGA256C3 0x2FDA
+#define USB_PID_ATMEL_DFU_ATXMEGA384C3 0x2FDB
+#define USB_PID_ATMEL_DFU_ATUCL3_L4 0x2FDC
+#define USB_PID_ATMEL_DFU_ATXMEGA64A4U 0x2FDD
+#define USB_PID_ATMEL_DFU_ATXMEGA128A4U 0x2FDE
+
+#define USB_PID_ATMEL_DFU_ATXMEGA64B3 0x2FDF
+#define USB_PID_ATMEL_DFU_ATXMEGA128B3 0x2FE0
+#define USB_PID_ATMEL_DFU_ATXMEGA64B1 0x2FE1
+#define USB_PID_ATMEL_DFU_ATXMEGA256A3BU 0x2FE2
+#define USB_PID_ATMEL_DFU_ATXMEGA16A4U 0x2FE3
+#define USB_PID_ATMEL_DFU_ATXMEGA32A4U 0x2FE4
+#define USB_PID_ATMEL_DFU_ATXMEGA64A3U 0x2FE5
+#define USB_PID_ATMEL_DFU_ATXMEGA128A3U 0x2FE6
+#define USB_PID_ATMEL_DFU_ATXMEGA192A3U 0x2FE7
+#define USB_PID_ATMEL_DFU_ATXMEGA64A1U 0x2FE8
+#define USB_PID_ATMEL_DFU_ATUC3D 0x2FE9
+#define USB_PID_ATMEL_DFU_ATXMEGA128B1 0x2FEA
+#define USB_PID_ATMEL_DFU_AT32UC3C 0x2FEB
+#define USB_PID_ATMEL_DFU_ATXMEGA256A3U 0x2FEC
+#define USB_PID_ATMEL_DFU_ATXMEGA128A1U 0x2FED
+#define USB_PID_ATMEL_DFU_ATMEGA8U2 0x2FEE
+#define USB_PID_ATMEL_DFU_ATMEGA16U2 0x2FEF
+#define USB_PID_ATMEL_DFU_ATMEGA32U2 0x2FF0
+#define USB_PID_ATMEL_DFU_AT32UC3A3 0x2FF1
+#define USB_PID_ATMEL_DFU_ATMEGA32U6 0x2FF2
+#define USB_PID_ATMEL_DFU_ATMEGA16U4 0x2FF3
+#define USB_PID_ATMEL_DFU_ATMEGA32U4 0x2FF4
+#define USB_PID_ATMEL_DFU_AT32AP7200 0x2FF5
+#define USB_PID_ATMEL_DFU_AT32UC3B 0x2FF6
+#define USB_PID_ATMEL_DFU_AT90USB82 0x2FF7
+#define USB_PID_ATMEL_DFU_AT32UC3A 0x2FF8
+#define USB_PID_ATMEL_DFU_AT90USB64 0x2FF9
+#define USB_PID_ATMEL_DFU_AT90USB162 0x2FFA
+#define USB_PID_ATMEL_DFU_AT90USB128 0x2FFB
+// 2FFCh to 2FFFh used by C51 family products
+//! @}
+
+//! @}
+
+//! @}
+
+#endif // _USB_ATMEL_H_
diff --git a/usb/usb_debug.h b/usb/usb_debug.h
new file mode 100644
index 0000000..b20c356
--- /dev/null
+++ b/usb/usb_debug.h
@@ -0,0 +1,41 @@
+/**
+ * \file
+ *
+ * \brief USB Debug Files.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#ifndef _USB_DEBUG_H_
+#define _USB_DEBUG_H_
+
+#define udbg_print(...)
+
+#endif
diff --git a/usb/usb_includes.h b/usb/usb_includes.h
new file mode 100644
index 0000000..bcf99f7
--- /dev/null
+++ b/usb/usb_includes.h
@@ -0,0 +1,131 @@
+/**
+ * \file
+ *
+ * \brief USB Include Header Files.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#ifndef _USB_INCLUDES_H_
+#define _USB_INCLUDES_H_
+
+#ifdef USB_USER_INCLUDES
+
+#include "usb_user_includes.h"
+
+#else
+/* Include START headers */
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <utils.h>
+#include <utils_list.h>
+#include <utils_assert.h>
+#include <hal_atomic.h>
+
+typedef uint16_t le16_t;
+typedef uint32_t le32_t;
+typedef uint16_t be16_t;
+typedef uint32_t be32_t;
+
+#if (defined __GNUC__) || (defined __CC_ARM)
+#define is_constant(exp) __builtin_constant_p(exp)
+#else
+#define is_constant(exp) (0)
+#endif
+
+/*! \brief Toggles the endianism of \a u16 (by swapping its bytes).
+ *
+ * \param u16 U16 of which to toggle the endianism.
+ *
+ * \return Value resulting from \a u16 with toggled endianism.
+ *
+ * \note More optimized if only used with values known at compile time.
+ */
+#define swap_u16(u16) ((uint16_t)(((uint16_t)(u16) >> 8) | ((uint16_t)(u16) << 8)))
+
+/*! \brief Toggles the endianism of \a u32 (by swapping its bytes).
+ *
+ * \param u32 U32 of which to toggle the endianism.
+ *
+ * \return Value resulting from \a u32 with toggled endianism.
+ *
+ * \note More optimized if only used with values known at compile time.
+ */
+#if (defined __GNUC__)
+#define swap_u32(u32) \
+ (is_constant(u32) \
+ ? ((uint32_t)(((uint32_t)swap_u16((uint32_t)(u32) >> 16)) | ((uint32_t)swap_u16((uint32_t)(u32)) << 16))) \
+ : ((uint32_t)__builtin_bswap32((uint32_t)(u32))))
+#else
+#define swap_u32(u32) \
+ ((uint32_t)(((uint32_t)swap_u16((uint32_t)(u32) >> 16)) | ((uint32_t)swap_u16((uint32_t)(u32)) << 16)))
+#endif
+
+/** Get a value from/to LE16 data */
+#define LE16(x) (x)
+/** Get a value from/to LE32 data */
+#define LE32(x) (x)
+/** Get a value from/to BE16 data */
+#define BE16(x) swap_u16(x)
+/** Get a value from/to BE32 data */
+#define BE32(x) swap_u32(x)
+
+/** Get byte 0 for BE 16-bit value */
+#define BE16B0(a) ((uint8_t)((a) >> 8))
+/** Get byte 1 for BE 16-bit value */
+#define BE16B1(a) ((uint8_t)((a) >> 0))
+
+/** Get byte 0 for BE 32-bit value */
+#define BE32B0(a) ((uint8_t)((a) >> 24))
+/** Get byte 1 for BE 32-bit value */
+#define BE32B1(a) ((uint8_t)((a) >> 16))
+/** Get byte 2 for BE 32-bit value */
+#define BE32B2(a) ((uint8_t)((a) >> 8))
+/** Get byte 3 for BE 32-bit value */
+#define BE32B3(a) ((uint8_t)((a) >> 0))
+
+/** Get byte 0 for LE 16-bit value */
+#define LE16B0(a) ((uint8_t)((a) >> 0))
+/** Get byte 1 for LE 16-bit value */
+#define LE16B1(a) ((uint8_t)((a) >> 8))
+
+/** Get byte 0 for LE 32-bit value */
+#define LE32B0(a) ((uint8_t)((a) >> 0))
+/** Get byte 1 for LE 32-bit value */
+#define LE32B1(a) ((uint8_t)((a) >> 8))
+/** Get byte 2 for LE 32-bit value */
+#define LE32B2(a) ((uint8_t)((a) >> 16))
+/** Get byte 3 for LE 32-bit value */
+#define LE32B3(a) ((uint8_t)((a) >> 24))
+
+#endif /* USB_USER_INCLUDES */
+
+#endif /* _USB_INCLUDES_H_ */
diff --git a/usb/usb_protocol.c b/usb/usb_protocol.c
new file mode 100644
index 0000000..9f6323e
--- /dev/null
+++ b/usb/usb_protocol.c
@@ -0,0 +1,161 @@
+/**
+ * \file
+ *
+ * \brief USB protocol implementation.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#define CONF_NO_ASSERT_CHECK
+
+#include "usb_protocol.h"
+
+#ifdef CONF_NO_ASSERT_CHECK
+#define _param_error_check(cond)
+#define _desc_len_check() \
+ if (usb_desc_len(desc) < 2) { \
+ /* Encounter an invalid descriptor. */ \
+ return NULL; \
+ }
+#else
+#define _param_error_check(cond) ASSERT(cond)
+#define _desc_len_check() ASSERT(usb_desc_len(desc) >= 2)
+#endif
+
+uint8_t *usb_find_desc(uint8_t *desc, uint8_t *eof, uint8_t type)
+{
+ _param_error_check(desc && eof && (desc < eof));
+
+ while (desc < eof) {
+ _desc_len_check();
+ if (type == usb_desc_type(desc)) {
+ return desc;
+ }
+ desc = usb_desc_next(desc);
+ }
+ return NULL;
+}
+
+uint8_t *usb_find_iface_after(uint8_t *desc, uint8_t *eof, uint8_t iface_n)
+{
+ _param_error_check(desc && eof && (desc < eof));
+
+ while (desc < eof) {
+ _desc_len_check();
+ if (USB_DT_INTERFACE == usb_desc_type(desc)) {
+ if (iface_n != desc[2]) {
+ return desc;
+ }
+ }
+ desc = usb_desc_next(desc);
+ }
+ return eof;
+}
+
+uint8_t *usb_find_ep_desc(uint8_t *desc, uint8_t *eof)
+{
+ _param_error_check(desc && eof && (desc < eof));
+
+ while (desc < eof) {
+ _desc_len_check();
+ if (USB_DT_INTERFACE == usb_desc_type(desc)) {
+ break;
+ }
+ if (USB_DT_ENDPOINT == usb_desc_type(desc)) {
+ return desc;
+ }
+ desc = usb_desc_next(desc);
+ }
+ return NULL;
+}
+
+uint8_t *usb_find_cfg_desc(uint8_t *desc, uint8_t *eof, uint8_t cfg_value)
+{
+ _param_error_check(desc && eof && (desc < eof));
+
+ desc = usb_find_desc(desc, eof, USB_DT_CONFIG);
+ if (!desc) {
+ return NULL;
+ }
+ while (desc < eof) {
+ _desc_len_check();
+ if (desc[1] != USB_DT_CONFIG) {
+ break;
+ }
+ if (desc[5] == cfg_value) {
+ return desc;
+ }
+ desc = usb_cfg_desc_next(desc);
+ }
+ return NULL;
+}
+
+uint8_t *usb_find_othspdcfg_desc(uint8_t *desc, uint8_t *eof, uint8_t cfg_value)
+{
+ _param_error_check(desc && eof && (desc < eof));
+
+ desc = usb_find_desc(desc, eof, USB_DT_OTHER_SPEED_CONFIG);
+ if (!desc) {
+ return NULL;
+ }
+ while (desc < eof) {
+ _desc_len_check();
+ if (desc[1] != USB_DT_OTHER_SPEED_CONFIG) {
+ break;
+ }
+ if (desc[5] == cfg_value) {
+ return desc;
+ }
+ desc = usb_cfg_desc_next(desc);
+ }
+ return NULL;
+}
+
+uint8_t *usb_find_str_desc(uint8_t *desc, uint8_t *eof, uint8_t str_index)
+{
+ uint8_t i;
+
+ _param_error_check(desc && eof && (desc < eof));
+
+ for (i = 0; desc < eof;) {
+ desc = usb_find_desc(desc, eof, USB_DT_STRING);
+ if (desc) {
+ _desc_len_check();
+ if (i == str_index) {
+ return desc;
+ }
+ i++;
+ desc = usb_desc_next(desc);
+ } else {
+ return NULL;
+ }
+ }
+ return NULL;
+}
diff --git a/usb/usb_protocol.h b/usb/usb_protocol.h
new file mode 100644
index 0000000..35e2833
--- /dev/null
+++ b/usb/usb_protocol.h
@@ -0,0 +1,782 @@
+/**
+ * \file
+ *
+ * \brief USB protocol definitions.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ */
+
+#ifndef _USB_PROTOCOL_H_
+#define _USB_PROTOCOL_H_
+
+#include "usb_includes.h"
+
+/**
+ * \ingroup usb_group
+ * \defgroup usb_protocol_group USB Protocol Definitions
+ *
+ * This module defines constants and data structures provided by the USB
+ * 2.0 specification.
+ *
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __CC_ARM
+#pragma anon_unions
+#endif
+
+/*! Value for field bcdUSB */
+#define USB_V2_0 (0x0200) /*!< USB Specification version 2.00 */
+#define USB_V2_1 (0x0201) /*!< USB Specification version 2.01 (support BOS) */
+
+/*! \name Generic definitions (Class, subclass and protocol)
+ */
+/*! @{ */
+#define USB_CLASS_NO (0x00)
+#define USB_SUBCLASS_NO (0x00)
+#define USB_PROTOCOL_NO (0x00)
+/*! @} */
+
+/*! \name IAD (Interface Association Descriptor) constants */
+/*! @{ */
+#define USB_CLASS_IAD (0xEF)
+#define USB_SUBCLASS_IAD (0x02)
+#define USB_PROTOCOL_IAD (0x01)
+/*! @} */
+
+/**
+ * \brief USB request data transfer direction (bmRequestType)
+ */
+#define USB_REQT_DIR_OUT (0 << 7) /*!< Host to device */
+#define USB_REQT_DIR_H2D (0 << 7) /*!< Host to device */
+#define USB_REQT_DIR_IN (1 << 7) /*!< Device to host */
+#define USB_REQT_DIR_D2H (1 << 7) /*!< Device to host */
+#define USB_REQT_DIR_MASK (1 << 7) /*!< Mask */
+
+/**
+ * \brief USB request types (bmRequestType)
+ */
+#define USB_REQT_TYPE_STANDARD (0 << 5) /*!< Standard request */
+#define USB_REQT_TYPE_CLASS (1 << 5) /*!< Class-specific request */
+#define USB_REQT_TYPE_VENDOR (2 << 5) /*!< Vendor-specific request */
+#define USB_REQT_TYPE_MASK (3 << 5) /*!< Mask */
+
+/**
+ * \brief USB recipient codes (bmRequestType)
+ */
+#define USB_REQT_RECIP_DEVICE (0 << 0) /*!< Recipient device */
+#define USB_REQT_RECIP_INTERFACE (1 << 0) /*!< Recipient interface */
+#define USB_REQT_RECIP_ENDPOINT (2 << 0) /*!< Recipient endpoint */
+#define USB_REQT_RECIP_OTHER (3 << 0) /*!< Recipient other */
+#define USB_REQT_RECIP_MASK (0x1F) /*!< Mask */
+
+/**
+ * \brief Standard USB control transfer stages.
+ */
+enum usb_ctrl_stage { USB_SETUP_STAGE = 0, USB_DATA_STAGE = 1, USB_STATUS_STAGE = 2 };
+
+/**
+ * \brief Standard USB requests (bRequest)
+ */
+enum usb_req_code {
+ USB_REQ_GET_STATUS = 0,
+ USB_REQ_CLEAR_FTR = 1,
+ USB_REQ_SET_FTR = 3,
+ USB_REQ_SET_ADDRESS = 5,
+ USB_REQ_GET_DESC = 6,
+ USB_REQ_SET_DESC = 7,
+ USB_REQ_GET_CONFIG = 8,
+ USB_REQ_SET_CONFIG = 9,
+ USB_REQ_GET_INTERFACE = 10,
+ USB_REQ_SET_INTERFACE = 11,
+ USB_REQ_SYNCH_FRAME = 12,
+ USB_REQ_SET_SEL = 48,
+ USB_REQ_ISOCH_DELAY = 49
+};
+
+/**
+ * \brief Standard USB device status flags
+ *
+ */
+enum usb_dev_status {
+ USB_DEV_STAT_BUS_POWERED = 0,
+ USB_DEV_STAT_SELF_POWERED = 1,
+ USB_DEV_STAT_REMOTEWAKEUP = 2,
+ USB_DEV_STAT_U1_ENABLE = 4,
+ USB_DEV_STAT_U2_ENABLE = 8,
+ USB_DEV_STAT_LTM_ENABLE = 16
+};
+
+/**
+ * \brief Standard USB Interface status flags
+ *
+ */
+enum usb_interface_status {
+ USB_IFACE_STAT_RESERVED = 0,
+ USB_IFACE_STAT_REMOTEWAKE_CAP = 1,
+ USB_IFACE_STAT_REMOTEWAKE = 2
+};
+
+/**
+ * \brief Standard USB endpoint status flags
+ *
+ */
+enum usb_endpoint_status { USB_EP_STAT_HALT = 1 };
+
+/**
+ * \brief Standard USB device feature flags
+ *
+ * \note valid for SetFeature request.
+ */
+enum usb_device_feature {
+ USB_DEV_FTR_REMOTE_WAKEUP = 1, /*!< Remote wakeup enabled */
+ USB_DEV_FTR_TEST_MODE = 2, /*!< USB test mode */
+ USB_DEV_FTR_OTG_B_HNP_ENABLE = 3,
+ USB_DEV_FTR_OTG_A_HNP_SP = 4,
+ USB_DEV_FTR_OTG_A_ALT_HNP_SP = 5,
+ USB_DEV_FTR_U1_ENABLE = 48,
+ USB_DEV_FTR_U2_ENABLE = 49,
+ USB_DEV_FTR_LTM_ENABLE = 50
+};
+
+/**
+ * \brief Test Mode possible on HS USB device
+ *
+ * \note valid for USB_DEV_FTR_TEST_MODE request.
+ */
+enum usb_device_hs_test_mode {
+ USB_DEV_TEST_MODE_J = 1,
+ USB_DEV_TEST_MODE_K = 2,
+ USB_DEV_TEST_MODE_SE0_NAK = 3,
+ USB_DEV_TEST_MODE_PACKET = 4,
+ USB_DEV_TEST_MODE_FORCE_ENABLE = 5
+};
+
+/**
+ * \brief Standard Feature Selectors for Interface
+ */
+enum usb_iface_feature { USB_IFACE_FTR_FUNC_SUSP = 0 };
+
+/**
+ * \brief Standard USB endpoint feature/status flags
+ */
+enum usb_endpoint_feature { USB_EP_FTR_HALT = 0 };
+
+/**
+ * \brief Standard USB Test Mode Selectors
+ */
+enum usb_test_mode_selector {
+ USB_TEST_J = 0x01,
+ USB_TEST_K = 0x02,
+ USB_TEST_SE0_NAK = 0x03,
+ USB_TEST_PACKET = 0x04,
+ USB_TEST_FORCE_ENABLE = 0x05
+};
+
+/**
+ * \brief Standard USB descriptor types
+ */
+enum usb_descriptor_type {
+ USB_DT_DEVICE = 1,
+ USB_DT_CONFIG = 2,
+ USB_DT_STRING = 3,
+ USB_DT_INTERFACE = 4,
+ USB_DT_ENDPOINT = 5,
+ USB_DT_DEVICE_QUALIFIER = 6,
+ USB_DT_OTHER_SPEED_CONFIG = 7,
+ USB_DT_INTERFACE_POWER = 8,
+ USB_DT_OTG = 9,
+ USB_DT_DEBUG = 10,
+ USB_DT_IAD = 11,
+ USB_DT_BOS = 15,
+ USB_DT_DEV_CAP = 16,
+ USB_DT_SS_EP_COMPANION = 48
+};
+
+/**
+ * \brief Capability types
+ */
+enum usb_capability_type {
+ USB_CAPT_WIRELESS = 1,
+ USB_CAPT_2_0_EXT = 2,
+ USB_CAPT_SUPER_SPEED = 3,
+ USB_CAPT_CONTAINER_ID = 4
+};
+
+/**
+ * \brief USB 2.0 Extension attributes
+ */
+enum usb_2_0_ext_attr { USB_2_0_EXT_LPM_SP = 1 };
+
+/**
+ * \brief USB SuperSpeed Capability attributes
+ */
+enum usb_ss_cap_attr { USB_SS_LTM_SP };
+
+/**
+ * \brief USB Speed Supports
+ */
+enum usb_speed_sp {
+ USB_SPEED_LOW_SP = 1,
+ USB_SPEED_LS_SP = 1,
+ USB_SPEED_FULL_SP = 2,
+ USB_SPEED_FS_SP = 2,
+ USB_SPEED_HIGH_SP = 4,
+ USB_SPEED_HS_SP = 4,
+ USB_SPEED_SUPER_SP = 8,
+ USB_SPEED_SS_SP = 8
+};
+
+/**
+ * \brief Standard USB endpoint transfer types
+ */
+enum usb_ep_type {
+ USB_EP_TYPE_CONTROL = 0x00,
+ USB_EP_TYPE_ISOCHRONOUS = 0x01,
+ USB_EP_TYPE_BULK = 0x02,
+ USB_EP_TYPE_INTERRUPT = 0x03,
+ USB_EP_TYPE_MASK = 0x03u
+};
+
+/**
+ * \brief USB endpoint interrupt types
+ */
+enum usb_ep_int_type { USB_EP_INT_T_PERIODIC = 0x00u, USB_EP_INT_T_NOTIFICATION = 0x01u, USB_EP_INT_T_MASK = 0x03u };
+
+/**
+ * \brief Standard USB endpoint synchronization types
+ */
+enum usb_ep_sync_type {
+ USB_EP_SYNC_T_NO = 0x00u,
+ USB_EP_SYNC_T_ASYNC = 0x02u,
+ USB_EP_SYNC_T_ADAPTIVE = 0x02u,
+ USB_EP_SYNC_T_SYNC = 0x03u,
+ USB_EP_SYNC_T_MASK = 0x03u
+};
+
+/**
+ * \brief Standard USB endpoint usage types
+ */
+enum usb_ep_usage_type {
+ USB_EP_USAGE_T_DATA = 0x00u,
+ USB_EP_USAGE_T_FEEDBACK = 0x01u,
+ USB_EP_USAGE_T_FEEDBACK_DATA = 0x02u,
+ USB_EP_USAGE_T_MASK = 0x03u
+};
+
+/**
+ * \brief Standard USB language IDs for string descriptors
+ */
+enum usb_langid {
+ USB_LANGID_EN_US = 0x0409 /*!< English (United States) */
+};
+
+/**
+ * \brief Mask selecting the index part of an endpoint address
+ */
+#define USB_EP_ADDR_MASK 0x0f
+/**
+ * \brief Endpoint transfer direction is IN
+ */
+#define USB_EP_DIR_IN 0x80
+/**
+ * \brief Endpoint transfer direction is OUT
+ */
+#define USB_EP_DIR_OUT 0x00
+
+/**
+ * \brief Maximum length in bytes of a USB descriptor
+ *
+ * The maximum length of a USB descriptor is limited by the 8-bit
+ * bLength field.
+ */
+#define USB_DESC_LEN_MAX 255
+
+/*
+ * 2-byte alignment requested for all USB structures.
+ */
+COMPILER_PACK_SET(1)
+
+/**
+ * \brief A USB Device SETUP request
+ *
+ * The data payload of SETUP packets always follows this structure.
+ */
+typedef struct usb_req {
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ union {
+ le16_t wValue;
+ struct {
+ uint8_t l;
+ uint8_t h;
+ } wValueBytes;
+ };
+ union {
+ le16_t wIndex;
+ struct {
+ uint8_t l;
+ uint8_t h;
+ } wIndexBytes;
+ };
+ union {
+ le16_t wLength;
+ struct {
+ uint8_t l;
+ uint8_t h;
+ } wLengthBytes;
+ };
+} usb_req_t;
+
+/**
+ * \brief Standard USB device descriptor structure
+ */
+typedef struct usb_dev_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ le16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ le16_t idVendor;
+ le16_t idProduct;
+ le16_t bcdDevice;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+ uint8_t bNumConfigurations;
+} usb_dev_desc_t;
+
+/**
+ * \brief Binary device Object Store (BOS) descriptor structure
+ */
+typedef struct usb_bos_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ le16_t wTotalLength;
+ uint8_t bNumDeviceCaps;
+} usb_bos_desc_t;
+
+/**
+ * \brief Device Capability Descriptor structure
+ */
+typedef struct usb_cap_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t Vars[1];
+} usb_cap_desc_t;
+
+/**
+ * \brief USB 2.0 Extension Descriptor structure
+ */
+typedef struct usb_2_0_ext {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint32_t bmAttributes;
+} usb_2_0_ext_t;
+
+/**
+ * \brief LPM Device Capabilities descriptor structure
+ */
+typedef struct usb_2_0_ext usb_lpm_cap_desc_t;
+
+/**
+ * \brief SuperSpeed USB Device Capability structure
+ */
+typedef struct usb_ss_cap_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t bmAttributes;
+ le16_t wSpeedsSupported;
+ uint8_t bFunctionalitySupport;
+ uint8_t bU1DevExitLat;
+ uint8_t bU2DevExitLat;
+} usb_ss_cap_desc_t;
+
+/**
+ * \brief USB Container ID Descriptor structure
+ */
+typedef struct usb_container_id_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t bReserved;
+ uint8_t ContainerID[16];
+} usb_container_id_desc_t;
+
+/**
+ * \brief Standard USB device qualifier descriptor structure
+ *
+ * This descriptor contains information about the device when running at
+ * the "other" speed (i.e. if the device is currently operating at high
+ * speed, this descriptor can be used to determine what would change if
+ * the device was operating at full speed.)
+ */
+typedef struct usb_dev_qual_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ le16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ uint8_t bNumConfigurations;
+ uint8_t bReserved;
+} usb_dev_qual_desc_t;
+
+/**
+ * \brief Standard USB configuration descriptor structure
+ */
+typedef struct usb_config_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ le16_t wTotalLength;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+} usb_config_desc_t;
+
+#define USB_CONFIG_ATTR_MUST_SET (1 << 7) /*!< Must always be set */
+#define USB_CONFIG_ATTR_BUS_POWERED (0 << 6) /*!< Bus-powered */
+#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6) /*!< Self-powered */
+#define USB_CONFIG_ATTR_REMOTE_WAKEUP (1 << 5) /*!< remote wakeup supported */
+
+#define USB_CONFIG_MAX_POWER(ma) (((ma) + 1) / 2) /*!< Max power in mA */
+
+/**
+ * \brief Standard USB association descriptor structure
+ */
+typedef struct usb_iad_desc {
+ uint8_t bLength; /*!< Size of this descriptor in bytes */
+ uint8_t bDescriptorType; /*!< Interface descriptor type */
+ uint8_t bFirstInterface; /*!< Number of interface */
+ uint8_t bInterfaceCount; /*!< value to select alternate setting */
+ uint8_t bFunctionClass; /*!< Class code assigned by the USB */
+ uint8_t bFunctionSubClass; /*!< Sub-class code assigned by the USB */
+ uint8_t bFunctionProtocol; /*!< Protocol code assigned by the USB */
+ uint8_t iFunction; /*!< Index of string descriptor */
+} usb_iad_desc_t;
+
+/**
+ * \brief Standard USB interface descriptor structure
+ */
+typedef struct usb_iface_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+} usb_iface_desc_t;
+
+/**
+ * \brief Standard USB endpoint descriptor structure
+ */
+typedef struct usb_ep_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ le16_t wMaxPacketSize;
+ uint8_t bInterval;
+} usb_ep_desc_t;
+
+/**
+ * \brief SuperSpeed Endpoint Companion descriptor structure
+ */
+typedef struct usb_ss_ep_comp_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bMaxBurst;
+ uint8_t bmAttributes;
+ le16_t wBytesPerInterval;
+} usb_ss_ep_comp_desc_t;
+
+/**
+ * \brief LPM Token bmAttributes structure
+ */
+typedef struct usb_lpm_attributes {
+ uint8_t bLinkState : 4;
+ uint8_t HIRD : 4;
+ uint8_t bRemoteWake : 1;
+ uint8_t Reserved : 2;
+} usb_lpm_attributes_t;
+
+/**
+ * \brief A standard USB string descriptor structure
+ */
+typedef struct usb_str_desc {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+} usb_str_desc_t;
+
+typedef struct usb_str_langid_desc {
+ usb_str_desc_t desc;
+ le16_t string[1];
+} usb_str_langid_desc_t;
+
+COMPILER_PACK_RESET()
+
+/** \name Macros to build USB standard descriptors */
+/*@{*/
+
+/** Build bytes for USB device descriptor. */
+#define USB_DEV_DESC_BYTES(bcdUSB, \
+ bDeviceClass, \
+ bDeviceSubClass, \
+ bDeviceProtocol, \
+ bMaxPacketSize0, \
+ idVendor, \
+ idProduct, \
+ bcdDevice, \
+ iManufacturer, \
+ iProduct, \
+ iSerialNumber, \
+ bNumConfigurations) \
+ 18, /* bLength */ \
+ 0x01, /* bDescriptorType: DEVICE */ \
+ LE_BYTE0(bcdUSB), LE_BYTE1(bcdUSB), bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, \
+ LE_BYTE0(idVendor), LE_BYTE1(idVendor), LE_BYTE0(idProduct), LE_BYTE1(idProduct), LE_BYTE0(bcdDevice), \
+ LE_BYTE1(bcdDevice), iManufacturer, iProduct, iSerialNumber, bNumConfigurations
+
+#define USB_DEV_QUAL_DESC_BYTES( \
+ bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, bNumConfigurations) \
+ 10, /* bLength */ \
+ USB_DT_DEVICE_QUALIFIER, /* bDescriptorType: DEVICE_QUALIFIER */ \
+ LE_BYTE0(bcdUSB), LE_BYTE1(bcdUSB), bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0, \
+ bNumConfigurations, 0
+
+#define USB_DEV_DESC_LEN 18
+
+/** Build bytes for USB configuration descriptor. */
+#define USB_CONFIG_DESC_BYTES( \
+ wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration, bmAttributes, bMaxPower) \
+ 9, /* bLength */ \
+ 0x02, /* bDescriptorType: CONFIGURATION */ \
+ LE_BYTE0(wTotalLength), LE_BYTE1(wTotalLength), bNumInterfaces, bConfigurationValue, iConfiguration, \
+ bmAttributes, bMaxPower
+
+#define USB_OTH_SPD_CFG_DESC_BYTES( \
+ wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration, bmAttributes, bMaxPower) \
+ 9, /* bLength */ \
+ USB_DT_OTHER_SPEED_CONFIG, /* bDescriptorType: OTH_SPD_CONFIGURATION */ \
+ LE_BYTE0(wTotalLength), LE_BYTE1(wTotalLength), bNumInterfaces, bConfigurationValue, iConfiguration, \
+ bmAttributes, bMaxPower
+
+#define USB_CONFIG_DESC_LEN 9
+
+/** Build bytes for USB IAD descriptor. */
+#define USB_IAD_DESC_BYTES( \
+ bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol, iFunction) \
+ 8, /* bLength */ \
+ USB_DT_IAD, /* bDescriptorType */ \
+ bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol, iFunction
+
+#define USB_IAD_DESC_LEN 8
+
+/** Build bytes for USB interface descriptor. */
+#define USB_IFACE_DESC_BYTES(bInterfaceNumber, \
+ bAlternateSetting, \
+ bNumEndpoints, \
+ bInterfaceClass, \
+ bInterfaceSubClass, \
+ bInterfaceProtocol, \
+ iInterface) \
+ 9, /* bLength */ \
+ 0x04, /* bDescriptorType: INTERFACE */ \
+ bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, \
+ iInterface
+
+#define USB_IFACE_DESC_LEN 9
+
+/** Build bytes for USB endpoint descriptor. */
+#define USB_ENDP_DESC_BYTES(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
+ 7, /* bLength */ \
+ 0x05, /* bDescriptorType: ENDPOINT */ \
+ bEndpointAddress, bmAttributes, LE_BYTE0(wMaxPacketSize), LE_BYTE1(wMaxPacketSize), bInterval
+
+#define USB_ENDP_DESC_LEN 7
+
+/*@}*/
+
+/** \brief Get a word (calculate by little endian 16-bit data)
+ * \param[in] ptr Byte pointer to the address to get data
+ * \return a 16-bit word
+ */
+static inline uint16_t usb_get_u16(const uint8_t *ptr)
+{
+ return (ptr[0] + (ptr[1] << 8));
+}
+
+/** \brief Get a double word (calculate by little endian 32-bit data)
+ * \param[in] ptr Byte pointer to the address to get data
+ * \return a 32-bit word
+ */
+static inline uint32_t usb_get_u32(const uint8_t *ptr)
+{
+ return (ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24));
+}
+
+/** \brief Get descriptor length
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \return descriptor length
+ */
+static inline uint8_t usb_desc_len(const uint8_t *desc)
+{
+ return desc[0];
+}
+
+/** \brief Get descriptor type
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \return descriptor type
+ */
+static inline uint8_t usb_desc_type(const uint8_t *desc)
+{
+ return desc[1];
+}
+
+/** \brief Get next USB descriptor
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \return Byte pointer to the next descriptor
+ */
+static inline uint8_t *usb_desc_next(uint8_t *desc)
+{
+ return (desc + usb_desc_len(desc));
+}
+
+/** \brief Get idVendor of USB Device Descriptor
+ * \param[in] dev_desc Byte pointer to the descriptor start address
+ * \return 16-bit idVendor value
+ */
+static inline uint16_t usb_dev_desc_vid(const uint8_t *dev_desc)
+{
+ return usb_get_u16(dev_desc + 8);
+}
+
+/** \brief Get idProduct of USB Device Descriptor
+ * \param[in] dev_desc Byte pointer to the descriptor start address
+ * \return 16-bit idProduct value
+ */
+static inline uint16_t usb_dev_desc_pid(const uint8_t *dev_desc)
+{
+ return usb_get_u16(dev_desc + 10);
+}
+
+/** \brief Get wTotalLength of USB Configuration Descriptor
+ * \param[in] cfg_desc Byte pointer to the descriptor start address
+ * \return 16-bit total length of configuration list
+ */
+static inline uint16_t usb_cfg_desc_total_len(const uint8_t *cfg_desc)
+{
+ return usb_get_u16(cfg_desc + 2);
+}
+
+/** \brief Get Next USB Descriptor After the Configuration Descriptors list
+ * \param[in] cfg_desc Byte pointer to the descriptor start address
+ * \return Byte pointer to descriptor after configuration end
+ */
+static inline uint8_t *usb_cfg_desc_next(uint8_t *cfg_desc)
+{
+ return (cfg_desc + usb_cfg_desc_total_len(cfg_desc));
+}
+
+/** \brief Find specific USB Descriptor by its type
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \param[in] eof Byte pointer to the descriptor end address
+ * \param[in] type The descriptor type expected
+ * \return Pointer to the descriptor
+ * \retval NULL if not found
+ */
+uint8_t *usb_find_desc(uint8_t *desc, uint8_t *eof, uint8_t type);
+
+/** Get interface descriptor next to the specified one (by interface number)
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \param[in] eof Byte pointer to the descriptor end address
+ * \param[in] iface_n The interface number to check
+ * \return Pointer to the descriptor
+ * \retval >= eof if not found
+ */
+uint8_t *usb_find_iface_after(uint8_t *desc, uint8_t *eof, uint8_t iface_n);
+
+/** Find endpoint descriptor, breaks if interface descriptor detected
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \param[in] eof Byte pointer to the descriptor end address
+ * \return Pointer to the descriptor
+ * \retval NULL if not found
+ */
+uint8_t *usb_find_ep_desc(uint8_t *desc, uint8_t *eof);
+
+/** Find configuration descriptor by its configuration number
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \param[in] eof Byte pointer to the descriptor end address
+ * \param[in] cfg_value The configure value expected
+ * \return Pointer to the descriptor
+ * \retval NULL if not found
+ */
+uint8_t *usb_find_cfg_desc(uint8_t *desc, uint8_t *eof, uint8_t cfg_value);
+
+/** Find other speed configuration descriptor by its configuration number
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \param[in] eof Byte pointer to the descriptor end address
+ * \param[in] cfg_value The configure value expected
+ * \return Pointer to the descriptor
+ * \retval NULL if not found
+ */
+uint8_t *usb_find_othspdcfg_desc(uint8_t *desc, uint8_t *eof, uint8_t cfg_value);
+
+/** Find string descriptor by its index
+ * \param[in] desc Byte pointer to the descriptor start address
+ * \param[in] eof Byte pointer to the descriptor end address
+ * \param[in] str_index The string index expected
+ * \return Pointer to the descriptor
+ * \retval NULL if not found
+ */
+uint8_t *usb_find_str_desc(uint8_t *desc, uint8_t *eof, uint8_t str_index);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @} */
+
+#endif /* _USB_PROTOCOL_H_ */