aboutsummaryrefslogtreecommitdiff
path: root/atmel-samd/asf4/samd21/usb
diff options
context:
space:
mode:
authorScott Shawcroft <scott@tannewt.org>2017-09-22 18:05:51 -0700
committerDan Halbert <halbert@halwitz.org>2017-09-22 21:05:51 -0400
commit6839fff31303463d5c7942387fa498895edf1abf (patch)
treef4c5b94c6534c8d5c65ea6b7209cd2d681508f5f /atmel-samd/asf4/samd21/usb
parent3ad01ddb04b160b74b4baee9fce043da17dbcef5 (diff)
Move to ASF4 and introduce SAMD51 support. (#258)3.0.0-alpha.0
* atmel-samd: Remove ASF3. This will break builds. * atmel-samd: Add ASF4 for the SAMD21 and SAMD51. * Introduce the supervisor concept to facilitate porting. The supervisor is the code which runs individual MicroPython VMs. By splitting it out we make it more consistent and easier to find. This also adds very basic SAMD21 and SAMD51 support using the supervisor. Only the REPL currently works. This begins the work for #178.
Diffstat (limited to 'atmel-samd/asf4/samd21/usb')
-rw-r--r--atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.c389
-rw-r--r--atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.h114
-rw-r--r--atmel-samd/asf4/samd21/usb/class/cdc/usb_protocol_cdc.h407
-rw-r--r--atmel-samd/asf4/samd21/usb/class/composite/device/composite_desc.h170
-rw-r--r--atmel-samd/asf4/samd21/usb/class/composite/device/usbd_composite_config.h355
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.c358
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.h102
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.c365
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.h91
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.c363
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.h95
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hid/usb_protocol_hid.h597
-rw-r--r--atmel-samd/asf4/samd21/usb/class/hub/usb_protocol_hub.h364
-rw-r--r--atmel-samd/asf4/samd21/usb/class/msc/sbc_protocol.h163
-rw-r--r--atmel-samd/asf4/samd21/usb/class/msc/spc_protocol.h340
-rw-r--r--atmel-samd/asf4/samd21/usb/class/msc/usb_protocol_msc.h177
-rw-r--r--atmel-samd/asf4/samd21/usb/class/vendor/usb_protocol_vendor.h63
-rw-r--r--atmel-samd/asf4/samd21/usb/device/usbdc.c836
-rw-r--r--atmel-samd/asf4/samd21/usb/device/usbdc.h246
-rw-r--r--atmel-samd/asf4/samd21/usb/usb_atmel.h189
-rw-r--r--atmel-samd/asf4/samd21/usb/usb_debug.h47
-rw-r--r--atmel-samd/asf4/samd21/usb/usb_includes.h137
-rw-r--r--atmel-samd/asf4/samd21/usb/usb_protocol.c146
-rw-r--r--atmel-samd/asf4/samd21/usb/usb_protocol.h765
24 files changed, 6879 insertions, 0 deletions
diff --git a/atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.c b/atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.c
new file mode 100644
index 000000000..f0a8de446
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.c
@@ -0,0 +1,389 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack CDC ACM Function Implementation.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel micro controller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \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/atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.h b/atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.h
new file mode 100644
index 000000000..913e734be
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/cdc/device/cdcdf_acm.h
@@ -0,0 +1,114 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack CDC ACM Function Definition.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#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/atmel-samd/asf4/samd21/usb/class/cdc/usb_protocol_cdc.h b/atmel-samd/asf4/samd21/usb/class/cdc/usb_protocol_cdc.h
new file mode 100644
index 000000000..6017864cb
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/cdc/usb_protocol_cdc.h
@@ -0,0 +1,407 @@
+/**
+ * \file
+ *
+ * \brief USB Communication Device Class (CDC) protocol definitions
+ *
+ * Copyright (c) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel 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 0 (space)
+ CDC_PAR_SPACE = 4 //!< Parity forced to 1 (mark)
+};
+//@}
+
+//! \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()
+
+//! @}
+
+#endif // _USB_PROTOCOL_CDC_H_
diff --git a/atmel-samd/asf4/samd21/usb/class/composite/device/composite_desc.h b/atmel-samd/asf4/samd21/usb/class/composite/device/composite_desc.h
new file mode 100644
index 000000000..68db57af9
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/composite/device/composite_desc.h
@@ -0,0 +1,170 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack Composite Class Descriptor Setting.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef USBDF_COMPOSITE_DESC_H_
+#define USBDF_COMPOSITE_DESC_H_
+
+#include "usb_protocol.h"
+#include "usbd_composite_config.h"
+
+#if CONF_USB_COMPOSITE_CDC_ACM_EN == 1
+#define CONF_CDC_ACM_IFC_LEN 66
+#define CONF_CDC_ACM_IFC_NUM 2
+#define CONF_USB_COMPOSITE_CDC_ACM_COMM_BIFCNUM 0
+#define CONF_USB_COMPOSITE_CDC_ACM_DATA_BIFCNUM 1
+#define CONF_CDC_ACM_IFC_DESC \
+ USB_IAD_DESC_BYTES( \
+ CONF_USB_COMPOSITE_CDC_ACM_COMM_BIFCNUM, 0x02, CDC_CLASS_DEVICE, CDC_SUBCLASS_ACM, CDC_PROTOCOL_V25TER, 0x00) \
+ , \
+ USB_IFACE_DESC_BYTES(CONF_USB_COMPOSITE_CDC_ACM_COMM_BIFCNUM, \
+ 0x00, \
+ 0x01, \
+ CDC_CLASS_DEVICE, \
+ CDC_SUBCLASS_ACM, \
+ CDC_PROTOCOL_V25TER, \
+ 0x00), \
+ 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_COMPOSITE_CDC_ACM_COMM_BIFCNUM, 0x01), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_CDC_ACM_COMM_INT_EPADDR, 3, CONF_USB_COMPOSITE_CDC_ACM_COMM_INT_MAXPKSZ, 10), \
+ USB_IFACE_DESC_BYTES(CONF_USB_COMPOSITE_CDC_ACM_DATA_BIFCNUM, 0x00, 2, 0x0A, 0x00, 0x00, 0x00), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_EPADDR, 2, CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ, 0x00), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_EPADDR, 2, CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_MAXPKSZ, 0x00),
+#else
+#define CONF_CDC_ACM_IFC_LEN 0
+#define CONF_CDC_ACM_IFC_NUM 0
+#define CONF_USB_COMPOSITE_CDC_ACM_COMM_BIFCNUM -2
+#define CONF_USB_COMPOSITE_CDC_ACM_DATA_BIFCNUM -1
+#define CONF_CDC_ACM_IFC_DESC
+#endif
+
+#if CONF_USB_COMPOSITE_HID_MOUSE_EN == 1
+#define CONF_HID_MOUSE_IFC_LEN 25
+#define CONF_HID_MOUSE_IFC_NUM 1
+#define CONF_USB_COMPOSITE_HID_MOUSE_BIFCNUM (CONF_USB_COMPOSITE_CDC_ACM_DATA_BIFCNUM + 1)
+#define CONF_HID_MOUSE_IFC_DESC \
+ USB_IFACE_DESC_BYTES(CONF_USB_COMPOSITE_HID_MOUSE_BIFCNUM, 0x00, 0x01, 0x03, 0x01, 0x02, 0x00) \
+ , USB_HID_DESC_BYTES(0x09, 0x21, 0x01, 0x22, 0x34), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_HID_MOUSE_INTIN_EPADDR, 0x03, CONF_USB_COMPOSITE_HID_MOUSE_INTIN_MAXPKSZ, 10),
+#else
+#define CONF_HID_MOUSE_IFC_LEN 0
+#define CONF_HID_MOUSE_IFC_NUM 0
+#define CONF_USB_COMPOSITE_HID_MOUSE_BIFCNUM CONF_USB_COMPOSITE_CDC_ACM_DATA_BIFCNUM
+#define CONF_HID_MOUSE_IFC_DESC
+#endif
+
+#if CONF_USB_COMPOSITE_HID_KEYBOARD_EN == 1
+#define CONF_HID_KEYBOARD_IFC_LEN 32
+#define CONF_HID_KEYBOARD_IFC_NUM 1
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_BIFCNUM (CONF_USB_COMPOSITE_HID_MOUSE_BIFCNUM + 1)
+#define CONF_HID_KEYBOARD_IFC_DESC \
+ USB_IFACE_DESC_BYTES(CONF_USB_COMPOSITE_HID_KEYBOARD_BIFCNUM, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00) \
+ , USB_HID_DESC_BYTES(0x09, 0x21, 0x01, 0x22, 59), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_HID_KEYBOARD_INTIN_EPADDR, 0x03, CONF_USB_COMPOSITE_HID_KEYBOARD_INTIN_MAXPKSZ, 10), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_HID_KEYBOARD_INTOUT_EPADDR, 0x03, CONF_USB_COMPOSITE_HID_KEYBOARD_INTOUT_MAXPKSZ, 10),
+#else
+#define CONF_HID_KEYBOARD_IFC_LEN 0
+#define CONF_HID_KEYBOARD_IFC_NUM 0
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_BIFCNUM CONF_USB_COMPOSITE_HID_MOUSE_BIFCNUM
+#define CONF_HID_KEYBOARD_IFC_DESC
+#endif
+
+#if CONF_USB_COMPOSITE_HID_GENERIC_EN == 1
+#define CONF_HID_GENERIC_IFC_LEN 32
+#define CONF_HID_GENERIC_IFC_NUM 1
+#define CONF_USB_COMPOSITE_HID_GENERIC_BIFCNUM (CONF_USB_COMPOSITE_HID_KEYBOARD_BIFCNUM + 1)
+#define CONF_HID_GENERIC_IFC_DESC \
+ USB_IFACE_DESC_BYTES(CONF_USB_COMPOSITE_HID_GENERIC_BIFCNUM, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00) \
+ , USB_HID_DESC_BYTES(0x09, 0x21, 0x01, 0x22, CONF_USB_COMPOSITE_HID_GENERIC_REPORT_LEN), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_HID_GENERIC_INTIN_EPADDR, 0x03, CONF_USB_COMPOSITE_HID_GENERIC_INTIN_MAXPKSZ, 10), \
+ USB_ENDP_DESC_BYTES( \
+ CONF_USB_COMPOSITE_HID_GENERIC_INTOUT_EPADDR, 0x03, CONF_USB_COMPOSITE_HID_GENERIC_INTOUT_MAXPKSZ, 10),
+#else
+#define CONF_HID_GENERIC_IFC_LEN 0
+#define CONF_HID_GENERIC_IFC_NUM 0
+#define CONF_USB_COMPOSITE_HID_GENERIC_BIFCNUM CONF_USB_COMPOSITE_HID_KEYBOARD_BIFCNUM
+#define CONF_HID_GENERIC_IFC_DESC
+#endif
+
+#define CONF_USB_COMPOSITE_TOTAL_LEN \
+ (USB_CONFIG_DESC_LEN + CONF_CDC_ACM_IFC_LEN + CONF_HID_MOUSE_IFC_LEN + CONF_HID_KEYBOARD_IFC_LEN \
+ + CONF_HID_GENERIC_IFC_LEN)
+
+#define CONF_USB_COMPOSITE_IFC_NUM \
+ (CONF_CDC_ACM_IFC_NUM + CONF_HID_MOUSE_IFC_NUM + CONF_HID_KEYBOARD_IFC_NUM + CONF_HID_GENERIC_IFC_NUM)
+
+#define COMPOSITE_DEV_DESC \
+ USB_DEV_DESC_BYTES(CONF_USB_COMPOSITE_BCDUSB, \
+ 0xEF, \
+ 0x02, \
+ 0x01, \
+ CONF_USB_COMPOSITE_BMAXPKSZ0, \
+ CONF_USB_COMPOSITE_IDVENDER, \
+ CONF_USB_COMPOSITE_IDPRODUCT, \
+ CONF_USB_COMPOSITE_BCDDEVICE, \
+ CONF_USB_COMPOSITE_IMANUFACT, \
+ CONF_USB_COMPOSITE_IPRODUCT, \
+ CONF_USB_COMPOSITE_ISERIALNUM, \
+ CONF_USB_COMPOSITE_BNUMCONFIG)
+
+#define COMPOSITE_CFG_DESC \
+ USB_CONFIG_DESC_BYTES(CONF_USB_COMPOSITE_TOTAL_LEN, \
+ CONF_USB_COMPOSITE_IFC_NUM, \
+ CONF_USB_COMPOSITE_BCONFIGVAL, \
+ CONF_USB_COMPOSITE_ICONFIG, \
+ CONF_USB_COMPOSITE_BMATTRI, \
+ CONF_USB_COMPOSITE_BMAXPOWER)
+
+#define COMPOSITE_IFACE_DESCES \
+ CONF_CDC_ACM_IFC_DESC \
+ CONF_HID_MOUSE_IFC_DESC \
+ CONF_HID_KEYBOARD_IFC_DESC \
+ CONF_HID_GENERIC_IFC_DESC
+
+/** USB Device descriptors and configuration descriptors */
+#define COMPOSITE_DESCES_LS_FS \
+ COMPOSITE_DEV_DESC, COMPOSITE_CFG_DESC, COMPOSITE_IFACE_DESCES CONF_USB_COMPOSITE_LANGUAGE_ID_STR_DESC, \
+ CONF_USB_COMPOSITE_MANUFACTOR_STR_DESC, CONF_USB_COMPOSITE_PRODUCT_STR_DESC
+
+#endif /* USBDF_COMPOSITE_DESC_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/class/composite/device/usbd_composite_config.h b/atmel-samd/asf4/samd21/usb/class/composite/device/usbd_composite_config.h
new file mode 100644
index 000000000..1b29802b0
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/composite/device/usbd_composite_config.h
@@ -0,0 +1,355 @@
+/* Auto-generated config file usbd_composite_config.h */
+#ifndef USBD_COMPOSITE_CONFIG_H
+#define USBD_COMPOSITE_CONFIG_H
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+// <h> Composite Device Descriptor
+
+// <o> bcdUSB
+// <0x0200=> USB 2.0 version
+// <0x0210=> USB 2.1 version
+// <id> usb_composite_bcdusb
+#ifndef CONF_USB_COMPOSITE_BCDUSB
+#define CONF_USB_COMPOSITE_BCDUSB 0x200
+#endif
+
+// <o> bMaxPackeSize0
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_bmaxpksz0
+#ifndef CONF_USB_COMPOSITE_BMAXPKSZ0
+#define CONF_USB_COMPOSITE_BMAXPKSZ0 0x40
+#endif
+
+// <o> idVender <0x0000-0xFFFF>
+// <id> usb_composite_idvender
+#ifndef CONF_USB_COMPOSITE_IDVENDER
+#define CONF_USB_COMPOSITE_IDVENDER 0x3eb
+#endif
+
+// <o> idProduct <0x0000-0xFFFF>
+// <id> usb_composite_idproduct
+#ifndef CONF_USB_COMPOSITE_IDPRODUCT
+#define CONF_USB_COMPOSITE_IDPRODUCT 0x2421
+#endif
+
+// <o> bcdDevice <0x0000-0xFFFF>
+// <id> usb_composite_bcddevice
+#ifndef CONF_USB_COMPOSITE_BCDDEVICE
+#define CONF_USB_COMPOSITE_BCDDEVICE 0x100
+#endif
+
+// <o> iManufacturer <0x00-0xFF>
+// <id> usb_composite_imanufact
+#ifndef CONF_USB_COMPOSITE_IMANUFACT
+#define CONF_USB_COMPOSITE_IMANUFACT 0x0
+#endif
+
+#ifndef CONF_USB_COMPOSITE_LANGUAGE_ID_STR_DESC
+#define CONF_USB_COMPOSITE_LANGUAGE_ID_STR_DESC 0x04, 0x03, 0x09, 0x04
+#endif
+
+#ifndef CONF_USB_COMPOSITE_MANUFACTOR_STR_DESC
+#define CONF_USB_COMPOSITE_MANUFACTOR_STR_DESC \
+ 0x14, 0x03, 0x41, 0x00, 0x54, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x53, 0x00, 0x46, \
+ 0x00
+#endif
+
+// <o> iProduct <0x00-0xFF>
+// <id> usb_composite_iproduct
+#ifndef CONF_USB_COMPOSITE_IPRODUCT
+#define CONF_USB_COMPOSITE_IPRODUCT 0x0
+#endif
+
+#ifndef CONF_USB_COMPOSITE_PRODUCT_STR_DESC
+#define CONF_USB_COMPOSITE_PRODUCT_STR_DESC \
+ 0x22, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x65, \
+ 0x00, 0x20, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00
+#endif
+
+// <o> iSerialNumber <0x00-0xFF>
+// <id> usb_composite_iserialnum
+#ifndef CONF_USB_COMPOSITE_ISERIALNUM
+#define CONF_USB_COMPOSITE_ISERIALNUM 0x0
+#endif
+
+// <o> bNumConfigurations <0x01-0xFF>
+// <id> usb_composite_bnumconfig
+#ifndef CONF_USB_COMPOSITE_BNUMCONFIG
+#define CONF_USB_COMPOSITE_BNUMCONFIG 0x1
+#endif
+// </h>
+
+// <h> Composite Configuration Descriptor
+
+// <o> bConfigurationValue <0x01-0xFF>
+// <id> usb_composite_bconfigval
+#ifndef CONF_USB_COMPOSITE_BCONFIGVAL
+#define CONF_USB_COMPOSITE_BCONFIGVAL 0x1
+#endif
+
+// <o> iConfiguration <0x00-0xFF>
+// <id> usb_composite_iconfig
+#ifndef CONF_USB_COMPOSITE_ICONFIG
+#define CONF_USB_COMPOSITE_ICONFIG 0x0
+#endif
+
+// <o> bmAttributes
+// <0x80=> Bus power supply, not support for remote wakeup
+// <0xA0=> Bus power supply, support for remote wakeup
+// <0xC0=> Self powered, not support for remote wakeup
+// <0xE0=> Self powered, support for remote wakeup
+// <id> usb_composite_bmattri
+#ifndef CONF_USB_COMPOSITE_BMATTRI
+#define CONF_USB_COMPOSITE_BMATTRI 0x80
+#endif
+
+// <o> bMaxPower <0x00-0xFF>
+// <id> usb_composite_bmaxpower
+#ifndef CONF_USB_COMPOSITE_BMAXPOWER
+#define CONF_USB_COMPOSITE_BMAXPOWER 0x32
+#endif
+// </h>
+
+// <e> CDC ACM Support
+// <id> usb_composite_cdc_acm_support
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_EN
+#define CONF_USB_COMPOSITE_CDC_ACM_EN 1
+#endif
+
+// <o> CDC ACM Comm Interrupt IN Endpoint Address
+// <0x81=> EndpointAddress = 0x81
+// <0x82=> EndpointAddress = 0x82
+// <0x83=> EndpointAddress = 0x83
+// <0x84=> EndpointAddress = 0x84
+// <0x85=> EndpointAddress = 0x85
+// <0x86=> EndpointAddress = 0x86
+// <0x87=> EndpointAddress = 0x87
+// <id> usb_composite_cdc_acm_epaddr
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_COMM_INT_EPADDR
+#define CONF_USB_COMPOSITE_CDC_ACM_COMM_INT_EPADDR 0x82
+#endif
+
+// <o> CDC ACM Comm Interrupt IN Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_cdc_acm_comm_int_maxpksz
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_COMM_INT_MAXPKSZ
+#define CONF_USB_COMPOSITE_CDC_ACM_COMM_INT_MAXPKSZ 0x40
+#endif
+
+// <o> CDC ACM Data BULK IN Endpoint Address
+// <0x81=> EndpointAddress = 0x81
+// <0x82=> EndpointAddress = 0x82
+// <0x83=> EndpointAddress = 0x83
+// <0x84=> EndpointAddress = 0x84
+// <0x85=> EndpointAddress = 0x85
+// <0x86=> EndpointAddress = 0x86
+// <0x87=> EndpointAddress = 0x87
+// <id> usb_composite_cdc_acm_data_bulkin_epaddr
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_EPADDR
+#define CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_EPADDR 0x81
+#endif
+
+// <o> CDC ACM Data BULK IN Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_cdc_acm_data_builin_maxpksz
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_MAXPKSZ
+#define CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_MAXPKSZ 0x40
+#endif
+
+// <o> CDC ACM Data BULK OUT Endpoint Address
+// <0x01=> EndpointAddress = 0x01
+// <0x02=> EndpointAddress = 0x02
+// <0x03=> EndpointAddress = 0x03
+// <0x04=> EndpointAddress = 0x04
+// <0x05=> EndpointAddress = 0x05
+// <0x06=> EndpointAddress = 0x06
+// <0x07=> EndpointAddress = 0x07
+// <id> usb_composite_cdc_acm_data_bulkout_epaddr
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_EPADDR
+#define CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_EPADDR 0x1
+#endif
+
+// <o> CDC ACM Data BULK OUT Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_cdc_acm_data_buckout_maxpksz
+#ifndef CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ
+#define CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ 0x40
+#endif
+// </e>
+
+// <e> HID Mouse Support
+// <id> usb_composite_hid_mouse_support
+#ifndef CONF_USB_COMPOSITE_HID_MOUSE_EN
+#define CONF_USB_COMPOSITE_HID_MOUSE_EN 0
+#endif
+
+// <o> HID Mouse INTERRUPT IN Endpoint Address
+// <0x81=> EndpointAddress = 0x81
+// <0x82=> EndpointAddress = 0x82
+// <0x83=> EndpointAddress = 0x83
+// <0x84=> EndpointAddress = 0x84
+// <0x85=> EndpointAddress = 0x85
+// <0x86=> EndpointAddress = 0x86
+// <0x87=> EndpointAddress = 0x87
+// <id> usb_composite_hid_mouse_intin_epaddr
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_MOUSE_INTIN_EPADDR
+#define CONF_USB_COMPOSITE_HID_MOUSE_INTIN_EPADDR 0x83
+#endif
+
+// <o> HID Mouse INTERRUPT IN Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_hid_mouse_intin_maxpksz
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_MOUSE_INTIN_MAXPKSZ
+#define CONF_USB_COMPOSITE_HID_MOUSE_INTIN_MAXPKSZ 0x8
+#endif
+
+// </e>
+
+// <e> HID Keyboard Support
+// <id> usb_composite_hid_keyboard_support
+#ifndef CONF_USB_COMPOSITE_HID_KEYBOARD_EN
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_EN 0
+#endif
+
+// <o> HID Keyboard INTERRUPT IN Endpoint Address
+// <0x81=> EndpointAddress = 0x81
+// <0x82=> EndpointAddress = 0x82
+// <0x83=> EndpointAddress = 0x83
+// <0x84=> EndpointAddress = 0x84
+// <0x85=> EndpointAddress = 0x85
+// <0x86=> EndpointAddress = 0x86
+// <0x87=> EndpointAddress = 0x87
+// <id> usb_composite_hid_keyboard_intin_epaddr
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_KEYBOARD_INTIN_EPADDR
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_INTIN_EPADDR 0x84
+#endif
+
+// <o> HID Keyboard INTERRUPT IN Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_hid_keyboard_intin_maxpksz
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_KEYBOARD_INTIN_MAXPKSZ
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_INTIN_MAXPKSZ 0x8
+#endif
+
+// <o> HID Keyboard INTERRUPT OUT Endpoint Address
+// <0x01=> EndpointAddress = 0x01
+// <0x02=> EndpointAddress = 0x02
+// <0x03=> EndpointAddress = 0x03
+// <0x04=> EndpointAddress = 0x04
+// <0x05=> EndpointAddress = 0x05
+// <0x06=> EndpointAddress = 0x06
+// <0x07=> EndpointAddress = 0x07
+// <id> usb_composite_hid_keyboard_intout_epaddr
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_KEYBOARD_INTOUT_EPADDR
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_INTOUT_EPADDR 0x2
+#endif
+
+// <o> HID Keyboard INTERRUPT OUT Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_hid_keyboard_intout_maxpksz
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_KEYBOARD_INTOUT_MAXPKSZ
+#define CONF_USB_COMPOSITE_HID_KEYBOARD_INTOUT_MAXPKSZ 0x8
+#endif
+
+// </e>
+
+// <e> HID Generic Support
+// <id> usb_composite_hid_generic_support
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_EN
+#define CONF_USB_COMPOSITE_HID_GENERIC_EN 0
+#endif
+
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_REPORT_LEN
+#define CONF_USB_COMPOSITE_HID_GENERIC_REPORT_LEN 53
+#endif
+
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_REPORT
+#define CONF_USB_COMPOSITE_HID_GENERIC_REPORT \
+ 0x06, 0xFF, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x09, 0x02, 0x09, 0x03, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, \
+ 0x40, 0x81, 0x02, 0x09, 0x04, 0x09, 0x05, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x40, 0x91, 0x02, \
+ 0x09, 0x06, 0x09, 0x07, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x04, 0xB1, 0x02, 0xC0
+#endif
+
+// <o> HID Generic INTERRUPT IN Endpoint Address
+// <0x81=> EndpointAddress = 0x81
+// <0x82=> EndpointAddress = 0x82
+// <0x83=> EndpointAddress = 0x83
+// <0x84=> EndpointAddress = 0x84
+// <0x85=> EndpointAddress = 0x85
+// <0x86=> EndpointAddress = 0x86
+// <0x87=> EndpointAddress = 0x87
+// <id> usb_composite_hid_generic_intin_epaddr
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_INTIN_EPADDR
+#define CONF_USB_COMPOSITE_HID_GENERIC_INTIN_EPADDR 0x85
+#endif
+
+// <o> HID Generic INTERRUPT IN Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_hid_generic_intin_maxpksz
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_INTIN_MAXPKSZ
+#define CONF_USB_COMPOSITE_HID_GENERIC_INTIN_MAXPKSZ 0x40
+#endif
+
+// <o> HID Generic INTERRUPT OUT Endpoint Address
+// <0x01=> EndpointAddress = 0x01
+// <0x02=> EndpointAddress = 0x02
+// <0x03=> EndpointAddress = 0x03
+// <0x04=> EndpointAddress = 0x04
+// <0x05=> EndpointAddress = 0x05
+// <0x06=> EndpointAddress = 0x06
+// <0x07=> EndpointAddress = 0x07
+// <id> usb_composite_hid_generic_intout_epaddr
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_INTOUT_EPADDR
+#define CONF_USB_COMPOSITE_HID_GENERIC_INTOUT_EPADDR 0x3
+#endif
+
+// <o> HID Generic INTERRUPT OUT Endpoint wMaxPacketSize
+// <0x0008=> 8 bytes
+// <0x0010=> 16 bytes
+// <0x0020=> 32 bytes
+// <0x0040=> 64 bytes
+// <id> usb_composite_hid_generic_intout_maxpksz
+// <i> Please make sure that the setting here is coincide with the endpoint setting in USB device driver.
+#ifndef CONF_USB_COMPOSITE_HID_GENERIC_INTOUT_MAXPKSZ
+#define CONF_USB_COMPOSITE_HID_GENERIC_INTOUT_MAXPKSZ 0x40
+#endif
+
+// </e>
+
+// <<< end of configuration section >>>
+
+#endif // USBD_COMPOSITE_CONFIG_H
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.c b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.c
new file mode 100644
index 000000000..2c7cd3584
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.c
@@ -0,0 +1,358 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack HID Generic Function Implementation.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel micro controller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "hiddf_generic.h"
+#include <string.h>
+
+#define HIDDF_GENERIC_VERSION 0x00000001u
+
+/** USB Device HID Generic Function Specific Data */
+struct hiddf_generic_func_data {
+ /** HID Device Generic Interface information */
+ uint8_t func_iface;
+ /** HID Device Generic IN Endpoint */
+ uint8_t func_ep_in;
+ /** HID Device Generic OUT Endpoint */
+ uint8_t func_ep_out;
+ /** HID Device Generic Report Descriptor */
+ const uint8_t *report_desc;
+ /** HID Device Generic Report Descriptor Length */
+ uint32_t report_desc_len;
+ /** HID Device Generic Enable Flag */
+ bool enabled;
+};
+
+/* USB Device HID Generic Function Instance */
+static struct usbdf_driver _hiddf_generic;
+
+/* USB Device HID Generic Function Data Instance */
+static struct hiddf_generic_func_data _hiddf_generic_funcd;
+
+/* USB Device HID Generic Set Report Function Callback */
+static hiddf_generic_set_report_t hiddf_generic_set_report = NULL;
+
+/**
+ * \brief Enable HID Generic Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB interface descriptor
+ * \return Operation status.
+ */
+static int32_t hid_generic_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ uint8_t * ifc, *ep, i;
+ usb_iface_desc_t ifc_desc;
+ usb_ep_desc_t ep_desc;
+
+ struct hiddf_generic_func_data *func_data = (struct hiddf_generic_func_data *)(drv->func_data);
+
+ ifc = desc->sod;
+ if (NULL == ifc) {
+ return ERR_NOT_FOUND;
+ }
+
+ ifc_desc.bInterfaceNumber = ifc[2];
+ ifc_desc.bInterfaceClass = ifc[5];
+
+ if (HID_CLASS == ifc_desc.bInterfaceClass) {
+ if (func_data->func_iface == ifc_desc.bInterfaceNumber) { // Initialized
+ return ERR_ALREADY_INITIALIZED;
+ } else if (func_data->func_iface != 0xFF) { // Occupied
+ return ERR_NO_RESOURCE;
+ } else {
+ func_data->func_iface = ifc_desc.bInterfaceNumber;
+ }
+ } else { // Not supported by this function driver
+ return ERR_NOT_FOUND;
+ }
+
+ // Install endpoints
+ for (i = 0; i < 2; i++) {
+ ep = usb_find_ep_desc(usb_desc_next(desc->sod), desc->eod);
+ desc->sod = ep;
+ if (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 = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_in);
+ } else {
+ func_data->func_ep_out = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_out);
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+ }
+
+ // Installed
+ _hiddf_generic_funcd.enabled = true;
+ return ERR_NONE;
+}
+
+/**
+ * \brief Disable HID Generic Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB device descriptor
+ * \return Operation status.
+ */
+static int32_t hid_generic_disable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ struct hiddf_generic_func_data *func_data = (struct hiddf_generic_func_data *)(drv->func_data);
+
+ usb_iface_desc_t ifc_desc;
+
+ if (desc) {
+ ifc_desc.bInterfaceClass = desc->sod[5];
+ if (ifc_desc.bInterfaceClass != HID_CLASS) {
+ return ERR_NOT_FOUND;
+ }
+ }
+
+ if (func_data->func_iface != 0xFF) {
+ func_data->func_iface = 0xFF;
+ }
+
+ if (func_data->func_ep_in != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_in);
+ func_data->func_ep_in = 0xFF;
+ }
+
+ if (func_data->func_ep_out != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_out);
+ func_data->func_ep_out = 0xFF;
+ }
+
+ _hiddf_generic_funcd.enabled = false;
+ return ERR_NONE;
+}
+
+/**
+ * \brief HID Generic 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 hid_generic_ctrl(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param)
+{
+ switch (ctrl) {
+ case USBDF_ENABLE:
+ return hid_generic_enable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_DISABLE:
+ return hid_generic_disable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_GET_IFACE:
+ return ERR_UNSUPPORTED_OP;
+
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the HID class get descriptor
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t hid_generic_get_desc(uint8_t ep, struct usb_req *req)
+{
+ switch (req->wValue >> 8) {
+ case USB_DT_HID_REPORT:
+ return usbdc_xfer(ep, (uint8_t *)_hiddf_generic_funcd.report_desc, _hiddf_generic_funcd.report_desc_len, false);
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the HID class request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t hid_generic_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ uint8_t *ctrl_buf = usbdc_get_ctrl_buffer();
+ uint16_t len = req->wLength;
+
+ if ((0x81 == req->bmRequestType) && (0x06 == req->bRequest) && (req->wIndex == _hiddf_generic_funcd.func_iface)) {
+ return hid_generic_get_desc(ep, req);
+ } else {
+ if (0x01 != ((req->bmRequestType >> 5) & 0x03)) { // class request
+ return ERR_NOT_FOUND;
+ }
+ if (req->wIndex == _hiddf_generic_funcd.func_iface) {
+ if (req->bmRequestType & USB_EP_DIR_IN) {
+ return ERR_INVALID_ARG;
+ } else {
+ if (USB_REQ_HID_SET_REPORT == req->bRequest) {
+ if (USB_SETUP_STAGE == stage) {
+ return usbdc_xfer(ep, ctrl_buf, len, false);
+ } else {
+ if (NULL != hiddf_generic_set_report) {
+ hiddf_generic_set_report(ctrl_buf, len);
+ }
+ return ERR_NONE;
+ }
+ } else {
+ return usbdc_xfer(0, NULL, 0, 0);
+ }
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+ }
+}
+
+/** USB Device HID Generic Handler Struct */
+static struct usbdc_handler hid_generic_req_h = {NULL, (FUNC_PTR)hid_generic_req};
+
+/**
+ * \brief Initialize the USB HID Generic Function Driver
+ */
+int32_t hiddf_generic_init(const uint8_t *report_desc, uint32_t len)
+{
+ if (NULL == report_desc || 0 == len) {
+ return ERR_INVALID_ARG;
+ }
+
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _hiddf_generic_funcd.report_desc = report_desc;
+ _hiddf_generic_funcd.report_desc_len = len;
+ _hiddf_generic.ctrl = hid_generic_ctrl;
+ _hiddf_generic.func_data = &_hiddf_generic_funcd;
+
+ usbdc_register_function(&_hiddf_generic);
+ usbdc_register_handler(USBDC_HDL_REQ, &hid_generic_req_h);
+
+ return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize the USB HID Generic Function Driver
+ */
+int32_t hiddf_generic_deinit(void)
+{
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _hiddf_generic.ctrl = NULL;
+ _hiddf_generic.func_data = NULL;
+
+ usbdc_unregister_function(&_hiddf_generic);
+ usbdc_unregister_handler(USBDC_HDL_REQ, &hid_generic_req_h);
+ return ERR_NONE;
+}
+
+/**
+ * \brief Check whether HID Generic Function is enabled
+ */
+bool hiddf_generic_is_enabled(void)
+{
+ return _hiddf_generic_funcd.enabled;
+}
+
+/**
+ * \brief USB HID Generic Function Read Data
+ */
+int32_t hiddf_generic_read(uint8_t *buf, uint32_t size)
+{
+ if (!hiddf_generic_is_enabled()) {
+ return ERR_DENIED;
+ }
+ return usbdc_xfer(_hiddf_generic_funcd.func_ep_out, buf, size, false);
+}
+
+/**
+ * \brief USB HID Generic Function Write Data
+ */
+int32_t hiddf_generic_write(uint8_t *buf, uint32_t size)
+{
+ if (!hiddf_generic_is_enabled()) {
+ return ERR_DENIED;
+ }
+ return usbdc_xfer(_hiddf_generic_funcd.func_ep_in, buf, size, false);
+}
+
+/**
+ * \brief USB HID Generic Function Register Callback
+ */
+int32_t hiddf_generic_register_callback(enum hiddf_generic_cb_type cb_type, FUNC_PTR func)
+{
+ if (!hiddf_generic_is_enabled()) {
+ return ERR_DENIED;
+ }
+ switch (cb_type) {
+ case HIDDF_GENERIC_CB_READ:
+ usb_d_ep_register_callback(_hiddf_generic_funcd.func_ep_out, USB_D_EP_CB_XFER, func);
+ break;
+ case HIDDF_GENERIC_CB_WRITE:
+ usb_d_ep_register_callback(_hiddf_generic_funcd.func_ep_in, USB_D_EP_CB_XFER, func);
+ break;
+ case HIDDF_GENERIC_CB_SET_REPORT:
+ hiddf_generic_set_report = (hiddf_generic_set_report_t)func;
+ break;
+ default:
+ return ERR_INVALID_ARG;
+ }
+
+ return ERR_NONE;
+}
+
+/**
+ * \brief Return version
+ */
+uint32_t hiddf_generic_get_version(void)
+{
+ return HIDDF_GENERIC_VERSION;
+}
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.h b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.h
new file mode 100644
index 000000000..c12f1575a
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_generic.h
@@ -0,0 +1,102 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack HID Generic Function Definition.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef USBDF_HID_GENERIC_H_
+#define USBDF_HID_GENERIC_H_
+
+#include "usbdc.h"
+#include "usb_protocol_hid.h"
+
+/** HID Generic Callback Type */
+enum hiddf_generic_cb_type { HIDDF_GENERIC_CB_READ, HIDDF_GENERIC_CB_WRITE, HIDDF_GENERIC_CB_SET_REPORT };
+
+/** HID Generic Set Report Callback. */
+typedef bool (*hiddf_generic_set_report_t)(uint8_t *, uint16_t);
+
+/**
+ * \brief Initialize the USB HID Generic Function Driver
+ * \param[in] report_desc Point to usr HID Report Descriptor
+ * \param[in] len length of usr HID Report Descriptor
+ * \return Operation status.
+ */
+int32_t hiddf_generic_init(const uint8_t *report_desc, uint32_t len);
+
+/**
+ * \brief Deinitialize the USB HID Generic Function Driver
+ * \return Operation status.
+ */
+int32_t hiddf_generic_deinit(void);
+
+/**
+ * \brief Check whether HID Generic Function is enabled
+ * \return Operation status.
+ * \return true HID Generic Function is enabled
+ * \return false HID Generic Function is disabled
+ */
+bool hiddf_generic_is_enabled(void);
+
+/**
+ * \brief USB HID Generic 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 hiddf_generic_read(uint8_t *buf, uint32_t size);
+
+/**
+ * \brief USB HID Generic 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 hiddf_generic_write(uint8_t *buf, uint32_t size);
+
+/**
+ * \brief USB HID Generic Function Register Callback
+ * \param[in] cb_type Callback type of HID Generic Function
+ * \param[in] func Pointer to callback function
+ * \return Operation status.
+ */
+int32_t hiddf_generic_register_callback(enum hiddf_generic_cb_type cb_type, FUNC_PTR func);
+
+/**
+ * \brief Return version
+ */
+uint32_t hiddf_generic_get_version(void);
+
+#endif /* USBDF_HID_GENERIC_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.c b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.c
new file mode 100644
index 000000000..835481e41
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.c
@@ -0,0 +1,365 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack HID Keyboard Function Implementation.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel micro controller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "hiddf_keyboard.h"
+#include <string.h>
+
+#define HIDDF_KEYBOARD_VERSION 0x00000001u
+
+#define KEYBOARD_REPORT_DESC_LEN 59
+
+/** USB Device HID Keyboard Function Specific Data */
+struct hiddf_keyboard_func_data {
+ /* HID Device Keyboard Report */
+ uint8_t kb_report[8];
+ /** HID Device Keyboard Interface information */
+ uint8_t func_iface;
+ /** HID Device Keyboard IN Endpoint */
+ uint8_t func_ep_in;
+ /** HID Device Keyboard OUT Endpoint */
+ uint8_t func_ep_out;
+ /** HID Device Keyboard Enable Flag */
+ bool enabled;
+};
+
+/* HID report descriptor for standard HID keyboard */
+const uint8_t keyboard_report_desc[KEYBOARD_REPORT_DESC_LEN] = {
+ 0x05, 0x01, /* Usage Page (Generic Desktop) */
+ 0x09, 0x06, /* Usage (Keyboard) */
+ 0xA1, 0x01, /* Collection (Application) */
+ 0x05, 0x07, /* Usage Page (Keyboard) */
+ 0x19, 0xE0, /* Usage Minimum (224) */
+ 0x29, 0xE7, /* Usage Maximum (231) */
+ 0x15, 0x00, /* Logical Minimum (0) */
+ 0x25, 0x01, /* Logical Maximum (1) */
+ 0x75, 0x01, /* Report Size (1) */
+ 0x95, 0x08, /* Report Count (8) */
+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */
+ 0x81, 0x01, /* Input (Constant) */
+ 0x19, 0x00, /* Usage Minimum (0) */
+ 0x29, 0x65, /* Usage Maximum (101) */
+ 0x15, 0x00, /* Logical Minimum (0) */
+ 0x25, 0x65, /* Logical Maximum (101) */
+ 0x75, 0x08, /* Report Size (8) */
+ 0x95, 0x06, /* Report Count (6) */
+ 0x81, 0x00, /* Input (Data, Array) */
+ 0x05, 0x08, /* Usage Page (LED) */
+ 0x19, 0x01, /* Usage Minimum (1) */
+ 0x29, 0x05, /* Usage Maximum (5) */
+ 0x15, 0x00, /* Logical Minimum (0) */
+ 0x25, 0x01, /* Logical Maximum (1) */
+ 0x75, 0x01, /* Report Size (1) */
+ 0x95, 0x05, /* Report Count (5) */
+ 0x91, 0x02, /* Output (Data, Variable, Absolute) */
+ 0x95, 0x03, /* Report Count (3) */
+ 0x91, 0x01, /* Output (Constant) */
+ 0xC0 /* End Collection */
+};
+
+/* USB Device HID Keyboard Function Instance */
+static struct usbdf_driver _hiddf_keyboard;
+
+/* USB Device HID Keyboard Function Data Instance */
+static struct hiddf_keyboard_func_data _hiddf_keyboard_funcd;
+
+/**
+ * \brief Enable HID Keyboard Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB interface descriptor
+ * \return Operation status.
+ */
+static int32_t hid_keyboard_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ uint8_t * ifc, *ep, i;
+ usb_iface_desc_t ifc_desc;
+ usb_ep_desc_t ep_desc;
+
+ struct hiddf_keyboard_func_data *func_data = (struct hiddf_keyboard_func_data *)(drv->func_data);
+
+ ifc = desc->sod;
+ if (NULL == ifc) {
+ return ERR_NOT_FOUND;
+ }
+
+ ifc_desc.bInterfaceNumber = ifc[2];
+ ifc_desc.bInterfaceClass = ifc[5];
+
+ if (HID_CLASS == ifc_desc.bInterfaceClass) {
+ if (func_data->func_iface == ifc_desc.bInterfaceNumber) { // Initialized
+ return ERR_ALREADY_INITIALIZED;
+ } else if (func_data->func_iface != 0xFF) { // Occupied
+ return ERR_NO_RESOURCE;
+ } else {
+ func_data->func_iface = ifc_desc.bInterfaceNumber;
+ }
+ } else { // Not supported by this function driver
+ return ERR_NOT_FOUND;
+ }
+
+ // Install endpoints
+ for (i = 0; i < 2; i++) {
+ ep = usb_find_ep_desc(usb_desc_next(desc->sod), desc->eod);
+ desc->sod = ep;
+ if (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 = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_in);
+ } else {
+ func_data->func_ep_out = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_out);
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+ }
+
+ // Installed
+ _hiddf_keyboard_funcd.enabled = true;
+ return ERR_NONE;
+}
+
+/**
+ * \brief Disable HID Keyboard Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB device descriptor
+ * \return Operation status.
+ */
+static int32_t hid_keyboard_disable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ struct hiddf_keyboard_func_data *func_data = (struct hiddf_keyboard_func_data *)(drv->func_data);
+
+ usb_iface_desc_t ifc_desc;
+
+ if (desc) {
+ ifc_desc.bInterfaceClass = desc->sod[5];
+ if (ifc_desc.bInterfaceClass != HID_CLASS) {
+ return ERR_NOT_FOUND;
+ }
+ }
+
+ if (func_data->func_iface != 0xFF) {
+ func_data->func_iface = 0xFF;
+ }
+
+ if (func_data->func_ep_in != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_in);
+ func_data->func_ep_in = 0xFF;
+ }
+
+ if (func_data->func_ep_out != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_out);
+ func_data->func_ep_out = 0xFF;
+ }
+
+ _hiddf_keyboard_funcd.enabled = false;
+ return ERR_NONE;
+}
+
+/**
+ * \brief HID Keyboard 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 hid_keyboard_ctrl(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param)
+{
+ switch (ctrl) {
+ case USBDF_ENABLE:
+ return hid_keyboard_enable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_DISABLE:
+ return hid_keyboard_disable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_GET_IFACE:
+ return ERR_UNSUPPORTED_OP;
+
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the HID class get descriptor
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t hid_keyboard_get_desc(uint8_t ep, struct usb_req *req)
+{
+ switch (req->wValue >> 8) {
+ case USB_DT_HID_REPORT:
+ return usbdc_xfer(ep, (uint8_t *)keyboard_report_desc, KEYBOARD_REPORT_DESC_LEN, false);
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the HID class request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t hid_keyboard_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ if ((0x81 == req->bmRequestType) && (0x06 == req->bRequest) && (req->wIndex == _hiddf_keyboard_funcd.func_iface)) {
+ return hid_keyboard_get_desc(ep, req);
+ } else {
+ if (0x01 != ((req->bmRequestType >> 5) & 0x03)) { // class request
+ return ERR_NOT_FOUND;
+ }
+ if (req->wIndex == _hiddf_keyboard_funcd.func_iface) {
+ if (req->bmRequestType & USB_EP_DIR_IN) {
+ return ERR_INVALID_ARG;
+ } else {
+ return usbdc_xfer(0, NULL, 0, 0);
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+ }
+ (void)stage;
+}
+
+/** USB Device HID Keyboard Handler Struct */
+static struct usbdc_handler hid_keyboard_req_h = {NULL, (FUNC_PTR)hid_keyboard_req};
+
+/**
+ * \brief Initialize the USB HID Keyboard Function Driver
+ */
+int32_t hiddf_keyboard_init(void)
+{
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _hiddf_keyboard.ctrl = hid_keyboard_ctrl;
+ _hiddf_keyboard.func_data = &_hiddf_keyboard_funcd;
+
+ usbdc_register_function(&_hiddf_keyboard);
+ usbdc_register_handler(USBDC_HDL_REQ, &hid_keyboard_req_h);
+ return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize the USB HID Keyboard Function Driver
+ */
+int32_t hiddf_keyboard_deinit(void)
+{
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _hiddf_keyboard.ctrl = NULL;
+ _hiddf_keyboard.func_data = NULL;
+
+ usbdc_unregister_function(&_hiddf_keyboard);
+ usbdc_unregister_handler(USBDC_HDL_REQ, &hid_keyboard_req_h);
+ return ERR_NONE;
+}
+
+/**
+ * \brief Check whether HID Keyboard Function is enabled
+ */
+bool hiddf_keyboard_is_enabled(void)
+{
+ return _hiddf_keyboard_funcd.enabled;
+}
+
+/**
+ * \brief Process the HID Keyboard key state change request
+ * \param keys_desc[] keys_descriptor array for state changing
+ * \param keys_count total keys amount for state changing
+ * \return Operation status.
+ */
+int32_t hiddf_keyboard_keys_state_change(struct hiddf_kb_key_descriptors keys_desc[], uint8_t keys_count)
+{
+ uint8_t i, j;
+ uint8_t modifier_keys, regular_keys;
+
+ if (!hiddf_keyboard_is_enabled()) {
+ return ERR_DENIED;
+ }
+
+ memset(_hiddf_keyboard_funcd.kb_report, 0x00, 8);
+ modifier_keys = 0;
+
+ for (i = 0; i < keys_count; i++) {
+ if (true == keys_desc[i].b_modifier) {
+ modifier_keys++;
+ }
+ }
+
+ regular_keys = keys_count - modifier_keys;
+
+ if (regular_keys > 6) {
+ memset(&_hiddf_keyboard_funcd.kb_report[2], 0xFF, 6);
+ } else {
+ i = 2;
+ for (j = 0; j < keys_count; j++) {
+ if (HID_KB_KEY_DOWN == keys_desc[j].state) {
+ if (true == keys_desc[j].b_modifier) {
+ _hiddf_keyboard_funcd.kb_report[0] |= keys_desc[j].key_id;
+ } else {
+ _hiddf_keyboard_funcd.kb_report[i++] = keys_desc[j].key_id;
+ }
+ }
+ }
+ }
+ return usbdc_xfer(_hiddf_keyboard_funcd.func_ep_in, &_hiddf_keyboard_funcd.kb_report[0], 8, false);
+}
+
+/**
+ * \brief Return version
+ */
+uint32_t hiddf_keyboard_get_version(void)
+{
+ return HIDDF_KEYBOARD_VERSION;
+}
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.h b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.h
new file mode 100644
index 000000000..3295d1b78
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_keyboard.h
@@ -0,0 +1,91 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack HID Keyboard Function Definition.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef USBDF_HID_KEYBOARD_H_
+#define USBDF_HID_KEYBOARD_H_
+
+#include "usbdc.h"
+#include "usb_protocol_hid.h"
+
+/** HID Keyboard Class Key State Type */
+enum hiddf_kb_key_state { HID_KB_KEY_UP, HID_KB_KEY_DOWN };
+
+/** Describes the USB HID Keyboard Key descriptors. */
+struct hiddf_kb_key_descriptors {
+ /* HID Key Value, defined in usb_protocol_hid.h */
+ uint8_t key_id;
+ /* Flag whether it is a modifier key */
+ bool b_modifier;
+ /* Key State */
+ enum hiddf_kb_key_state state;
+};
+
+/**
+ * \brief Initialize the USB HID Keyboard Function Driver
+ * \return Operation status.
+ */
+int32_t hiddf_keyboard_init(void);
+
+/**
+ * \brief Deinitialize the USB HID Keyboard Function Driver
+ * \return Operation status.
+ */
+int32_t hiddf_keyboard_deinit(void);
+
+/**
+ * \brief Check whether HID Keyboard Function is enabled
+ * \return Operation status.
+ * \return true HID Keyboard Function is enabled
+ * \return false HID Keyboard Function is disabled
+ */
+bool hiddf_keyboard_is_enabled(void);
+
+/**
+ * \brief Process the HID Keyboard key state change request
+ * \param keys_desc[] keys_descriptor array for state changing
+ * \param keys_count total keys amount for state changing
+ * \return Operation status.
+ */
+int32_t hiddf_keyboard_keys_state_change(struct hiddf_kb_key_descriptors keys_desc[], uint8_t keys_count);
+
+/**
+ * \brief Return version
+ */
+uint32_t hiddf_keyboard_get_version(void);
+
+#endif /* USBDF_HID_KEYBOARD_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.c b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.c
new file mode 100644
index 000000000..7a58ce66e
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.c
@@ -0,0 +1,363 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack HID Mouse Function Implementation.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel micro controller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#include "hiddf_mouse.h"
+
+#define HIDDF_MOUSE_VERSION 0x00000001u
+
+#define MOUSE_REPORT_DESC_LEN 52
+
+/** USB Device HID Mouse Function Specific Data */
+struct hiddf_mouse_func_data {
+ /* HID Device Mouse Report */
+ union {
+ /** Interpreted by bytes. */
+ struct {
+ /** Button Status. */
+ uint8_t button_state;
+ /** X Axis Variant.*/
+ uint8_t x_axis_var;
+ /** Y Axis Variant.*/
+ uint8_t y_axis_var;
+ /** Scroll Variant.*/
+ uint8_t scroll_var;
+ } bytes;
+ uint32_t u32;
+ } mouse_report;
+ /** HID Device Mouse Interface information */
+ uint8_t func_iface;
+ /** HID Device Mouse IN Endpoint */
+ uint8_t func_ep_in;
+ /** HID Device Mouse Enable Flag */
+ bool enabled;
+};
+
+/* HID report descriptor for standard HID mouse */
+const uint8_t mouse_report_desc[MOUSE_REPORT_DESC_LEN] = {
+ 0x05, 0x01, /* Usage Page (Generic Desktop), */
+ 0x09, 0x02, /* Usage (Mouse), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x09, 0x01, /* Usage (Pointer), */
+ 0xA1, 0x00, /* Collection (Physical), */
+ 0x05, 0x09, /* Usage Page (Buttons), */
+ 0x19, 0x01, /* Usage Minimum (01), */
+ 0x29, 0x03, /* Usage Maximum (03), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */
+ 0x75, 0x05, /* Report Size (5), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0x05, 0x01, /* Usage Page (Generic Desktop), */
+ 0x09, 0x30, /* Usage (X), */
+ 0x09, 0x31, /* Usage (Y), */
+ 0x09, 0x38, /* Usage (Scroll), */
+ 0x15, 0x81, /* Logical Minimum (-127), */
+ 0x25, 0x7F, /* Logical Maximum (127), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x03, /* Report Count (3), */
+ 0x81, 0x06, /* Input (Data, Variable, Relative) */
+ 0xC0, /* End Collection, */
+ 0xC0, /* End Collection */
+};
+
+/* USB Device HID Mouse Function Instance */
+static struct usbdf_driver _hiddf_mouse;
+
+/* USB Device HID Mouse Function Data Instance */
+static struct hiddf_mouse_func_data _hiddf_mouse_funcd;
+
+/**
+ * \brief Enable HID Mouse Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB interface descriptor
+ * \return Operation status.
+ */
+static int32_t hid_mouse_enable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ uint8_t * ifc, *ep;
+ usb_iface_desc_t ifc_desc;
+ usb_ep_desc_t ep_desc;
+
+ struct hiddf_mouse_func_data *func_data = (struct hiddf_mouse_func_data *)(drv->func_data);
+
+ ifc = desc->sod;
+ if (NULL == ifc) {
+ return ERR_NOT_FOUND;
+ }
+
+ ifc_desc.bInterfaceNumber = ifc[2];
+ ifc_desc.bInterfaceClass = ifc[5];
+
+ if (HID_CLASS == ifc_desc.bInterfaceClass) {
+ if (func_data->func_iface == ifc_desc.bInterfaceNumber) { // Initialized
+ return ERR_ALREADY_INITIALIZED;
+ } else if (func_data->func_iface != 0xFF) { // Occupied
+ return ERR_NO_RESOURCE;
+ } else {
+ func_data->func_iface = ifc_desc.bInterfaceNumber;
+ }
+ } else { // Not supported by this function driver
+ return ERR_NOT_FOUND;
+ }
+
+ // Install endpoints
+ ep = usb_find_ep_desc(usb_desc_next(desc->sod), desc->eod);
+ desc->sod = ep;
+ if (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 = ep_desc.bEndpointAddress;
+ usb_d_ep_enable(func_data->func_ep_in);
+ } else {
+ return ERR_INVALID_DATA;
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+ // Installed
+ _hiddf_mouse_funcd.enabled = true;
+ return ERR_NONE;
+}
+
+/**
+ * \brief Disable HID Mouse Function
+ * \param[in] drv Pointer to USB device function driver
+ * \param[in] desc Pointer to USB device descriptor
+ * \return Operation status.
+ */
+static int32_t hid_mouse_disable(struct usbdf_driver *drv, struct usbd_descriptors *desc)
+{
+ struct hiddf_mouse_func_data *func_data = (struct hiddf_mouse_func_data *)(drv->func_data);
+
+ usb_iface_desc_t ifc_desc;
+
+ if (desc) {
+ ifc_desc.bInterfaceClass = desc->sod[5];
+ if (ifc_desc.bInterfaceClass != HID_CLASS) {
+ return ERR_NOT_FOUND;
+ }
+ }
+
+ if (func_data->func_iface != 0xFF) {
+ func_data->func_iface = 0xFF;
+ }
+
+ if (func_data->func_ep_in != 0xFF) {
+ usb_d_ep_deinit(func_data->func_ep_in);
+ func_data->func_ep_in = 0xFF;
+ }
+
+ _hiddf_mouse_funcd.enabled = false;
+ return ERR_NONE;
+}
+
+/**
+ * \brief HID Mouse 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 hid_mouse_ctrl(struct usbdf_driver *drv, enum usbdf_control ctrl, void *param)
+{
+ switch (ctrl) {
+ case USBDF_ENABLE:
+ return hid_mouse_enable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_DISABLE:
+ return hid_mouse_disable(drv, (struct usbd_descriptors *)param);
+
+ case USBDF_GET_IFACE:
+ return ERR_UNSUPPORTED_OP;
+
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the HID class get descriptor
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t hid_mouse_get_desc(uint8_t ep, struct usb_req *req)
+{
+ switch (req->wValue >> 8) {
+ case USB_DT_HID_REPORT:
+ return usbdc_xfer(ep, (uint8_t *)mouse_report_desc, MOUSE_REPORT_DESC_LEN, false);
+ default:
+ return ERR_INVALID_ARG;
+ }
+}
+
+/**
+ * \brief Process the HID class request
+ * \param[in] ep Endpoint address.
+ * \param[in] req Pointer to the request.
+ * \return Operation status.
+ */
+static int32_t hid_mouse_req(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
+{
+ if ((0x81 == req->bmRequestType) && (0x06 == req->bRequest) && (req->wIndex == _hiddf_mouse_funcd.func_iface)) {
+ return hid_mouse_get_desc(ep, req);
+ } else {
+ if (0x01 != ((req->bmRequestType >> 5) & 0x03)) { // class request
+ return ERR_NOT_FOUND;
+ }
+ if (req->wIndex == _hiddf_mouse_funcd.func_iface) {
+ if (req->bmRequestType & USB_EP_DIR_IN) {
+ return ERR_INVALID_ARG;
+ } else {
+ return usbdc_xfer(0, NULL, 0, 0);
+ }
+ } else {
+ return ERR_NOT_FOUND;
+ }
+ }
+ (void)stage;
+}
+
+/** USB Device HID Mouse Handler Struct */
+static struct usbdc_handler hid_mouse_req_h = {NULL, (FUNC_PTR)hid_mouse_req};
+
+/**
+ * \brief Initialize the USB HID Mouse Function Driver
+ */
+int32_t hiddf_mouse_init(void)
+{
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _hiddf_mouse.ctrl = hid_mouse_ctrl;
+ _hiddf_mouse.func_data = &_hiddf_mouse_funcd;
+
+ usbdc_register_function(&_hiddf_mouse);
+ usbdc_register_handler(USBDC_HDL_REQ, &hid_mouse_req_h);
+ return ERR_NONE;
+}
+
+/**
+ * \brief Deinitialize the USB HID Mouse Function Driver
+ */
+int32_t hiddf_mouse_deinit(void)
+{
+ if (usbdc_get_state() > USBD_S_POWER) {
+ return ERR_DENIED;
+ }
+
+ _hiddf_mouse.ctrl = NULL;
+ _hiddf_mouse.func_data = NULL;
+
+ usbdc_unregister_function(&_hiddf_mouse);
+ usbdc_unregister_handler(USBDC_HDL_REQ, &hid_mouse_req_h);
+ return ERR_NONE;
+}
+
+/**
+ * \brief Check whether HID Mouse Function is enabled
+ */
+bool hiddf_mouse_is_enabled(void)
+{
+ return _hiddf_mouse_funcd.enabled;
+}
+
+/**
+ * \brief Move the mouse pointer
+ * \param pos Signed value to move
+ * \param type HID mouse class pointer move type
+ * \return Operation status.
+ */
+int32_t hiddf_mouse_move(int8_t pos, enum hiddf_mouse_move_type type)
+{
+
+ _hiddf_mouse_funcd.mouse_report.u32 = 0;
+
+ if (type == HID_MOUSE_X_AXIS_MV) {
+ _hiddf_mouse_funcd.mouse_report.bytes.x_axis_var = pos;
+ } else if (type == HID_MOUSE_Y_AXIS_MV) {
+ _hiddf_mouse_funcd.mouse_report.bytes.y_axis_var = pos;
+ } else if (type == HID_MOUSE_SCROLL_MV) {
+ _hiddf_mouse_funcd.mouse_report.bytes.scroll_var = pos;
+ } else {
+ return ERR_INVALID_ARG;
+ }
+
+ return usbdc_xfer(_hiddf_mouse_funcd.func_ep_in, &_hiddf_mouse_funcd.mouse_report.bytes.button_state, 4, false);
+}
+
+/**
+ * \brief Changes button state
+ * \param b_state New button state
+ * \param type Button type
+ * \return Operation status.
+ */
+int32_t hiddf_mouse_button_change(enum hiddf_mouse_button_state b_state, enum hiddf_mouse_button_type type)
+{
+ _hiddf_mouse_funcd.mouse_report.u32 = 0;
+
+ if (b_state == HID_MOUSE_BTN_DOWN) {
+ _hiddf_mouse_funcd.mouse_report.bytes.button_state = type;
+ } else {
+ _hiddf_mouse_funcd.mouse_report.bytes.button_state = 0x00;
+ }
+
+ return usbdc_xfer(_hiddf_mouse_funcd.func_ep_in, &_hiddf_mouse_funcd.mouse_report.bytes.button_state, 4, false);
+}
+
+/**
+ * \brief Return version
+ */
+uint32_t hiddf_mouse_get_version(void)
+{
+ return HIDDF_MOUSE_VERSION;
+}
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.h b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.h
new file mode 100644
index 000000000..464b1e92d
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/device/hiddf_mouse.h
@@ -0,0 +1,95 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack HID Mouse Function Definition.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef USBDF_HID_MOUSE_H_
+#define USBDF_HID_MOUSE_H_
+
+#include "usbdc.h"
+#include "usb_protocol_hid.h"
+
+/** HID Mouse Class Button State Type */
+enum hiddf_mouse_button_state { HID_MOUSE_BTN_UP, HID_MOUSE_BTN_DOWN };
+
+/* HID Mosue Class Button Type */
+enum hiddf_mouse_button_type { HID_MOUSE_LEFT_BTN = 0x01, HID_MOUSE_RIGHT_BTN = 0x02, HID_MOUSE_MIDDLE_BTN = 0x04 };
+
+/* HID Mouse Class Pointer Move Type */
+enum hiddf_mouse_move_type { HID_MOUSE_X_AXIS_MV = 0x01, HID_MOUSE_Y_AXIS_MV = 0x02, HID_MOUSE_SCROLL_MV = 0x03 };
+
+/**
+ * \brief Initialize the USB HID Mouse Function Driver
+ * \return Operation status.
+ */
+int32_t hiddf_mouse_init(void);
+
+/**
+ * \brief Deinitialize the USB HID Mouse Function Driver
+ * \return Operation status.
+ */
+int32_t hiddf_mouse_deinit(void);
+
+/**
+ * \brief Check whether HID Mouse Function is enabled
+ * \return Operation status.
+ * \return true HID Mouse Function is enabled
+ * \return false HID Mouse Function is disabled
+ */
+bool hiddf_mouse_is_enabled(void);
+
+/**
+ * \brief Move the mouse pointer
+ * \param pos Signed value to move
+ * \param type HID mouse class pointer move type
+ * \return Operation status.
+ */
+int32_t hiddf_mouse_move(int8_t pos, enum hiddf_mouse_move_type type);
+
+/**
+ * \brief Changes button state
+ * \param b_state New button state
+ * \param type Button type
+ * \return Operation status.
+ */
+int32_t hiddf_mouse_button_change(enum hiddf_mouse_button_state b_state, enum hiddf_mouse_button_type type);
+
+/**
+ * \brief Return version
+ */
+uint32_t hiddf_mouse_get_version(void);
+
+#endif /* USBDF_CDC_ACM_SER_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/class/hid/usb_protocol_hid.h b/atmel-samd/asf4/samd21/usb/class/hid/usb_protocol_hid.h
new file mode 100644
index 000000000..71d74e632
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hid/usb_protocol_hid.h
@@ -0,0 +1,597 @@
+/**
+ * \file
+ *
+ * \brief USB Human Interface Device (HID) protocol definitions.
+ *
+ * Copyright (c) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef _USB_PROTOCOL_HID_H_
+#define _USB_PROTOCOL_HID_H_
+
+#include "usb_includes.h"
+
+/**
+ * \ingroup usb_protocol_group
+ * \defgroup usb_hid_protocol USB Human Interface Device (HID)
+ * protocol definitions
+ * \brief USB Human Interface Device (HID) protocol definitions
+ *
+ * @{
+ */
+
+//! \name Possible Class value
+//@{
+#define HID_CLASS 0x03
+//@}
+
+//! \name Possible SubClass value
+//@{
+//! Interface subclass NO support BOOT protocol
+#define HID_SUB_CLASS_NOBOOT 0x00
+//! Interface subclass support BOOT protocol
+#define HID_SUB_CLASS_BOOT 0x01
+//@}
+
+//! \name Possible protocol value
+//@{
+//! Protocol generic standard
+#define HID_PROTOCOL_GENERIC 0x00
+//! Protocol keyboard standard
+#define HID_PROTOCOL_KEYBOARD 0x01
+//! Protocol mouse standard
+#define HID_PROTOCOL_MOUSE 0x02
+//@}
+
+//! \brief Hid USB requests (bRequest)
+
+#define USB_REQ_HID_GET_REPORT 0x01
+#define USB_REQ_HID_GET_IDLE 0x02
+#define USB_REQ_HID_GET_PROTOCOL 0x03
+#define USB_REQ_HID_SET_REPORT 0x09
+#define USB_REQ_HID_SET_IDLE 0x0A
+#define USB_REQ_HID_SET_PROTOCOL 0x0B
+
+//! \brief HID USB descriptor types
+#define USB_DT_HID 0x21
+#define USB_DT_HID_REPORT 0x22
+#define USB_DT_HID_PHYSICAL 0x23
+
+//! \brief HID Type for report descriptor
+#define USB_HID_ITEM_REPORT_TYPE_MAIN 0
+#define USB_HID_ITEM_REPORT_TYPE_GLOBAL 1
+#define USB_HID_ITEM_REPORT_TYPE_LOCAL 2
+#define USB_HID_ITEM_REPORT_TYPE_LONG 3
+
+//! \brief HID report type
+#define USB_HID_REPORT_TYPE_INPUT 1
+#define USB_HID_REPORT_TYPE_OUTPUT 2
+#define USB_HID_REPORT_TYPE_FEATURE 3
+
+//! \brief HID protocol
+#define USB_HID_PROCOTOL_BOOT 0
+#define USB_HID_PROCOTOL_REPORT 1
+
+#define USB_HID_DESC_BYTES(bLength, bCountryCode, bNumDescriptors, bDescriptorType, bDescriptorLength) \
+ bLength, 0x21, 0x10, 0x01, bCountryCode, bNumDescriptors, bDescriptorType, LE_BYTE0(bDescriptorLength), \
+ LE_BYTE1(bDescriptorLength)
+
+COMPILER_PACK_SET(1)
+
+//! \brief HID Descriptor
+typedef struct usb_hid_descriptor {
+ uint8_t bLength; //!< Size of this descriptor in bytes
+ uint8_t bDescriptorType; //!< HID descriptor type
+ le16_t bcdHID; //!< Binary Coded Decimal Spec. release
+ uint8_t bCountryCode; //!< Hardware target country
+ uint8_t bNumDescriptors; //!< Number of HID class descriptors to follow
+ uint8_t bRDescriptorType; //!< Report descriptor type
+ le16_t wDescriptorLength; //!< Total length of Report descriptor
+} usb_hid_descriptor_t;
+
+COMPILER_PACK_RESET()
+
+//! \name HID Report type
+//! Used by SETUP_HID_GET_REPORT & SETUP_HID_SET_REPORT
+//! @{
+#define REPORT_TYPE_INPUT 0x01
+#define REPORT_TYPE_OUTPUT 0x02
+#define REPORT_TYPE_FEATURE 0x03
+//! @}
+
+//! \name Constants of field DESCRIPTOR_HID
+//! @{
+//! Numeric expression identifying the HID Class
+//! Specification release (here V1.11)
+#define USB_HID_BDC_V1_11 0x0111
+//! Numeric expression specifying the number of class descriptors
+//! Note: Always at least one i.e. Report descriptor.
+#define USB_HID_NUM_DESC 0x01
+
+//! \name Country code
+//! @{
+#define USB_HID_NO_COUNTRY_CODE 0 // Not Supported
+#define USB_HID_COUNTRY_ARABIC 1 // Arabic
+#define USB_HID_COUNTRY_BELGIAN 2 // Belgian
+#define USB_HID_COUNTRY_CANADIAN_BILINGUAL 3 // Canadian-Bilingual
+#define USB_HID_COUNTRY_CANADIAN_FRENCH 4 // Canadian-French
+#define USB_HID_COUNTRY_CZECH_REPUBLIC 5 // Czech Republic
+#define USB_HID_COUNTRY_DANISH 6 // Danish
+#define USB_HID_COUNTRY_FINNISH 7 // Finnish
+#define USB_HID_COUNTRY_FRENCH 8 // French
+#define USB_HID_COUNTRY_GERMAN 9 // German
+#define USB_HID_COUNTRY_GREEK 10 // Greek
+#define USB_HID_COUNTRY_HEBREW 11 // Hebrew
+#define USB_HID_COUNTRY_HUNGARY 12 // Hungary
+#define USB_HID_COUNTRY_INTERNATIONAL_ISO 13 // International (ISO)
+#define USB_HID_COUNTRY_ITALIAN 14 // Italian
+#define USB_HID_COUNTRY_JAPAN_KATAKANA 15 // Japan (Katakana)
+#define USB_HID_COUNTRY_KOREAN 16 // Korean
+#define USB_HID_COUNTRY_LATIN_AMERICAN 17 // Latin American
+#define USB_HID_COUNTRY_NETHERLANDS_DUTCH 18 // Netherlands/Dutch
+#define USB_HID_COUNTRY_NORWEGIAN 19 // Norwegian
+#define USB_HID_COUNTRY_PERSIAN_FARSI 20 // Persian (Farsi)
+#define USB_HID_COUNTRY_POLAND 21 // Poland
+#define USB_HID_COUNTRY_PORTUGUESE 22 // Portuguese
+#define USB_HID_COUNTRY_RUSSIA 23 // Russia
+#define USB_HID_COUNTRY_SLOVAKIA 24 // Slovakia
+#define USB_HID_COUNTRY_SPANISH 25 // Spanish
+#define USB_HID_COUNTRY_SWEDISH 26 // Swedish
+#define USB_HID_COUNTRY_SWISS_FRENCH 27 // Swiss/French
+#define USB_HID_COUNTRY_SWISS_GERMAN 28 // Swiss/German
+#define USB_HID_COUNTRY_SWITZERLAND 29 // Switzerland
+#define USB_HID_COUNTRY_TAIWAN 30 // Taiwan
+#define USB_HID_COUNTRY_TURKISH_Q 31 // Turkish-Q
+#define USB_HID_COUNTRY_UK 32 // UK
+#define USB_HID_COUNTRY_US 33 // US
+#define USB_HID_COUNTRY_YUGOSLAVIA 34 // Yugoslavia
+#define USB_HID_COUNTRY_TURKISH_F 35 // Turkish-F
+ //! @}
+ //! @}
+//! @}
+
+//! \name HID KEYS values
+//! @{
+#define HID_A 0x04
+#define HID_B 0x05
+#define HID_C 0x06
+#define HID_D 0x07
+#define HID_E 0x08
+#define HID_F 0x09
+#define HID_G 0x0A
+#define HID_H 0x0B
+#define HID_I 0x0C
+#define HID_J 0x0D
+#define HID_K 0x0E
+#define HID_L 0x0F
+#define HID_M 0x10
+#define HID_N 0x11
+#define HID_O 0x12
+#define HID_P 0x13
+#define HID_Q 0x14
+#define HID_R 0x15
+#define HID_S 0x16
+#define HID_T 0x17
+#define HID_U 0x18
+#define HID_V 0x19
+#define HID_W 0x1A
+#define HID_X 0x1B
+#define HID_Y 0x1C
+#define HID_Z 0x1D
+#define HID_1 30
+#define HID_2 31
+#define HID_3 32
+#define HID_4 33
+#define HID_5 34
+#define HID_6 35
+#define HID_7 36
+#define HID_8 37
+#define HID_9 38
+#define HID_0 39
+#define HID_ENTER 40
+#define HID_ESCAPE 41
+#define HID_BACKSPACE 42
+#define HID_TAB 43
+#define HID_SPACEBAR 44
+#define HID_UNDERSCORE 45
+#define HID_PLUS 46
+#define HID_OPEN_BRACKET 47 // {
+#define HID_CLOSE_BRACKET 48 // }
+#define HID_BACKSLASH 49
+#define HID_ASH 50 // # ~
+#define HID_COLON 51 // ; :
+#define HID_QUOTE 52 // ' "
+#define HID_TILDE 53
+#define HID_COMMA 54
+#define HID_DOT 55
+#define HID_SLASH 56
+#define HID_CAPS_LOCK 57
+#define HID_F1 58
+#define HID_F2 59
+#define HID_F3 60
+#define HID_F4 61
+#define HID_F5 62
+#define HID_F6 63
+#define HID_F7 64
+#define HID_F8 65
+#define HID_F9 66
+#define HID_F10 67
+#define HID_F11 68
+#define HID_F12 69
+#define HID_PRINTSCREEN 70
+#define HID_SCROLL_LOCK 71
+#define HID_PAUSE 72
+#define HID_INSERT 73
+#define HID_HOME 74
+#define HID_PAGEUP 75
+#define HID_DELETE 76
+#define HID_END 77
+#define HID_PAGEDOWN 78
+#define HID_RIGHT 79
+#define HID_LEFT 80
+#define HID_DOWN 81
+#define HID_UP 82
+#define HID_KEYPAD_NUM_LOCK 83
+#define HID_KEYPAD_DIVIDE 84
+#define HID_KEYPAD_AT 85
+#define HID_KEYPAD_MULTIPLY 85
+#define HID_KEYPAD_MINUS 86
+#define HID_KEYPAD_PLUS 87
+#define HID_KEYPAD_ENTER 88
+#define HID_KEYPAD_1 89
+#define HID_KEYPAD_2 90
+#define HID_KEYPAD_3 91
+#define HID_KEYPAD_4 92
+#define HID_KEYPAD_5 93
+#define HID_KEYPAD_6 94
+#define HID_KEYPAD_7 95
+#define HID_KEYPAD_8 96
+#define HID_KEYPAD_9 97
+#define HID_KEYPAD_0 98
+
+//! \name HID modifier values
+//! @{
+#define HID_MODIFIER_NONE 0x00
+#define HID_MODIFIER_LEFT_CTRL 0x01
+#define HID_MODIFIER_LEFT_SHIFT 0x02
+#define HID_MODIFIER_LEFT_ALT 0x04
+#define HID_MODIFIER_LEFT_UI 0x08
+#define HID_MODIFIER_RIGHT_CTRL 0x10
+#define HID_MODIFIER_RIGHT_SHIFT 0x20
+#define HID_MODIFIER_RIGHT_ALT 0x40
+#define HID_MODIFIER_RIGHT_UI 0x80
+//! @}
+//! @}
+
+//! \name HID KEYS LED values
+//! @{
+#define HID_LED_NUM_LOCK (1 << 0)
+#define HID_LED_CAPS_LOCK (1 << 1)
+#define HID_LED_SCROLL_LOCK (1 << 2)
+#define HID_LED_COMPOSE (1 << 3)
+#define HID_LED_KANA (1 << 4)
+//! @}
+
+/** \name Standard HID mouse definitions from HID spec. example */
+/*@{*/
+
+/** \brief Structure for standard HID keyboard modified keys */
+typedef union hid_kbd_modifier {
+ uint8_t byte;
+ struct {
+ uint8_t lctrl : 1; /**< Left Ctrl */
+ uint8_t lshift : 1; /**< Left Shift */
+ uint8_t lalt : 1; /**< Left Alt */
+ uint8_t lgui : 1; /**< Left Gui */
+ uint8_t rctrl : 1; /**< Right Ctrl */
+ uint8_t rshift : 1; /**< Right Shift */
+ uint8_t ralt : 1; /**< Right Alt */
+ uint8_t rgui : 1; /**< Right Gui */
+ } bm;
+} hid_kbd_modifier_t;
+#define HID_KBD_L_CTRL (1 << 0) /**< Left Ctrl */
+#define HID_KBD_L_SHIFT (1 << 1) /**< Left Shift */
+#define HID_KBD_L_ALT (1 << 2) /**< Left Alt */
+#define HID_KBD_L_GUI (1 << 3) /**< Left Gui */
+#define HID_KBD_R_CTRL (1 << 4) /**< Right Ctrl */
+#define HID_KBD_R_SHIFT (1 << 5) /**< Right Shift */
+#define HID_KBD_R_ALT (1 << 6) /**< Right Alt */
+#define HID_KBD_R_GUI (1 << 7) /**< Right Gui */
+
+/** \brief Structure for standard HID keyboard input report */
+typedef union hid_kbd_input_report {
+ uint8_t byte[8];
+ struct {
+ union hid_kbd_modifier modifier;
+ uint8_t reserved_oem;
+ uint8_t key[6]; /** < Key array */
+ } field;
+} hid_kbd_input_report_t;
+/** Access to the modifier keys in HID keyboard report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_kbd_modifier_keys(rpt) (rpt[0])
+/** Access to the OEM reserved in HID keyboard report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_kbd_oem(rpt) (rpt[1])
+/** Access to the Key code in HID keyboard report
+ * \param rpt Pointer to report data of bytes
+ * \param i Index in the report key array (0~n)
+ */
+#define hid_kbd_keycode(rpt, i) (rpt[2 + i])
+
+/** \brief Structure for standard HID keyboard output report */
+typedef union hid_kbd_output_report {
+ uint8_t byte;
+ struct {
+ uint8_t num_lock : 1; /**< LED of Num Lock */
+ uint8_t caps_lock : 1; /**< LED of Caps Lock */
+ uint8_t scroll_lock : 1; /**< LED of Scroll Lock */
+ uint8_t compose : 1; /**< LED of COMPOSE LOCK */
+ uint8_t kana : 1; /**< LED of KANA */
+ uint8_t constant : 3;
+ } field;
+} hid_kbd_output_report_t;
+#define HID_KBD_NUM_LOCK (1 << 0) /**< LED of Num Lock */
+#define HID_KBD_CAPS_LOCK (1 << 1) /**< LED of Caps Lock */
+#define HID_KBD_SCROLL_LOCK (1 << 2) /**< LED of Scroll Lock */
+#define HID_KBD_COMPOSE (1 << 3) /**< LED of COMPOSE LOCK */
+#define HID_KBD_KANA (1 << 4) /**< LED of KANA */
+
+/*@}*/
+
+/** \name Standard HID mouse definitions from HID spec. example */
+/*@{*/
+/** \brief Structure for standard HID mouse report */
+typedef union hid_mouse_report {
+ uint8_t byte[3];
+ struct {
+ uint8_t btn1 : 1; /**< Button 1 */
+ uint8_t btn2 : 2; /**< Button 2 */
+ uint8_t btn3 : 3; /**< Button 3 */
+ uint8_t device_spec : 5;
+ int8_t x; /**< X displacement */
+ int8_t y; /**< Y displacement */
+ } field;
+ /* More bytes are optional */
+} hid_mouse_report_t;
+#define HID_MOUSE_BTN1 (1 << 0) /**< Button 1 */
+#define HID_MOUSE_BTN2 (1 << 1) /**< Button 2 */
+#define HID_MOUSE_BTN3 (1 << 2) /**< Button 3 */
+
+/** Access to the button state in HID mouse report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_mouse_btn_state(rpt) (rpt[0])
+/** Check if the button is done in HID mouse report
+ * \param rpt Pointer to report data of bytes
+ * \param btn Button bitmap to check
+ */
+#define hid_mouse_is_btn_down(rpt, btn) (rpt[0] & (btn))
+/** Access to the relative X displacement in HID mouse report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_mouse_x(rpt) ((int8_t)rpt[1])
+/** Access to the relative Y displacement in HID mouse report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_mouse_y(rpt) ((int8_t)rpt[2])
+
+/*@}*/
+
+/** \name Standard HID joystick definitions from HID spec. example */
+/*@{*/
+
+/** \brief Structure for standard HID joystick report */
+typedef union hid_joystick_report {
+ uint8_t byte[4];
+ struct {
+ int8_t x;
+ int8_t y;
+ uint8_t hat_sw : 4; /**< Hat switch */
+ uint8_t btn1 : 1; /**< Button 1 */
+ uint8_t btn2 : 1; /**< Button 2 */
+ uint8_t btn3 : 1; /**< Button 3 */
+ uint8_t btn4 : 1; /**< Button 4 */
+ uint8_t throttle;
+ } field;
+} hid_joystick_report_t;
+#define HID_JOYSTICK_BTN1 (1 << 4) /**< Button 1 */
+#define HID_JOYSTICK_BTN2 (1 << 5) /**< Button 2 */
+#define HID_JOYSTICK_BTN3 (1 << 6) /**< Button 3 */
+#define HID_JOYSTICK_BTN4 (1 << 7) /**< Button 4 */
+
+/** Access to the absolute X position in HID joystick report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_joystick_x(rpt) ((int8_t)rpt[0])
+/** Access to the absolute Y position in HID joystick report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_joystick_y(rpt) ((int8_t)rpt[1])
+/** Access to the button state in HID joystick report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_joystick_btn_state(rpt) (rpt[2])
+/** Check if the button is done in HID joystick report
+ * \param rpt Pointer to report data of bytes
+ * \param btn Button bitmap to check
+ */
+#define hid_joystick_is_btn_down(rpt, btn) (rpt[2] & (btn))
+/** Get the Hat switch in HID joystick report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_joystick_hat_sw(rpt) (rpt[2] & 0xF)
+/** Access to the throttle in HID joystick report
+ * \param rpt Pointer to report data of bytes
+ */
+#define hid_joystick_throttle(rpt) (rpt[3])
+
+/*@}*/
+
+/**
+ * \brief Fill a GetHIDDescriptor request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] type Descriptor type
+ * \param[in] index Descriptor index
+ * \param[in] iface Interface Number
+ * \param[in] len Descriptor Length
+ */
+static inline void usb_fill_GetHIDDesc_req(struct usb_req *req, uint8_t type, uint8_t index, uint8_t iface,
+ uint16_t len)
+{
+ req->bmRequestType = 0x81;
+ req->bRequest = USB_REQ_GET_DESC;
+ req->wValue = (type << 8) | index;
+ req->wIndex = iface;
+ req->wLength = len;
+}
+
+/**
+ * \brief Fill a SetHIDDescriptor request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] type Descriptor type
+ * \param[in] index Descriptor index
+ * \param[in] iface Interface Number
+ * \param[in] len Descriptor Length
+ */
+static inline void usb_fill_SetHIDDesc_req(struct usb_req *req, uint8_t type, uint8_t index, uint8_t iface,
+ uint16_t len)
+{
+ req->bmRequestType = 0x01;
+ req->bRequest = USB_REQ_SET_DESC;
+ req->wValue = (type << 8) | index;
+ req->wIndex = iface;
+ req->wLength = len;
+}
+
+/**
+ * \brief Fill a GetReport request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] type Report type
+ * \param[in] id Report ID
+ * \param[in] iface Interface Number
+ * \param[in] len Report Length
+ */
+static inline void usb_fill_GetReport_req(struct usb_req *req, uint8_t type, uint8_t id, uint8_t iface, uint16_t len)
+{
+ req->bmRequestType = 0xA1;
+ req->bRequest = USB_REQ_HID_GET_REPORT;
+ req->wValue = (type << 8) | id;
+ req->wIndex = iface;
+ req->wLength = len;
+}
+
+/**
+ * \brief Fill a SetReport request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] type Report type
+ * \param[in] id Report ID
+ * \param[in] iface Interface Number
+ * \param[in] len Report Length
+ */
+static inline void usb_fill_SetReport_req(struct usb_req *req, uint8_t type, uint8_t id, uint8_t iface, uint16_t len)
+{
+ req->bmRequestType = 0x21;
+ req->bRequest = USB_REQ_HID_GET_REPORT;
+ req->wValue = (type << 8) | id;
+ req->wIndex = iface;
+ req->wLength = len;
+}
+
+/**
+ * \brief Fill a GetIdle request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] id Report ID
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_GetIdle_req(struct usb_req *req, uint8_t id, uint8_t iface)
+{
+ req->bmRequestType = 0xA1;
+ req->bRequest = USB_REQ_HID_GET_IDLE;
+ req->wValue = id;
+ req->wIndex = iface;
+ req->wLength = 1;
+}
+
+/**
+ * \brief Fill a SetIdle request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] duration Duration value
+ * \param[in] id Report ID
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_SetIdle_req(struct usb_req *req, uint8_t duration, uint8_t id, uint8_t iface)
+{
+ req->bmRequestType = 0x21;
+ req->bRequest = USB_REQ_HID_SET_IDLE;
+ req->wValue = (duration << 8) | id;
+ req->wIndex = iface;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a GetProtocol request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_GetProtocol_req(struct usb_req *req, uint8_t iface)
+{
+ req->bmRequestType = 0xA1;
+ req->bRequest = USB_REQ_HID_GET_PROTOCOL;
+ req->wValue = 0;
+ req->wIndex = iface;
+ req->wLength = 1;
+}
+
+/**
+ * \brief Fill a SetProtocol request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_SetProtocol_req(struct usb_req *req, uint8_t protocol, uint8_t iface)
+{
+ req->bmRequestType = 0x21;
+ req->bRequest = USB_REQ_HID_SET_PROTOCOL;
+ req->wValue = protocol;
+ req->wIndex = iface;
+ req->wLength = 0;
+}
+
+#endif // _USB_PROTOCOL_HID_H_
diff --git a/atmel-samd/asf4/samd21/usb/class/hub/usb_protocol_hub.h b/atmel-samd/asf4/samd21/usb/class/hub/usb_protocol_hub.h
new file mode 100644
index 000000000..dbfc04a2c
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/hub/usb_protocol_hub.h
@@ -0,0 +1,364 @@
+/**
+ * \file
+ *
+ * \brief USB hub protocol definitions.
+ *
+ * Copyright (c) 2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef _USB_PROTOCOL_HUB_H_
+#define _USB_PROTOCOL_HUB_H_
+
+#include <usb_protocol.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \name Possible class value */
+/*@{*/
+#define HUB_CLASS 0x09
+/*@}*/
+
+/** \brief Hub USB requests (bRequest) */
+enum usb_reqid_hub {
+ USB_REQ_HUB_GET_STATUS = 0,
+ /** CLEAR_FEATURE */
+ USB_REQ_HUB_CLR_FTR = 1,
+ /** SET_FEATURE */
+ USB_REQ_HUB_SET_FTR = 3,
+ /** GET_DESCRIPTOR */
+ USB_REQ_HUB_GET_DESC = 6,
+ /** SET_DESCRIPTOR */
+ USB_REQ_HUB_SET_DESC = 7,
+ /** CLEAR_TT_BUFFER */
+ USB_REQ_HUB_CLR_TT_BUF = 8,
+ /** RESET_TT */
+ USB_REQ_HUB_RESET_TT = 9,
+ /** GET_TT_STATE */
+ USB_REQ_HUB_GET_TT_STATE = 10,
+ /** STOP_TT */
+ USB_REQ_HUB_STOP_TT
+};
+
+/** \brief Hub USB descriptor type */
+enum usb_descriptor_type_hub { USB_DT_HUB = 0x29 };
+
+/** \brief Hub feature selector */
+enum usb_hub_ftr_sel {
+ USB_HUB_FTR_C_HUB_LOCAL_POWER = 0,
+ USB_HUB_FTR_C_HUB_OVER_CURRENT = 1,
+ USB_HUB_FTR_PORT_CONNECTION = 0,
+ USB_HUB_FTR_PORT_ENABLE = 1,
+ USB_HUB_FTR_PORT_SUSPEND = 2,
+ USB_HUB_FTR_PORT_OVER_CURRENT = 3,
+ USB_HUB_FTR_PORT_RESET = 4,
+ USB_HUB_FTR_PORT_POWER = 8,
+ USB_HUB_FTR_PORT_LOW_SPEED = 9,
+ USB_HUB_FTR_PORT_LS = 9,
+ USB_HUB_FTR_PORT_HIGH_SPEED = 10,
+ USB_HUB_FTR_PORT_HS = 10,
+ USB_HUB_FTR_C_PORT_CONNECTION = 16,
+ USB_HUB_FTR_C_PORT_ENABLE = 17,
+ USB_HUB_FTR_C_PORT_SUSPEND = 18,
+ USB_HUB_FTR_C_PORT_OVER_CURRENT = 19,
+ USB_HUB_FTR_C_PORT_RESET = 20,
+ USB_HUB_FTR_PORT_TEST = 21,
+ USB_HUB_FTR_PORT_INDICATOR
+};
+
+COMPILER_PACK_SET(1)
+
+/**
+ * \brief General Hub Descriptor
+ */
+typedef struct usb_hub_descriptor {
+ uint8_t bDescLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint32_t variables[1];
+} usb_hub_descriptor_t;
+
+/**
+ * \brief Hub Descriptor with no more than 7 ports
+ */
+typedef struct usb_hub_descriptor_7p {
+ uint8_t bDescLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable[1];
+ uint8_t PortPwrCtrlMask[1];
+} usb_hub_descriptor_7p_t;
+
+/**
+ * \brief Hub Descriptor with no more than 15 ports
+ */
+typedef struct usb_hub_descriptor_15p {
+ uint8_t bDescLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable[2];
+ uint8_t PortPwrCtrlMask[2];
+} usb_hub_descriptor_15p_t;
+
+/**
+ * \brief Hub Descriptor with no more than 23 ports
+ */
+typedef struct usb_hub_descriptor_23p {
+ uint8_t bDescLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable[3];
+ uint8_t PortPwrCtrlMask[3];
+} usb_hub_descriptor_23p_t;
+
+/**
+ * \brief Hub Descriptor with no more than 31 ports
+ */
+typedef struct usb_hub_descriptor_31p {
+ uint8_t bDescLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable[4];
+ uint8_t PortPwrCtrlMask[4];
+} usb_hub_descriptor_31p_t;
+
+COMPILER_PACK_RESET()
+
+/**
+ * \brief Check if hub change is detected
+ * \param[in] bitmap Pointer to the bitmap location
+ * \return \c true if hub change is detected
+ */
+static inline bool usb_is_hub_change_detected(const uint8_t *bitmap)
+{
+ return (*bitmap & 0x1);
+}
+
+/**
+ * \brief Check if port change is detected
+ * \param[in] bitmap Pointer to the bitmap location
+ * \param[in] port Port number ( 1 ~ n )
+ * \return \c true if port change is detected
+ */
+static inline bool usb_is_port_change_detected(const uint8_t *bitmap, const uint8_t port)
+{
+ uint8_t idx = port >> 3;
+ uint8_t pos = port & 0x7;
+ return (bitmap[idx] & (1u << pos));
+}
+
+/**
+ * \brief Fill a ClearHubFeature request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] ftr Feature selector
+ */
+static inline void usb_fill_ClrHubFtr_req(struct usb_req *req, uint8_t ftr)
+{
+ req->bmRequestType = 0x20;
+ req->bRequest = USB_REQ_CLEAR_FTR;
+ req->wValue = ftr;
+ req->wIndex = 0;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a ClearPortFeature request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] ftr Feature selector
+ * \param[in] port Port number ( 1 ~ n )
+ */
+static inline void usb_fill_ClrPortFtr_req(struct usb_req *req, uint8_t ftr, uint8_t port)
+{
+ req->bmRequestType = 0x23;
+ req->bRequest = USB_REQ_CLEAR_FTR;
+ req->wValue = ftr;
+ req->wIndex = port;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a ClearTTBuffer request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] dev Dev_Addr
+ * \param[in] ep EP_Num
+ * \param[in] tt_port TT_port
+ */
+static inline void usb_fill_ClrTTBuf_req(struct usb_req *req, uint8_t dev, uint8_t ep, uint8_t tt_port)
+{
+ req->bmRequestType = 0x23;
+ req->bRequest = USB_REQ_HUB_CLR_TT_BUF;
+ req->wValue = (dev << 8) | ep;
+ req->wIndex = tt_port;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a GetHubDescriptor request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] len Length of available buffer for request data
+ */
+static inline void usb_fill_GetHubDesc_req(struct usb_req *req, uint16_t len)
+{
+ req->bmRequestType = 0xA0;
+ req->bRequest = USB_REQ_GET_DESC;
+ req->wValue = (USB_DT_HUB << 8) | 0;
+ req->wIndex = 0;
+ req->wLength = len;
+}
+
+/**
+ * \brief Fill a GetHubStatus request
+ * \param[out] req Pointer to the request to fill
+ */
+static inline void usb_fill_GetHubStatus_req(struct usb_req *req)
+{
+ req->bmRequestType = 0xA0;
+ req->bRequest = USB_REQ_GET_STATUS;
+ req->wValue = 0;
+ req->wIndex = 0;
+ req->wLength = 4;
+}
+
+/**
+ * \brief Fill a GetPortStatus request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] port Port number ( 1 ~ n )
+ */
+static inline void usb_fill_GetPortStatus_req(struct usb_req *req, uint8_t port)
+{
+ req->bmRequestType = 0xA3;
+ req->bRequest = USB_REQ_GET_STATUS;
+ req->wValue = 0;
+ req->wIndex = port;
+ req->wLength = 4;
+}
+
+/**
+ * \brief Fill a ResetTT request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] port Port number ( 1 ~ n )
+ */
+static inline void usb_fill_ResetTT_req(struct usb_req *req, uint8_t port)
+{
+ req->bmRequestType = 0x23;
+ req->bRequest = USB_REQ_HUB_RESET_TT;
+ req->wValue = 0;
+ req->wIndex = port;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a SetHubFeature request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] ftr Feature selector
+ */
+static inline void usb_fill_SetHubFtr_req(struct usb_req *req, uint8_t ftr)
+{
+ req->bmRequestType = 0x20;
+ req->bRequest = USB_REQ_SET_FTR;
+ req->wValue = ftr;
+ req->wIndex = 0;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a SetPortFeature request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] ftr Feature selector
+ * \param[in] port Port number ( 1 ~ n )
+ */
+static inline void usb_fill_SetPortFtr_req(struct usb_req *req, uint8_t ftr, uint8_t port)
+{
+ req->bmRequestType = 0x23;
+ req->bRequest = USB_REQ_SET_FTR;
+ req->wValue = ftr;
+ req->wIndex = port;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a GetTTState request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] tt_flags TT_Flags
+ * \param[in] port Port number ( 1 ~ n )
+ * \param[in] len TT State Length
+ */
+static inline void usb_fill_GetTTState_req(struct usb_req *req, uint16_t tt_flags, uint8_t port, uint16_t len)
+{
+ req->bmRequestType = 0xA3;
+ req->bRequest = USB_REQ_HUB_GET_TT_STATE;
+ req->wValue = tt_flags;
+ req->wIndex = port;
+ req->wLength = len;
+}
+
+/**
+ * \brief Fill a StopTT request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] port Port number ( 1 ~ n )
+ */
+static inline void usb_fill_StopTT_req(struct usb_req *req, uint8_t port)
+{
+ req->bmRequestType = 0x23;
+ req->bRequest = USB_REQ_HUB_STOP_TT;
+ req->wValue = 0;
+ req->wIndex = port;
+ req->wLength = 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _USB_PROTOCOL_HUB_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/class/msc/sbc_protocol.h b/atmel-samd/asf4/samd21/usb/class/msc/sbc_protocol.h
new file mode 100644
index 000000000..925933522
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/msc/sbc_protocol.h
@@ -0,0 +1,163 @@
+/**
+ * \file
+ *
+ * \brief SCSI Block Commands
+ *
+ * This file contains definitions of some of the commands found in the
+ * SCSI SBC-2 standard.
+ *
+ * Note that the SBC specification depends on several commands defined
+ * by the SCSI Primary Commands (SPC) standard. Each version of the SBC
+ * standard is meant to be used in conjunction with a specific version
+ * of the SPC standard, as follows:
+ * - SBC depends on SPC
+ * - SBC-2 depends on SPC-3
+ * - SBC-3 depends on SPC-4
+ *
+ * Copyright (c) 2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+#ifndef _SBC_PROTOCOL_H_
+#define _SBC_PROTOCOL_H_
+
+/**
+ * \ingroup usb_msc_protocol
+ * \defgroup usb_sbc_protocol SCSI Block Commands protocol definitions
+ *
+ * @{
+ */
+
+/** \name SCSI commands defined by SBC-2 */
+#define SBC_FORMAT_UNIT 0x04
+#define SBC_READ6 0x08
+#define SBC_WRITE6 0x0A
+#define SBC_START_STOP_UNIT 0x1B
+#define SBC_READ_CAPACITY10 0x25
+#define SBC_READ10 0x28
+#define SBC_WRITE10 0x2A
+#define SBC_VERIFY10 0x2F
+
+/** \name SBC-2 Mode page definitions */
+enum scsi_sbc_mode {
+ SCSI_MS_MODE_RW_ERR_RECOV = 0x01, /**< Read-Write Error Recovery mode page */
+ SCSI_MS_MODE_FORMAT_DEVICE = 0x03, /**< Format Device mode page */
+ SCSI_MS_MODE_FLEXIBLE_DISK = 0x05, /**< Flexible Disk mode page */
+ SCSI_MS_MODE_CACHING = 0x08
+};
+
+/** \name SBC-2 Device-Specific Parameter */
+#define SCSI_MS_SBC_WP 0x80 /**< Write Protected */
+#define SCSI_MS_SBC_DPOFUA 0x10 /**< DPO and FUA supported */
+
+/**
+ * \brief SBC-2 Short LBA mode parameter block descriptor
+ * \note Fields are MSB first (BE)
+ */
+struct sbc_slba_block_desc {
+ be32_t nr_blocks; /**< Number of Blocks (BE32) */
+ be32_t block_len; /**< Block Length (BE32) */
+#define SBC_SLBA_BLOCK_LEN_MASK 0x00FFFFFFU /**< Mask reserved bits */
+};
+
+/**
+ * \brief SBC-2 Caching mode page
+ * \note Fields are MSB first (BE)
+ */
+struct sbc_caching_mode_page {
+ uint8_t page_code;
+ uint8_t page_length;
+ uint8_t flags2;
+#define SBC_MP_CACHE_IC (1 << 7) /**< Initiator Control */
+#define SBC_MP_CACHE_ABPF (1 << 6) /**< Abort Pre-Fetch */
+#define SBC_MP_CACHE_CAP (1 << 5) /**< Catching Analysis Permitted */
+#define SBC_MP_CACHE_DISC (1 << 4) /**< Discontinuity */
+#define SBC_MP_CACHE_SIZE (1 << 3) /**< Size enable */
+#define SBC_MP_CACHE_WCE (1 << 2) /**< Write back Cache Enable */
+#define SBC_MP_CACHE_MF (1 << 1) /**< Multiplication Factor */
+#define SBC_MP_CACHE_RCD (1 << 0) /**< Read Cache Disable */
+ uint8_t retention;
+ be16_t dis_pf_transfer_len;
+ be16_t min_prefetch;
+ be16_t max_prefetch;
+ be16_t max_prefetch_ceil;
+ uint8_t flags12;
+#define SBC_MP_CACHE_FSW (1 << 7) /**< Force Sequential Write */
+#define SBC_MP_CACHE_LBCSS (1 << 6) /**< Logical Blk Cache Seg Sz */
+#define SBC_MP_CACHE_DRA (1 << 5) /**< Disable Read-Ahead */
+#define SBC_MP_CACHE_NV_DIS (1 << 0) /**< Non-Volatile Cache Disable */
+ uint8_t nr_cache_segments;
+ be16_t cache_segment_size;
+ uint8_t reserved[4];
+};
+
+/**
+ * \brief SBC-2 Read-Write Error Recovery mode page
+ * \note Fields are MSB first (BE)
+ */
+struct sbc_rdwr_error_recovery_mode_page {
+ uint8_t page_code;
+ uint8_t page_length;
+#define SPC_MP_RW_ERR_RECOV_PAGE_LENGTH 0x0A
+ uint8_t flags1;
+#define SBC_MP_RW_ERR_RECOV_AWRE (1 << 7)
+#define SBC_MP_RW_ERR_RECOV_ARRE (1 << 6)
+#define SBC_MP_RW_ERR_RECOV_TB (1 << 5)
+#define SBC_MP_RW_ERR_RECOV_RC (1 << 4)
+#define SBC_MP_RW_ERR_RECOV_ERR (1 << 3)
+#define SBC_MP_RW_ERR_RECOV_PER (1 << 2)
+#define SBC_MP_RW_ERR_RECOV_DTE (1 << 1)
+#define SBC_MP_RW_ERR_RECOV_DCR (1 << 0)
+ uint8_t read_retry_count;
+ uint8_t correction_span;
+ uint8_t head_offset_count;
+ uint8_t data_strobe_offset_count;
+ uint8_t flags2;
+ uint8_t write_retry_count;
+ uint8_t flags3;
+ be16_t recovery_time_limit;
+};
+
+/**
+ * \brief SBC-2 READ CAPACITY (10) parameter data (8 bytes)
+ * \note Fields are MSB first (BE)
+ */
+struct sbc_read_capacity10_data {
+ be32_t max_lba; /**< LBA of last logical block (BE32) */
+ be32_t block_len; /**< Number of bytes in the last logical block (BE32) */
+};
+
+#endif /*_SBC_PROTOCOL_H_*/
diff --git a/atmel-samd/asf4/samd21/usb/class/msc/spc_protocol.h b/atmel-samd/asf4/samd21/usb/class/msc/spc_protocol.h
new file mode 100644
index 000000000..c44cbef32
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/msc/spc_protocol.h
@@ -0,0 +1,340 @@
+/**
+ * \file
+ *
+ * \brief SCSI Primary Commands
+ *
+ * This file contains definitions of some of the commands found in the
+ * SPC-2 standard.
+ *
+ * Copyright (c) 2009-2012 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+#ifndef _SPC_PROTOCOL_H_
+#define _SPC_PROTOCOL_H_
+
+/**
+ * \ingroup usb_msc_protocol
+ * \defgroup usb_spc_protocol SCSI Primary Commands protocol definitions
+ *
+ *
+ */
+
+/**< \name SCSI commands defined by SPC-2 */
+#define SPC_TEST_UNIT_READY 0x00
+#define SPC_REQUEST_SENSE 0x03
+#define SPC_INQUIRY 0x12
+#define SPC_MODE_SELECT6 0x15
+#define SPC_MODE_SENSE6 0x1A
+#define SPC_SEND_DIAGNOSTIC 0x1D
+#define SPC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
+#define SPC_MODE_SENSE10 0x5A
+#define SPC_REPORT_LUNS 0xA0
+
+/**< \brief May be set in byte 0 of the INQUIRY CDB */
+/**< Enable Vital Product Data */
+#define SCSI_INQ_REQ_EVPD 0x01
+/**< Command Support Data specified by the PAGE OR OPERATION CODE field */
+#define SCSI_INQ_REQ_CMDT 0x02
+
+COMPILER_PACK_SET(1)
+
+/**
+ * \brief SCSI Standard Inquiry data structure
+ */
+struct scsi_inquiry_data {
+ uint8_t pq_pdt; /**< Peripheral Qual / Peripheral Dev Type */
+#define SCSI_INQ_PQ_CONNECTED 0x00 /**< Peripheral connected */
+#define SCSI_INQ_PQ_NOT_CONN 0x20 /**< Peripheral not connected */
+#define SCSI_INQ_PQ_NOT_SUPP 0x60 /**< Peripheral not supported */
+#define SCSI_INQ_DT_DIR_ACCESS 0x00 /**< Direct Access (SBC) */
+#define SCSI_INQ_DT_SEQ_ACCESS 0x01 /**< Sequential Access */
+#define SCSI_INQ_DT_PRINTER 0x02 /**< Printer */
+#define SCSI_INQ_DT_PROCESSOR 0x03 /**< Processor device */
+#define SCSI_INQ_DT_WRITE_ONCE 0x04 /**< Write-once device */
+#define SCSI_INQ_DT_CD_DVD 0x05 /**< CD/DVD device */
+#define SCSI_INQ_DT_OPTICAL 0x07 /**< Optical Memory */
+#define SCSI_INQ_DT_MC 0x08 /**< Medium Changer */
+#define SCSI_INQ_DT_ARRAY 0x0c /**< Storage Array Controller */
+#define SCSI_INQ_DT_ENCLOSURE 0x0d /**< Enclosure Services */
+#define SCSI_INQ_DT_RBC 0x0e /**< Simplified Direct Access */
+#define SCSI_INQ_DT_OCRW 0x0f /**< Optical card reader/writer */
+#define SCSI_INQ_DT_BCC 0x10 /**< Bridge Controller Commands */
+#define SCSI_INQ_DT_OSD 0x11 /**< Object-based Storage */
+#define SCSI_INQ_DT_NONE 0x1f /**< No Peripheral */
+ uint8_t flags1; /**< Flags (byte 1) */
+#define SCSI_INQ_RMB 0x80 /**< Removable Medium */
+ uint8_t version; /**< Version */
+#define SCSI_INQ_VER_NONE 0x00 /**< No standards conformance */
+#define SCSI_INQ_VER_SPC 0x03 /**< SCSI Primary Commands (link to SBC) */
+#define SCSI_INQ_VER_SPC2 0x04 /**< SCSI Primary Commands - 2 (link to SBC-2) */
+#define SCSI_INQ_VER_SPC3 0x05 /**< SCSI Primary Commands - 3 (link to SBC-2) */
+#define SCSI_INQ_VER_SPC4 0x06 /**< SCSI Primary Commands - 4 (link to SBC-3) */
+ uint8_t flags3; /**< Flags (byte 3) */
+#define SCSI_INQ_NORMACA 0x20 /**< Normal ACA Supported */
+#define SCSI_INQ_HISUP 0x10 /**< Hierarchal LUN addressing */
+#define SCSI_INQ_RSP_SPC2 0x02 /**< SPC-2 / SPC-3 response format */
+ uint8_t addl_len; /**< Additional Length (n-4) */
+#define SCSI_INQ_ADDL_LEN(tot) ((tot)-5) /**< Total length is \a tot */
+ uint8_t flags5; /**< Flags (byte 5) */
+#define SCSI_INQ_SCCS 0x80
+ uint8_t flags6; /**< Flags (byte 6) */
+#define SCSI_INQ_BQUE 0x80
+#define SCSI_INQ_ENCSERV 0x40
+#define SCSI_INQ_MULTIP 0x10
+#define SCSI_INQ_MCHGR 0x08
+#define SCSI_INQ_ADDR16 0x01
+ uint8_t flags7; /**< Flags (byte 7) */
+#define SCSI_INQ_WBUS16 0x20
+#define SCSI_INQ_SYNC 0x10
+#define SCSI_INQ_LINKED 0x08
+#define SCSI_INQ_CMDQUE 0x02
+ uint8_t vendor_id[8]; /**< T10 Vendor Identification */
+ uint8_t product_id[16]; /**< Product Identification */
+ uint8_t product_rev[4]; /**< Product Revision Level */
+};
+
+/**
+ * \brief SCSI Standard Request sense data structure
+ */
+#define SCSI_SENSE_VALID 0x80 /**< Indicates the INFORMATION field contains valid information */
+#define SCSI_SENSE_RESPONSE_CODE_MASK 0x7F
+#define SCSI_SENSE_CURRENT 0x70 /**< Response code 70h (current errors) */
+#define SCSI_SENSE_DEFERRED 0x71
+
+#define SCSI_SENSE_FILEMARK 0x80 /**< Indicates that the current command has read a filemark or setmark. */
+#define SCSI_SENSE_EOM 0x40 /**< Indicates that an end-of-medium condition exists. */
+#define SCSI_SENSE_ILI \
+ 0x20 /**< Indicates that the requested logical block length did not match the logical block length of the data on \
+ the medium. */
+#define SCSI_SENSE_RESERVED 0x10 /**< Reserved */
+#define SCSI_SENSE_KEY(x) (x & 0x0F) /**< Sense Key */
+
+#define SCSI_SENSE_ADDL_LEN(total_len) ((total_len)-8)
+
+#define SCSI_SENSE_SKSV 0x80 /**< Indicates the SENSE-KEY SPECIFIC field contains valid information */
+
+struct scsi_request_sense_data {
+ /** 1st byte: REQUEST SENSE response flags*/
+ uint8_t valid_reponse_code;
+ /** 2nd byte */
+ uint8_t obsolete;
+ /** 3rd byte */
+ uint8_t sense_flag_key;
+ /** 4th to 7th bytes - INFORMATION field */
+ uint8_t information[4];
+ /** 8th byte - ADDITIONAL SENSE LENGTH field */
+ uint8_t AddSenseLen;
+ /** 9th to 12th byte - COMMAND-SPECIFIC INFORMATION field */
+ uint8_t CmdSpecINFO[4];
+ /** 13th to 14th byte - ADDITIONAL SENSE CODE and QUALIFIER field */
+ union {
+ struct {
+ uint8_t code; /**< ADDITIONAL SENSE CODE (ASC) */
+ uint8_t qualifier; /**< ADDITIONAL SENSE CODE QUALIFIER (ASCQ) */
+ } add_sense;
+ be16_t AddSense; /**< ASC | ASCQ */
+ };
+ /** 15th byte - FIELD REPLACEABLE UNIT CODE field */
+ uint8_t FldReplUnitCode;
+ /** 16th byte */
+ uint8_t SenseKeySpec[3];
+};
+
+COMPILER_PACK_RESET()
+
+/**< Vital Product Data page codes */
+enum scsi_vpd_page_code {
+ SCSI_VPD_SUPPORTED_PAGES = 0x00,
+ SCSI_VPD_UNIT_SERIAL_NUMBER = 0x80,
+ SCSI_VPD_DEVICE_IDENTIFICATION = 0x83
+};
+#define SCSI_VPD_HEADER_SIZE 4
+
+/**< Constants associated with the Device Identification VPD page */
+#define SCSI_VPD_ID_HEADER_SIZE 4
+
+#define SCSI_VPD_CODE_SET_BINARY 1
+#define SCSI_VPD_CODE_SET_ASCII 2
+#define SCSI_VPD_CODE_SET_UTF8 3
+
+#define SCSI_VPD_ID_TYPE_T10 1
+
+/**< Sense keys */
+enum scsi_sense_key {
+ SCSI_SK_NO_SENSE = 0x0,
+ SCSI_SK_RECOVERED_ERROR = 0x1,
+ SCSI_SK_NOT_READY = 0x2,
+ SCSI_SK_MEDIUM_ERROR = 0x3,
+ SCSI_SK_HARDWARE_ERROR = 0x4,
+ SCSI_SK_ILLEGAL_REQUEST = 0x5,
+ SCSI_SK_UNIT_ATTENTION = 0x6,
+ SCSI_SK_DATA_PROTECT = 0x7,
+ SCSI_SK_BLANK_CHECK = 0x8,
+ SCSI_SK_VENDOR_SPECIFIC = 0x9,
+ SCSI_SK_COPY_ABORTED = 0xa,
+ SCSI_SK_ABORTED_COMMAND = 0xb,
+ SCSI_SK_VOLUME_OVERFLOW = 0xd,
+ SCSI_SK_MISCOMPARE = 0xe
+};
+
+/**< Additional Sense Code | Additional Sense Code Qualifier pairs (BE16) */
+enum scsi_asc_ascq {
+ SCSI_ASC_NO_ADDITIONAL_SENSE_INFO = 0x0000,
+ SCSI_ASC_LU_NOT_READY_REBUILD_IN_PROGRESS = 0x0405,
+ SCSI_ASC_WRITE_ERROR = 0x0c00,
+ SCSI_ASC_UNRECOVERED_READ_ERROR = 0x1100,
+ SCSI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x2000,
+ SCSI_ASC_INVALID_FIELD_IN_CDB = 0x2400,
+ SCSI_ASC_WRITE_PROTECTED = 0x2700,
+ SCSI_ASC_NOT_READY_TO_READY_CHANGE = 0x2800,
+ SCSI_ASC_MEDIUM_NOT_PRESENT = 0x3A00,
+ SCSI_ASC_INTERNAL_TARGET_FAILURE = 0x4400
+};
+
+/**
+ * \brief SPC-2 Mode parameter
+ * This subclauses describes the block descriptors and the pages
+ * used with MODE SELECT and MODE SENSE commands
+ * that are applicable to all SCSI devices.
+ */
+enum scsi_spc_mode {
+ SCSI_MS_MODE_VENDOR_SPEC = 0x00,
+ SCSI_MS_MODE_INFEXP = 0x1C, /**< Informational exceptions control page */
+ SCSI_MS_MODE_ALL = 0x3f
+};
+
+/**
+ * \brief SPC-2 Informational exceptions control page
+ * See chapter 8.3.8
+ * \note Fields are MSB first (BE)
+ */
+struct spc_control_page_info_execpt {
+ uint8_t page_code;
+ uint8_t page_length;
+#define SPC_MP_INFEXP_PAGE_LENGTH 0x0A
+ uint8_t flags1;
+#define SPC_MP_INFEXP_PERF (1 << 7) /**< Initiator Control */
+#define SPC_MP_INFEXP_EBF (1 << 5) /**< Caching Analysis Permitted */
+#define SPC_MP_INFEXP_EWASC (1 << 4) /**< Discontinuity */
+#define SPC_MP_INFEXP_DEXCPT (1 << 3) /**< Size enable */
+#define SPC_MP_INFEXP_TEST (1 << 2) /**< Write-back Cache Enable */
+#define SPC_MP_INFEXP_LOGERR (1 << 0) /**< Log errors bit */
+ uint8_t mrie;
+#define SPC_MP_INFEXP_MRIE_NO_REPORT 0x00
+#define SPC_MP_INFEXP_MRIE_ASYNC_EVENT 0x01
+#define SPC_MP_INFEXP_MRIE_GEN_UNIT 0x02
+#define SPC_MP_INFEXP_MRIE_COND_RECOV_ERROR 0x03
+#define SPC_MP_INFEXP_MRIE_UNCOND_RECOV_ERROR 0x04
+#define SPC_MP_INFEXP_MRIE_NO_SENSE 0x05
+#define SPC_MP_INFEXP_MRIE_ONLY_REPORT 0x06
+ be32_t interval_timer;
+ be32_t report_count;
+};
+
+enum scsi_spc_mode_sense_pc {
+ SCSI_MS_SENSE_PC_CURRENT = 0,
+ SCSI_MS_SENSE_PC_CHANGEABLE = 1,
+ SCSI_MS_SENSE_PC_DEFAULT = 2,
+ SCSI_MS_SENSE_PC_SAVED = 3
+};
+
+/**
+ * \brief Check whether dbd field is set in sense code
+ * \param[in] cdb pointer to the sense code block
+ * \return Operation status.
+ */
+static inline bool scsi_mode_sense_dbd_is_set(const uint8_t *cdb)
+{
+ return (cdb[1] >> 3) & 1;
+}
+
+/**
+ * \brief Get page code from mode sense code
+ * \param[in] cdb pointer to the sense code block
+ * \return Operation status.
+ */
+static inline uint8_t scsi_mode_sense_get_page_code(const uint8_t *cdb)
+{
+ return cdb[2] & 0x3f;
+}
+
+/**
+ * \brief Get pc from mode sense code
+ * \param[in] cdb pointer to the sense code block
+ * \return Operation status.
+ */
+static inline uint8_t scsi_mode_sense_get_pc(const uint8_t *cdb)
+{
+ return cdb[2] >> 6;
+}
+
+/**
+ * \brief SCSI Mode Parameter Header used by MODE SELECT(6) and MODE SENSE(6)
+ * \note Fields are MSB first (BE)
+ */
+struct scsi_mode_param_header6 {
+ uint8_t mode_data_length; /**< Number of bytes after this */
+ uint8_t medium_type; /**< Medium Type */
+ uint8_t device_specific_parameter; /**< Defined by command set */
+ uint8_t block_descriptor_length; /**< Length of block descriptors */
+};
+
+/**
+ * \brief SCSI Mode Parameter Header used by MODE SELECT(10) and MODE SENSE(10)
+ * \note Fields are MSB first (BE)
+ */
+struct scsi_mode_param_header10 {
+ le16_t mode_data_length; /**< Number of bytes after this */
+ uint8_t medium_type; /**< Medium Type */
+ uint8_t device_specific_parameter; /**< Defined by command set */
+ uint8_t flags4; /**< LONGLBA in bit 0 */
+ uint8_t reserved;
+ le16_t block_descriptor_length; /**< Length of block descriptors */
+};
+
+/**
+ * \brief SCSI Page_0 Mode Page header (SPF not set)
+ */
+struct scsi_mode_page_0_header {
+ uint8_t page_code;
+#define SCSI_PAGE_CODE_PS (1 << 7) /**< Parameters Savable */
+#define SCSI_PAGE_CODE_SPF (1 << 6) /**< SubPage Format */
+ uint8_t page_length; /**< Number of bytes after this */
+#define SCSI_MS_PAGE_LEN(total) ((total)-2)
+};
+
+#endif /**< SPC_PROTOCOL_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/class/msc/usb_protocol_msc.h b/atmel-samd/asf4/samd21/usb/class/msc/usb_protocol_msc.h
new file mode 100644
index 000000000..f69eae232
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/msc/usb_protocol_msc.h
@@ -0,0 +1,177 @@
+/**
+ * \file
+ *
+ * \brief USB Mass Storage Class (MSC) protocol definitions.
+ *
+ * Copyright (c) 2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+
+#ifndef _USB_PROTOCOL_MSC_H_
+#define _USB_PROTOCOL_MSC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \ingroup usb_protocol_group
+ * \defgroup usb_msc_protocol USB Mass Storage Class (MSC) protocol definitions
+ *
+ * @{
+ */
+
+/**
+ * \name Possible Class value
+ */
+//@{
+#define MSC_CLASS 0x08
+//@}
+
+/**
+ * \name Possible SubClass value
+ * \note In practice, most devices should use
+ * #MSC_SUBCLASS_TRANSPARENT and specify the actual command set in
+ * the standard INQUIRY data block, even if the MSC spec indicates
+ * otherwise. In particular, RBC is not supported by certain major
+ * operating systems like Windows XP.
+ */
+//@{
+#define MSC_SUBCLASS_RBC 0x01 /**< Reduced Block Commands */
+#define MSC_SUBCLASS_ATAPI 0x02 /**< CD/DVD devices */
+#define MSC_SUBCLASS_QIC_157 0x03 /**< Tape devices */
+#define MSC_SUBCLASS_UFI 0x04 /**< Floppy disk drives */
+#define MSC_SUBCLASS_SFF_8070I 0x05 /**< Floppy disk drives */
+#define MSC_SUBCLASS_TRANSPARENT 0x06 /**< Determined by INQUIRY */
+ //@}
+
+/**
+ * \name Possible protocol value
+ * \note Only the BULK protocol should be used in new designs.
+ */
+//@{
+#define MSC_PROTOCOL_CBI 0x00 /**< Command/Bulk/Interrupt */
+#define MSC_PROTOCOL_CBI_ALT 0x01 /**< W/o command completion */
+#define MSC_PROTOCOL_BULK 0x50 /**< Bulk-only */
+ //@}
+
+/**
+ * \brief MSC USB requests (bRequest)
+ */
+
+#define USB_REQ_MSC_BULK_RESET 0xFF /**< Mass Storage Reset */
+#define USB_REQ_MSC_GET_MAX_LUN 0xFE /**< Get Max LUN */
+
+COMPILER_PACK_SET(1)
+
+/**
+ * \name A Command Block Wrapper (CBW)
+ * \note Fields are LSB first (LE)
+ */
+//@{
+struct usb_msc_cbw {
+ le32_t dCBWSignature; /**< Must contain 'USBC' (0x43425355, LE32) */
+ le32_t dCBWTag; /**< Unique command ID (LE32) */
+ le32_t dCBWDataTransferLength; /**< Number of bytes to transfer (LE32) */
+ uint8_t bmCBWFlags; /**< Direction in bit 7 */
+ uint8_t bCBWLUN; /**< Logical Unit Number */
+ uint8_t bCBWCBLength; /**< Number of valid CDB bytes */
+ uint8_t CDB[16]; /**< SCSI Command Descriptor Block */
+};
+
+#define USB_CBW_SIGNATURE 0x43425355 /**< dCBWSignature value */
+#define USB_CBW_DIRECTION_IN (1 << 7) /**< Data from device to host */
+#define USB_CBW_DIRECTION_OUT (0 << 7) /**< Data from host to device */
+#define USB_CBW_LUN_MASK 0x0F /**< Valid bits in bCBWLUN */
+#define USB_CBW_LEN_MASK 0x1F /**< Valid bits in bCBWCBLength */
+ //@}
+
+/**
+ * \name A Command Status Wrapper (CSW)
+ * \note Fields are LSB first (LE)
+ */
+//@{
+struct usb_msc_csw {
+ le32_t dCSWSignature; /**< Must contain 'USBS' */
+ le32_t dCSWTag; /**< Same as dCBWTag */
+ le32_t dCSWDataResidue; /**< Number of bytes not transfered */
+ uint8_t bCSWStatus; /**< Status code */
+};
+
+#define USB_CSW_SIGNATURE 0x53425355 /**< dCSWSignature value */
+#define USB_CSW_STATUS_PASS 0x00 /**< Command Passed */
+#define USB_CSW_STATUS_FAIL 0x01 /**< Command Failed */
+#define USB_CSW_STATUS_PE 0x02 /**< Phase Error */
+//@}
+
+COMPILER_PACK_RESET()
+
+//@}
+
+/**
+ * \brief Fill a Bulk-Only Mass Storage Reset request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_BOMSReset_req(struct usb_req *req, uint8_t iface)
+{
+ req->bmRequestType = 0x21;
+ req->bRequest = USB_REQ_MSC_BULK_RESET;
+ req->wValue = 0;
+ req->wIndex = iface;
+ req->wLength = 0;
+}
+
+/**
+ * \brief Fill a GetMaxLUN request
+ * \param[out] req Pointer to the request to fill
+ * \param[in] iface Interface Number
+ */
+static inline void usb_fill_GetMaxLUN_req(struct usb_req *req, uint8_t iface)
+{
+ req->bmRequestType = 0xA1;
+ req->bRequest = USB_REQ_MSC_GET_MAX_LUN;
+ req->wValue = 0;
+ req->wIndex = iface;
+ req->wLength = 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _USB_PROTOCOL_MSC_H_
diff --git a/atmel-samd/asf4/samd21/usb/class/vendor/usb_protocol_vendor.h b/atmel-samd/asf4/samd21/usb/class/vendor/usb_protocol_vendor.h
new file mode 100644
index 000000000..e865fb808
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/class/vendor/usb_protocol_vendor.h
@@ -0,0 +1,63 @@
+/**
+ * \file
+ *
+ * \brief USB Vendor class protocol definitions.
+ *
+ * Copyright (c) 2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef _USB_PROTOCOL_VENDOR_H_
+#define _USB_PROTOCOL_VENDOR_H_
+
+/**
+ * \ingroup usb_protocol_group
+ * \defgroup usb_vendor_protocol USB Vendor Class definitions
+ *
+ */
+
+/**
+ * \name Vendor class values
+ */
+#define VENDOR_CLASS 0xFF
+#define VENDOR_SUBCLASS 0xFF
+#define VENDOR_PROTOCOL 0xFF
+
+#endif /* _USB_PROTOCOL_VENDOR_H_ */
diff --git a/atmel-samd/asf4/samd21/usb/device/usbdc.c b/atmel-samd/asf4/samd21/usb/device/usbdc.c
new file mode 100644
index 000000000..f5243cad0
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/device/usbdc.c
@@ -0,0 +1,836 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack Core Layer Implementation.
+ *
+ * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel micro controller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \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;
+};
+
+/**
+ * \brief USB Device Core Driver Instance
+ */
+static struct usbdc_driver usbdc;
+
+/**
+ * \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 *cfg_desc, *str_desc;
+ uint16_t total_len;
+ uint16_t length = req->wLength;
+ uint8_t type = (uint8_t)(req->wValue >> 8);
+ uint8_t index = req->wValue & 0x00FF;
+ bool need_zlp = !(length & (usbdc.ctrl_size - 1));
+
+ switch (type) {
+ case USB_DT_DEVICE:
+ if (length > 0x12) {
+ length = 0x12;
+ }
+ usbdc_xfer(ep, usbdc.desces.ls_fs->sod, length, false);
+ return true;
+ case USB_DT_CONFIG:
+ 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;
+ }
+ usbdc_xfer(ep, cfg_desc, length, need_zlp);
+ return true;
+ case USB_DT_STRING:
+ str_desc = usb_find_str_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, index);
+ if (NULL == str_desc) {
+ return false;
+ }
+ total_len = str_desc[0];
+ if (length <= total_len) {
+ need_zlp = false;
+ } else {
+ length = total_len;
+ }
+ usbdc_xfer(ep, str_desc, length, need_zlp);
+ return true;
+
+ 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;
+
+ 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);
+ 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);
+ 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
+ */
+static void usbdc_set_config(void)
+{
+ struct usbd_descriptors desc;
+ struct usbdf_driver * func;
+ uint8_t * cfg_desc;
+ uint16_t total_len;
+ uint8_t last_iface = 0xFF;
+
+ if (usbdc.cfg_value == 0) {
+ usbdc_unconfig();
+ return;
+ }
+
+ cfg_desc = usb_find_cfg_desc(usbdc.desces.ls_fs->sod, usbdc.desces.ls_fs->eod, usbdc.cfg_value);
+
+ if (NULL == cfg_desc) {
+ return;
+ }
+
+ 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);
+ }
+}
+
+/**
+ * \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;
+
+ desc.sod = usbdc.desces.ls_fs->sod;
+ desc.eod = usbdc.desces.ls_fs->eod;
+ 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)) {
+ 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:
+ case USB_REQ_SET_CONFIG:
+ if (ERR_NONE == usbdc_xfer(ep, NULL, 0, true)) {
+ return true;
+ } else {
+ return false;
+ }
+ 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 bool 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 false;
+ }
+ }
+ 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)
+{
+ if (usbdc_request_handler(ep, req, USB_SETUP_STAGE)) {
+ return true;
+ }
+
+ // 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)
+{
+ switch (req->bRequest) {
+ case USB_REQ_SET_CONFIG:
+ usbdc.cfg_value = req->wValue;
+ usbdc_set_config();
+ 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;
+
+ // 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)
+{
+#ifdef 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;
+ } 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/atmel-samd/asf4/samd21/usb/device/usbdc.h b/atmel-samd/asf4/samd21/usb/device/usbdc.h
new file mode 100644
index 000000000..515d28f1b
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/device/usbdc.h
@@ -0,0 +1,246 @@
+/**
+ * \file
+ *
+ * \brief USB Device Stack Core Layer Definition.
+ *
+ * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _USB_USBDC_H_
+#define _USB_USBDC_H_
+
+#include "usb_includes.h"
+#include "usb_protocol.h"
+#include "hal_usb_device.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;
+#ifdef 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
+ * \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/atmel-samd/asf4/samd21/usb/usb_atmel.h b/atmel-samd/asf4/samd21/usb/usb_atmel.h
new file mode 100644
index 000000000..3ca7a2927
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/usb_atmel.h
@@ -0,0 +1,189 @@
+/**
+ * \file
+ *
+ * \brief All USB VIDs and PIDs from Atmel USB applications
+ *
+ * Copyright (c) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel 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/atmel-samd/asf4/samd21/usb/usb_debug.h b/atmel-samd/asf4/samd21/usb/usb_debug.h
new file mode 100644
index 000000000..4d8893208
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/usb_debug.h
@@ -0,0 +1,47 @@
+/**
+ * \file
+ *
+ * \brief USB Debug Files.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef _USB_DEBUG_H_
+#define _USB_DEBUG_H_
+
+#define udbg_print(...)
+
+#endif
diff --git a/atmel-samd/asf4/samd21/usb/usb_includes.h b/atmel-samd/asf4/samd21/usb/usb_includes.h
new file mode 100644
index 000000000..b3874d31e
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/usb_includes.h
@@ -0,0 +1,137 @@
+/**
+ * \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 - 2017 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#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/atmel-samd/asf4/samd21/usb/usb_protocol.c b/atmel-samd/asf4/samd21/usb/usb_protocol.c
new file mode 100644
index 000000000..534e4d1d9
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/usb_protocol.c
@@ -0,0 +1,146 @@
+/**
+ * \file
+ *
+ * \brief USB protocol implementation.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#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_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/atmel-samd/asf4/samd21/usb/usb_protocol.h b/atmel-samd/asf4/samd21/usb/usb_protocol.h
new file mode 100644
index 000000000..bb8d1ecd5
--- /dev/null
+++ b/atmel-samd/asf4/samd21/usb/usb_protocol.h
@@ -0,0 +1,765 @@
+/**
+ * \file
+ *
+ * \brief USB protocol definitions.
+ *
+ * This file contains the USB definitions and data structures provided by the
+ * USB 2.0 specification.
+ *
+ * Copyright (C) 2015 Atmel Corporation. All rights reserved.
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel AVR product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#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_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_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 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_ */