summaryrefslogtreecommitdiff
path: root/atmel-samd/asf4/samd21/usb
diff options
context:
space:
mode:
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_ */