4 * \brief USB Device Controller (UDC)
6 * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
48 #include "usb_protocol.h"
51 #include "udi_device_conf.h"
54 #include "md_bootloader.h"
58 * \defgroup udc_group_interne Implementation of UDC
60 * Internal implementation
64 //! \name Internal variables to manage the USB device
67 //! Device status state (see enum usb_device_status in usb_protocol.h)
68 static le16_t udc_device_status;
71 //! Device interface setting value
72 static uint8_t udc_iface_setting = 0;
74 //! Device Configuration number selected by the USB host
76 static uint8_t udc_num_configuration = 0;
78 //! Pointer on the selected speed device configuration
79 static udc_config_speed_t UDC_DESC_STORAGE *udc_ptr_conf;
81 //! Pointer on interface descriptor used by SETUP request.
82 static usb_iface_desc_t UDC_DESC_STORAGE *udc_ptr_iface;
87 //! \name Internal structure to store the USB device main strings
91 * \brief Language ID of USB device (US ID by default)
94 static UDC_DESC_STORAGE usb_str_lgid_desc_t udc_string_desc_languageid = {
95 .desc.bLength = sizeof(usb_str_lgid_desc_t),
96 .desc.bDescriptorType = USB_DT_STRING,
97 .string = {LE16(USB_LANGID_EN_US)}
101 * \brief USB device manufacture name storage
102 * String is allocated only if USB_DEVICE_MANUFACTURE_NAME is declared
103 * by usb application configuration
105 #ifdef USB_DEVICE_MANUFACTURE_NAME
106 static uint8_t udc_string_manufacturer_name[] = USB_DEVICE_MANUFACTURE_NAME;
107 #define USB_DEVICE_MANUFACTURE_NAME_SIZE (sizeof(udc_string_manufacturer_name)-1)
109 #define USB_DEVICE_MANUFACTURE_NAME_SIZE 0
113 * \brief USB device product name storage
114 * String is allocated only if USB_DEVICE_PRODUCT_NAME is declared
115 * by usb application configuration
117 #ifdef USB_DEVICE_PRODUCT_NAME
118 static uint8_t udc_string_product_name[] = USB_DEVICE_PRODUCT_NAME;
119 #define USB_DEVICE_PRODUCT_NAME_SIZE (sizeof(udc_string_product_name)-1)
121 #define USB_DEVICE_PRODUCT_NAME_SIZE 0
124 #if defined USB_DEVICE_SERIAL_NAME
125 #define USB_DEVICE_SERIAL_NAME_SIZE (sizeof(USB_DEVICE_SERIAL_NAME)-1)
127 #define USB_DEVICE_SERIAL_NAME_SIZE 0
130 uint8_t usb_device_serial_name_size = 0;
131 #if defined USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
132 uint8_t bootloader_serial_number[BOOTLOADER_SERIAL_MAX_SIZE+1]="";
134 static const uint8_t *udc_get_string_serial_name(void)
136 #if defined USB_DEVICE_SERIAL_USE_BOOTLOADER_SERIAL
137 uint32_t serial_ptrloc = (uint32_t)&_srom - 4;
138 uint32_t serial_address = *(uint32_t *)serial_ptrloc; //Address of bootloader's serial number if available
140 if (serial_address != 0xFFFFFFFF && serial_address < serial_ptrloc) //Check for factory programmed serial address
142 if ((serial_address & 0xFF) % 4 == 0) //Check alignment
144 uint16_t *serial_use = (uint16_t *)(serial_address); //Point to address of string in rom
145 uint8_t serial_length = 0;
147 while ((*(serial_use + serial_length) > 32 && *(serial_use + serial_length) < 127) &&
148 serial_length < BOOTLOADER_SERIAL_MAX_SIZE)
150 bootloader_serial_number[serial_length] = *(serial_use + serial_length) & 0xFF;
153 bootloader_serial_number[serial_length] = 0;
155 usb_device_serial_name_size = serial_length;
157 return bootloader_serial_number; //Use serial programmed into bootloader rom
162 usb_device_serial_name_size = USB_DEVICE_SERIAL_NAME_SIZE;
164 #if defined USB_DEVICE_SERIAL_NAME
165 return (const uint8_t *)USB_DEVICE_SERIAL_NAME; //Use serial supplied by keyboard's config.h
167 return 0; //No serial supplied
172 * \brief USB device string descriptor
173 * Structure used to transfer ASCII strings to USB String descriptor structure.
175 #ifndef BOOTLOADER_SERIAL_MAX_SIZE
176 #define BOOTLOADER_SERIAL_MAX_SIZE 0
177 #endif //BOOTLOADER_SERIAL_MAX_SIZE
178 struct udc_string_desc_t {
179 usb_str_desc_t header;
180 le16_t string[Max(Max(Max(USB_DEVICE_MANUFACTURE_NAME_SIZE, \
181 USB_DEVICE_PRODUCT_NAME_SIZE), USB_DEVICE_SERIAL_NAME_SIZE), \
182 BOOTLOADER_SERIAL_MAX_SIZE)];
184 COMPILER_WORD_ALIGNED
185 static UDC_DESC_STORAGE struct udc_string_desc_t udc_string_desc = {
186 .header.bDescriptorType = USB_DT_STRING
190 usb_iface_desc_t UDC_DESC_STORAGE *udc_get_interface_desc(void)
192 return udc_ptr_iface;
196 * \brief Returns a value to check the end of USB Configuration descriptor
198 * \return address after the last byte of USB Configuration descriptor
200 static usb_conf_desc_t UDC_DESC_STORAGE *udc_get_eof_conf(void)
202 return (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *)
204 le16_to_cpu(udc_ptr_conf->desc->wTotalLength));
207 #if (0!=USB_DEVICE_MAX_EP)
209 * \brief Search specific descriptor in global interface descriptor
211 * \param desc Address of interface descriptor
212 * or previous specific descriptor found
213 * \param desc_id Descriptor ID to search
215 * \return address of specific descriptor found
216 * \return NULL if it is the end of global interface descriptor
218 static usb_conf_desc_t UDC_DESC_STORAGE *udc_next_desc_in_iface(usb_conf_desc_t
219 UDC_DESC_STORAGE * desc, uint8_t desc_id)
221 usb_conf_desc_t UDC_DESC_STORAGE *ptr_eof_desc;
223 ptr_eof_desc = udc_get_eof_conf();
224 // Go to next descriptor
225 desc = (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) desc +
227 // Check the end of configuration descriptor
228 while (ptr_eof_desc > desc) {
229 // If new interface descriptor is found,
230 // then it is the end of the current global interface descriptor
231 if (USB_DT_INTERFACE == desc->bDescriptorType) {
232 break; // End of global interface descriptor
234 if (desc_id == desc->bDescriptorType) {
235 return desc; // Specific descriptor found
237 // Go to next descriptor
238 desc = (UDC_DESC_STORAGE usb_conf_desc_t *) ((uint8_t *) desc +
241 return NULL; // No specific descriptor found
246 * \brief Search an interface descriptor
247 * This routine updates the internal pointer udc_ptr_iface.
249 * \param iface_num Interface number to find in Configuration Descriptor
250 * \param setting_num Setting number of interface to find
252 * \return 1 if found or 0 if not found
254 static bool udc_update_iface_desc(uint8_t iface_num, uint8_t setting_num)
256 usb_conf_desc_t UDC_DESC_STORAGE *ptr_end_desc;
258 if (0 == udc_num_configuration) {
262 if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) {
266 // Start at the beginning of configuration descriptor
267 udc_ptr_iface = (UDC_DESC_STORAGE usb_iface_desc_t *)
270 // Check the end of configuration descriptor
271 ptr_end_desc = udc_get_eof_conf();
272 while (ptr_end_desc >
273 (UDC_DESC_STORAGE usb_conf_desc_t *) udc_ptr_iface) {
274 if (USB_DT_INTERFACE == udc_ptr_iface->bDescriptorType) {
275 // A interface descriptor is found
276 // Check interface and alternate setting number
277 if ((iface_num == udc_ptr_iface->bInterfaceNumber) &&
279 udc_ptr_iface->bAlternateSetting)) {
280 return true; // Interface found
283 // Go to next descriptor
284 udc_ptr_iface = (UDC_DESC_STORAGE usb_iface_desc_t *) (
285 (uint8_t *) udc_ptr_iface +
286 udc_ptr_iface->bLength);
288 return false; // Interface not found
292 * \brief Disables an usb device interface (UDI)
293 * This routine call the UDI corresponding to interface number
295 * \param iface_num Interface number to disable
297 * \return 1 if it is done or 0 if interface is not found
299 static bool udc_iface_disable(uint8_t iface_num)
301 udi_api_t UDC_DESC_STORAGE *udi_api;
303 // Select first alternate setting of the interface
304 // to update udc_ptr_iface before call iface->getsetting()
305 if (!udc_update_iface_desc(iface_num, 0)) {
309 // Select the interface with the current alternate setting
310 udi_api = udc_ptr_conf->udi_apis[iface_num];
312 #if (0!=USB_DEVICE_MAX_EP)
313 if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) {
317 // Start at the beginning of interface descriptor
319 usb_ep_desc_t UDC_DESC_STORAGE *ep_desc;
320 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) udc_ptr_iface;
322 // Search Endpoint descriptor included in global interface descriptor
323 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *)
324 udc_next_desc_in_iface((UDC_DESC_STORAGE
326 ep_desc, USB_DT_ENDPOINT);
327 if (NULL == ep_desc) {
330 // Free the endpoint used by the interface
331 udd_ep_free(ep_desc->bEndpointAddress);
342 * \brief Enables an usb device interface (UDI)
343 * This routine calls the UDI corresponding
344 * to the interface and setting number.
346 * \param iface_num Interface number to enable
347 * \param setting_num Setting number to enable
349 * \return 1 if it is done or 0 if interface is not found
351 static bool udc_iface_enable(uint8_t iface_num, uint8_t setting_num)
353 // Select the interface descriptor
354 if (!udc_update_iface_desc(iface_num, setting_num)) {
358 #if (0!=USB_DEVICE_MAX_EP)
359 usb_ep_desc_t UDC_DESC_STORAGE *ep_desc;
361 // Start at the beginning of the global interface descriptor
362 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *) udc_ptr_iface;
364 // Search Endpoint descriptor included in the global interface descriptor
365 ep_desc = (UDC_DESC_STORAGE usb_ep_desc_t *)
366 udc_next_desc_in_iface((UDC_DESC_STORAGE
367 usb_conf_desc_t *) ep_desc,
371 // Alloc the endpoint used by the interface
372 if (!udd_ep_alloc(ep_desc->bEndpointAddress,
373 ep_desc->bmAttributes,
375 (ep_desc->wMaxPacketSize))) {
380 // Enable the interface
381 return udc_ptr_conf->udi_apis[iface_num]->enable();
384 /*! \brief Start the USB Device stack
391 /*! \brief Stop the USB Device stack
400 * \brief Reset the current configuration of the USB device,
401 * This routines can be called by UDD when a RESET on the USB line occurs.
407 if (udc_num_configuration) {
409 iface_num < udc_ptr_conf->desc->bNumInterfaces;
411 udc_iface_disable(iface_num);
414 udc_num_configuration = 0;
415 #if (USB_CONFIG_ATTR_REMOTE_WAKEUP \
416 == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP))
417 if (CPU_TO_LE16(USB_DEV_STATUS_REMOTEWAKEUP) & udc_device_status) {
418 // Remote wakeup is enabled then disable it
419 UDC_REMOTEWAKEUP_DISABLE();
423 #if (USB_DEVICE_ATTR & USB_CONFIG_ATTR_SELF_POWERED)
424 CPU_TO_LE16(USB_DEV_STATUS_SELF_POWERED);
426 CPU_TO_LE16(USB_DEV_STATUS_BUS_POWERED);
430 void udc_sof_notify(void)
434 if (udc_num_configuration) {
436 iface_num < udc_ptr_conf->desc->bNumInterfaces;
438 if (udc_ptr_conf->udi_apis[iface_num]->sof_notify != NULL) {
439 udc_ptr_conf->udi_apis[iface_num]->sof_notify();
446 * \brief Standard device request to get device status
448 * \return true if success
450 static bool udc_req_std_dev_get_status(void)
452 if (udd_g_ctrlreq.req.wLength != sizeof(udc_device_status)) {
456 udd_set_setup_payload( (uint8_t *) & udc_device_status,
457 sizeof(udc_device_status));
461 #if (0!=USB_DEVICE_MAX_EP)
463 * \brief Standard endpoint request to get endpoint status
465 * \return true if success
467 static bool udc_req_std_ep_get_status(void)
469 static le16_t udc_ep_status;
471 if (udd_g_ctrlreq.req.wLength != sizeof(udc_ep_status)) {
475 udc_ep_status = udd_ep_is_halted(udd_g_ctrlreq.req.
476 wIndex & 0xFF) ? CPU_TO_LE16(USB_EP_STATUS_HALTED) : 0;
478 udd_set_setup_payload( (uint8_t *) & udc_ep_status,
479 sizeof(udc_ep_status));
485 * \brief Standard device request to change device status
487 * \return true if success
489 static bool udc_req_std_dev_clear_feature(void)
491 if (udd_g_ctrlreq.req.wLength) {
495 if (udd_g_ctrlreq.req.wValue == USB_DEV_FEATURE_REMOTE_WAKEUP) {
496 udc_device_status &= CPU_TO_LE16(~(uint32_t)USB_DEV_STATUS_REMOTEWAKEUP);
497 #if (USB_CONFIG_ATTR_REMOTE_WAKEUP \
498 == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP))
499 UDC_REMOTEWAKEUP_DISABLE();
506 #if (0!=USB_DEVICE_MAX_EP)
508 * \brief Standard endpoint request to clear endpoint feature
510 * \return true if success
512 static bool udc_req_std_ep_clear_feature(void)
514 if (udd_g_ctrlreq.req.wLength) {
518 if (udd_g_ctrlreq.req.wValue == USB_EP_FEATURE_HALT) {
519 return udd_ep_clear_halt(udd_g_ctrlreq.req.wIndex & 0xFF);
526 * \brief Standard device request to set a feature
528 * \return true if success
530 static bool udc_req_std_dev_set_feature(void)
532 if (udd_g_ctrlreq.req.wLength) {
536 switch (udd_g_ctrlreq.req.wValue) {
538 case USB_DEV_FEATURE_REMOTE_WAKEUP:
539 #if (USB_CONFIG_ATTR_REMOTE_WAKEUP \
540 == (USB_DEVICE_ATTR & USB_CONFIG_ATTR_REMOTE_WAKEUP))
541 udc_device_status |= CPU_TO_LE16(USB_DEV_STATUS_REMOTEWAKEUP);
542 UDC_REMOTEWAKEUP_ENABLE();
548 #ifdef USB_DEVICE_HS_SUPPORT
549 case USB_DEV_FEATURE_TEST_MODE:
550 if (!udd_is_high_speed()) {
553 if (udd_g_ctrlreq.req.wIndex & 0xff) {
556 // Unconfigure the device, terminating all ongoing requests
558 switch ((udd_g_ctrlreq.req.wIndex >> 8) & 0xFF) {
559 case USB_DEV_TEST_MODE_J:
560 udd_g_ctrlreq.callback = udd_test_mode_j;
563 case USB_DEV_TEST_MODE_K:
564 udd_g_ctrlreq.callback = udd_test_mode_k;
567 case USB_DEV_TEST_MODE_SE0_NAK:
568 udd_g_ctrlreq.callback = udd_test_mode_se0_nak;
571 case USB_DEV_TEST_MODE_PACKET:
572 udd_g_ctrlreq.callback = udd_test_mode_packet;
575 case USB_DEV_TEST_MODE_FORCE_ENABLE: // Only for downstream facing hub ports
588 * \brief Standard endpoint request to halt an endpoint
590 * \return true if success
592 #if (0!=USB_DEVICE_MAX_EP)
593 static bool udc_req_std_ep_set_feature(void)
595 if (udd_g_ctrlreq.req.wLength) {
598 if (udd_g_ctrlreq.req.wValue == USB_EP_FEATURE_HALT) {
599 udd_ep_abort(udd_g_ctrlreq.req.wIndex & 0xFF);
600 return udd_ep_set_halt(udd_g_ctrlreq.req.wIndex & 0xFF);
607 * \brief Change the address of device
608 * Callback called at the end of request set address
610 static void udc_valid_address(void)
612 udd_set_address(udd_g_ctrlreq.req.wValue & 0x7F);
616 * \brief Standard device request to set device address
618 * \return true if success
620 static bool udc_req_std_dev_set_address(void)
622 if (udd_g_ctrlreq.req.wLength) {
626 // The address must be changed at the end of setup request after the handshake
627 // then we use a callback to change address
628 udd_g_ctrlreq.callback = udc_valid_address;
633 * \brief Standard device request to get device string descriptor
635 * \return true if success
637 static bool udc_req_std_dev_get_str_desc(void)
641 uint8_t str_length = 0;
643 // Link payload pointer to the string corresponding at request
644 switch (udd_g_ctrlreq.req.wValue & 0xff) {
646 udd_set_setup_payload((uint8_t *) &udc_string_desc_languageid,
647 sizeof(udc_string_desc_languageid));
650 #ifdef USB_DEVICE_MANUFACTURE_NAME
652 str_length = USB_DEVICE_MANUFACTURE_NAME_SIZE;
653 str = udc_string_manufacturer_name;
656 #ifdef USB_DEVICE_PRODUCT_NAME
658 str_length = USB_DEVICE_PRODUCT_NAME_SIZE;
659 str = udc_string_product_name;
663 str = udc_get_string_serial_name();
664 str_length = usb_device_serial_name_size;
667 #ifdef UDC_GET_EXTRA_STRING
668 if (UDC_GET_EXTRA_STRING()) {
676 for(i = 0; i < str_length; i++) {
677 udc_string_desc.string[i] = cpu_to_le16((le16_t)str[i]);
680 udc_string_desc.header.bLength = 2 + (str_length) * 2;
681 udd_set_setup_payload(
682 (uint8_t *) &udc_string_desc,
683 udc_string_desc.header.bLength);
690 * \brief Standard device request to get descriptors about USB device
692 * \return true if success
694 static bool udc_req_std_dev_get_descriptor(void)
698 conf_num = udd_g_ctrlreq.req.wValue & 0xff;
700 // Check descriptor ID
701 switch ((uint8_t) (udd_g_ctrlreq.req.wValue >> 8)) {
703 // Device descriptor requested
704 #ifdef USB_DEVICE_HS_SUPPORT
705 if (!udd_is_high_speed()) {
706 udd_set_setup_payload(
707 (uint8_t *) udc_config.confdev_hs,
708 udc_config.confdev_hs->bLength);
712 udd_set_setup_payload(
713 (uint8_t *) udc_config.confdev_lsfs,
714 udc_config.confdev_lsfs->bLength);
718 case USB_DT_CONFIGURATION:
719 // Configuration descriptor requested
720 #ifdef USB_DEVICE_HS_SUPPORT
721 if (udd_is_high_speed()) {
723 if (conf_num >= udc_config.confdev_hs->bNumConfigurations) {
726 udd_set_setup_payload(
727 (uint8_t *)udc_config.conf_hs[conf_num].desc,
728 le16_to_cpu(udc_config.conf_hs[conf_num].desc->wTotalLength));
733 if (conf_num >= udc_config.confdev_lsfs->bNumConfigurations) {
736 udd_set_setup_payload(
737 (uint8_t *)udc_config.conf_lsfs[conf_num].desc,
738 le16_to_cpu(udc_config.conf_lsfs[conf_num].desc->wTotalLength));
740 ((usb_conf_desc_t *) udd_g_ctrlreq.payload)->bDescriptorType =
741 USB_DT_CONFIGURATION;
744 #ifdef USB_DEVICE_HS_SUPPORT
745 case USB_DT_DEVICE_QUALIFIER:
746 // Device qualifier descriptor requested
747 udd_set_setup_payload( (uint8_t *) udc_config.qualifier,
748 udc_config.qualifier->bLength);
751 case USB_DT_OTHER_SPEED_CONFIGURATION:
752 // Other configuration descriptor requested
753 if (!udd_is_high_speed()) {
755 if (conf_num >= udc_config.confdev_hs->bNumConfigurations) {
758 udd_set_setup_payload(
759 (uint8_t *)udc_config.conf_hs[conf_num].desc,
760 le16_to_cpu(udc_config.conf_hs[conf_num].desc->wTotalLength));
763 if (conf_num >= udc_config.confdev_lsfs->bNumConfigurations) {
766 udd_set_setup_payload(
767 (uint8_t *)udc_config.conf_lsfs[conf_num].desc,
768 le16_to_cpu(udc_config.conf_lsfs[conf_num].desc->wTotalLength));
770 ((usb_conf_desc_t *) udd_g_ctrlreq.payload)->bDescriptorType =
771 USB_DT_OTHER_SPEED_CONFIGURATION;
776 // Device BOS descriptor requested
777 if (udc_config.conf_bos == NULL) {
780 udd_set_setup_payload( (uint8_t *) udc_config.conf_bos,
781 udc_config.conf_bos->wTotalLength);
785 // String descriptor requested
786 if (!udc_req_std_dev_get_str_desc()) {
792 // Unknown descriptor requested
795 // if the descriptor is larger than length requested, then reduce it
796 if (udd_g_ctrlreq.req.wLength < udd_g_ctrlreq.payload_size) {
797 udd_g_ctrlreq.payload_size = udd_g_ctrlreq.req.wLength;
803 * \brief Standard device request to get configuration number
805 * \return true if success
807 static bool udc_req_std_dev_get_configuration(void)
809 if (udd_g_ctrlreq.req.wLength != 1) {
813 udd_set_setup_payload(&udc_num_configuration,1);
818 * \brief Standard device request to enable a configuration
820 * \return true if success
822 static bool udc_req_std_dev_set_configuration(void)
826 // Check request length
827 if (udd_g_ctrlreq.req.wLength) {
830 // Authorize configuration only if the address is valid
831 if (!udd_getaddress()) {
834 // Check the configuration number requested
835 #ifdef USB_DEVICE_HS_SUPPORT
836 if (udd_is_high_speed()) {
838 if ((udd_g_ctrlreq.req.wValue & 0xFF) >
839 udc_config.confdev_hs->bNumConfigurations) {
846 if ((udd_g_ctrlreq.req.wValue & 0xFF) >
847 udc_config.confdev_lsfs->bNumConfigurations) {
852 // Reset current configuration
855 // Enable new configuration
856 udc_num_configuration = udd_g_ctrlreq.req.wValue & 0xFF;
857 if (udc_num_configuration == 0) {
858 return true; // Default empty configuration requested
860 // Update pointer of the configuration descriptor
861 #ifdef USB_DEVICE_HS_SUPPORT
862 if (udd_is_high_speed()) {
864 udc_ptr_conf = &udc_config.conf_hs[udc_num_configuration - 1];
869 udc_ptr_conf = &udc_config.conf_lsfs[udc_num_configuration - 1];
871 // Enable all interfaces of the selected configuration
872 for (iface_num = 0; iface_num < udc_ptr_conf->desc->bNumInterfaces;
874 if (!udc_iface_enable(iface_num, 0)) {
882 * \brief Standard interface request
883 * to get the alternate setting number of an interface
885 * \return true if success
887 static bool udc_req_std_iface_get_setting(void)
890 udi_api_t UDC_DESC_STORAGE *udi_api;
892 if (udd_g_ctrlreq.req.wLength != 1) {
893 return false; // Error in request
895 if (!udc_num_configuration) {
896 return false; // The device is not is configured state yet
899 // Check the interface number included in the request
900 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
901 if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) {
905 // Select first alternate setting of the interface to update udc_ptr_iface
906 // before call iface->getsetting()
907 if (!udc_update_iface_desc(iface_num, 0)) {
910 // Get alternate setting from UDI
911 udi_api = udc_ptr_conf->udi_apis[iface_num];
912 udc_iface_setting = udi_api->getsetting();
914 // Link value to payload pointer of request
915 udd_set_setup_payload(&udc_iface_setting,1);
920 * \brief Standard interface request
921 * to set an alternate setting of an interface
923 * \return true if success
925 static bool udc_req_std_iface_set_setting(void)
927 uint8_t iface_num, setting_num;
929 if (udd_g_ctrlreq.req.wLength) {
930 return false; // Error in request
932 if (!udc_num_configuration) {
933 return false; // The device is not is configured state yet
936 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
937 setting_num = udd_g_ctrlreq.req.wValue & 0xFF;
939 // Disable current setting
940 if (!udc_iface_disable(iface_num)) {
944 // Enable new setting
945 return udc_iface_enable(iface_num, setting_num);
949 * \brief Main routine to manage the standard USB SETUP request
951 * \return true if the request is supported
953 static bool udc_reqstd(void)
955 if (Udd_setup_is_in()) {
956 // GET Standard Requests
957 if (udd_g_ctrlreq.req.wLength == 0) {
958 return false; // Error for USB host
961 if (USB_REQ_RECIP_DEVICE == Udd_setup_recipient()) {
962 // Standard Get Device request
963 switch (udd_g_ctrlreq.req.bRequest) {
964 case USB_REQ_GET_STATUS:
965 return udc_req_std_dev_get_status();
966 case USB_REQ_GET_DESCRIPTOR:
967 return udc_req_std_dev_get_descriptor();
968 case USB_REQ_GET_CONFIGURATION:
969 return udc_req_std_dev_get_configuration();
975 if (USB_REQ_RECIP_INTERFACE == Udd_setup_recipient()) {
976 // Standard Get Interface request
977 switch (udd_g_ctrlreq.req.bRequest) {
978 case USB_REQ_GET_INTERFACE:
979 return udc_req_std_iface_get_setting();
984 #if (0!=USB_DEVICE_MAX_EP)
985 if (USB_REQ_RECIP_ENDPOINT == Udd_setup_recipient()) {
986 // Standard Get Endpoint request
987 switch (udd_g_ctrlreq.req.bRequest) {
988 case USB_REQ_GET_STATUS:
989 return udc_req_std_ep_get_status();
996 // SET Standard Requests
997 if (USB_REQ_RECIP_DEVICE == Udd_setup_recipient()) {
998 // Standard Set Device request
999 switch (udd_g_ctrlreq.req.bRequest) {
1000 case USB_REQ_SET_ADDRESS:
1001 return udc_req_std_dev_set_address();
1002 case USB_REQ_CLEAR_FEATURE:
1003 return udc_req_std_dev_clear_feature();
1004 case USB_REQ_SET_FEATURE:
1005 return udc_req_std_dev_set_feature();
1006 case USB_REQ_SET_CONFIGURATION:
1007 return udc_req_std_dev_set_configuration();
1008 case USB_REQ_SET_DESCRIPTOR:
1009 /* Not supported (defined as optional by the USB 2.0 spec) */
1016 if (USB_REQ_RECIP_INTERFACE == Udd_setup_recipient()) {
1017 // Standard Set Interface request
1018 switch (udd_g_ctrlreq.req.bRequest) {
1019 case USB_REQ_SET_INTERFACE:
1020 return udc_req_std_iface_set_setting();
1025 #if (0!=USB_DEVICE_MAX_EP)
1026 if (USB_REQ_RECIP_ENDPOINT == Udd_setup_recipient()) {
1027 // Standard Set Endpoint request
1028 switch (udd_g_ctrlreq.req.bRequest) {
1029 case USB_REQ_CLEAR_FEATURE:
1030 return udc_req_std_ep_clear_feature();
1031 case USB_REQ_SET_FEATURE:
1032 return udc_req_std_ep_set_feature();
1043 * \brief Send the SETUP interface request to UDI
1045 * \return true if the request is supported
1047 static bool udc_req_iface(void)
1050 udi_api_t UDC_DESC_STORAGE *udi_api;
1052 if (0 == udc_num_configuration) {
1053 return false; // The device is not is configured state yet
1055 // Check interface number
1056 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
1057 if (iface_num >= udc_ptr_conf->desc->bNumInterfaces) {
1061 //* To update udc_ptr_iface with the selected interface in request
1062 // Select first alternate setting of interface to update udc_ptr_iface
1063 // before calling udi_api->getsetting()
1064 if (!udc_update_iface_desc(iface_num, 0)) {
1067 // Select the interface with the current alternate setting
1068 udi_api = udc_ptr_conf->udi_apis[iface_num];
1069 if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) {
1073 // Send the SETUP request to the UDI corresponding to the interface number
1074 return udi_api->setup();
1078 * \brief Send the SETUP interface request to UDI
1080 * \return true if the request is supported
1082 static bool udc_req_ep(void)
1085 udi_api_t UDC_DESC_STORAGE *udi_api;
1087 if (0 == udc_num_configuration) {
1088 return false; // The device is not is configured state yet
1090 // Send this request on all enabled interfaces
1091 iface_num = udd_g_ctrlreq.req.wIndex & 0xFF;
1092 for (iface_num = 0; iface_num < udc_ptr_conf->desc->bNumInterfaces;
1094 // Select the interface with the current alternate setting
1095 udi_api = udc_ptr_conf->udi_apis[iface_num];
1096 if (!udc_update_iface_desc(iface_num, udi_api->getsetting())) {
1100 // Send the SETUP request to the UDI
1101 if (udi_api->setup()) {
1109 * \brief Main routine to manage the USB SETUP request.
1111 * This function parses a USB SETUP request and submits an appropriate
1112 * response back to the host or, in the case of SETUP OUT requests
1113 * with data, sets up a buffer for receiving the data payload.
1115 * The main standard requests defined by the USB 2.0 standard are handled
1116 * internally. The interface requests are sent to UDI, and the specific request
1117 * sent to a specific application callback.
1119 * \return true if the request is supported, else the request is stalled by UDD
1121 bool udc_process_setup(void)
1123 // By default no data (receive/send) and no callbacks registered
1124 udd_g_ctrlreq.payload_size = 0;
1125 udd_g_ctrlreq.callback = NULL;
1126 udd_g_ctrlreq.over_under_run = NULL;
1128 if (Udd_setup_is_in()) {
1129 if (udd_g_ctrlreq.req.wLength == 0) {
1130 return false; // Error from USB host
1134 // If standard request then try to decode it in UDC
1135 if (Udd_setup_type() == USB_REQ_TYPE_STANDARD) {
1141 // If interface request then try to decode it in UDI
1142 if (Udd_setup_recipient() == USB_REQ_RECIP_INTERFACE) {
1143 if (udc_req_iface()) {
1148 // If endpoint request then try to decode it in UDI
1149 if (Udd_setup_recipient() == USB_REQ_RECIP_ENDPOINT) {
1155 // Here SETUP request unknown by UDC and UDIs
1156 #ifdef USB_DEVICE_SPECIFIC_REQUEST
1157 // Try to decode it in specific callback
1158 return USB_DEVICE_SPECIFIC_REQUEST(); // Ex: Vendor request,...