SAMV71 Xplained Ultra Software Package 1.4

USBH.c

Go to the documentation of this file.
00001 /**
00002  * \file
00003  *
00004  * \brief USB Host Controller (UHC)
00005  *
00006  * Copyright (C) 2011-2015 Atmel Corporation. All rights reserved.
00007  *
00008  * \asf_license_start
00009  *
00010  * \page License
00011  *
00012  * Redistribution and use in source and binary forms, with or without
00013  * modification, are permitted provided that the following conditions are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright notice,
00016  *    this list of conditions and the following disclaimer.
00017  *
00018  * 2. Redistributions in binary form must reproduce the above copyright notice,
00019  *    this list of conditions and the following disclaimer in the documentation
00020  *    and/or other materials provided with the distribution.
00021  *
00022  * 3. The name of Atmel may not be used to endorse or promote products derived
00023  *    from this software without specific prior written permission.
00024  *
00025  * 4. This software may only be redistributed and used in connection with an
00026  *    Atmel microcontroller product.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00029  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00030  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00031  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
00032  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00033  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00034  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00035  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00036  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00037  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00038  * POSSIBILITY OF SUCH DAMAGE.
00039  *
00040  * \asf_license_stop
00041  *
00042  */
00043 /*
00044  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
00045  */
00046 
00047 #include "conf_usb_host.h"
00048 #include "USBHDriver.h"
00049 #include "uhi.h"
00050 #include "USBH.h"
00051 #include <stdlib.h>
00052 
00053 #ifndef USB_HOST_UHI
00054 #  error USB_HOST_UHI must be defined with unless one UHI interface in conf_usb_host.h file.
00055 #endif
00056 
00057 #ifdef USB_HOST_HUB_SUPPORT
00058 #  error The USB HUB support is not available in this revision.
00059 #endif
00060 
00061 // Optional UHC callbacks
00062 #ifndef UHC_CONNECTION_EVENT
00063 #  define UHC_CONNECTION_EVENT(dev,b_present)
00064 #endif
00065 #ifndef UHC_DEVICE_CONF
00066 #  define UHC_DEVICE_CONF(dev) 1
00067 #endif
00068 #ifndef UHC_ENUM_EVENT
00069 #  define UHC_ENUM_EVENT(dev,event)
00070 #endif
00071 #ifndef UHC_WAKEUP_EVENT
00072 #  define UHC_WAKEUP_EVENT()
00073 #endif
00074 
00075 /**
00076  * \ingroup USBH_group
00077  * \defgroup USBH_group_interne Implementation of UHC
00078  *
00079  * Internal implementation
00080  * @{
00081  */
00082 
00083 //! \name Internal variables to manage the USB host stack
00084 //! @{
00085 
00086 //! Entry point of all devices connected on USB tree
00087 static USBH_device_t USBH_device_root;
00088 
00089 //! Number of enumeration try
00090 static uint8_t USBH_enum_try;
00091 
00092 //! Maximum try to enumerate a device
00093 #define UHC_ENUM_NB_TRY 4
00094 
00095 //! Entry point of all devices connected on USB tree
00096 #define UHC_USB_ADD_NOT_VALID 0xFF
00097 
00098 #ifdef USB_HOST_HUB_SUPPORT
00099 //! USB address of the USB device under enumeration process
00100 #  define UHC_DEVICE_ENUM_ADD USBH_dev_enum->address
00101 
00102 //! Device under enumeration process
00103 static USBH_device_t *USBH_dev_enum;
00104 
00105 //! Total power of the connected devices
00106 static uint16_t USBH_power_running;
00107 
00108 #else
00109 //! USB address of the USB device under enumeration process
00110 #  define UHC_DEVICE_ENUM_ADD 1 // Static without USB HUB
00111 
00112 //! Device under enumeration process
00113 #  define USBH_dev_enum        (&USBH_device_root) // Static without USB HUB
00114 
00115 //! Total power of the devices connected
00116 #  define USBH_power_running   0 // No used without USB HUB
00117 #endif
00118 
00119 //! Type of callback on a SOF timeout
00120 typedef void (*USBH_sof_timeout_callback_t) (void);
00121 
00122 //! Callback currently registered on a SOF timeout
00123 static USBH_sof_timeout_callback_t USBH_sof_timeout_callback;
00124 
00125 //! Number of SOF remaining before call USBH_sof_timeout_callback callback
00126 uint8_t USBH_sof_timeout;
00127 
00128 //! Array of all UHI available
00129 static uhi_api_t USBH_uhis[] = {USB_HOST_UHI};
00130 
00131 //! Number of UHI available
00132 #define UHC_NB_UHI  (sizeof(USBH_uhis)/sizeof(USBH_uhis[0]))
00133 
00134 //! Volatile flag to pool the end of Get USB string setup request
00135 static volatile bool USBH_setup_request_finish;
00136 
00137 //! Volatile flag to know the status of Get USB string setup request
00138 static volatile bool USBH_setup_request_finish_status;
00139 
00140 //! @}
00141 
00142 
00143 //! \name Internal functions to manage the USB device enumeration
00144 //! @{
00145 static void USBH_enable_timeout_callback(
00146         uint8_t timeout,
00147         USBH_sof_timeout_callback_t callback);
00148 static void USBH_enumeration_suspend(void);
00149 static void USBH_enumeration_reset(uhd_callback_reset_t callback);
00150 static void USBH_connection_tree(bool b_plug, USBH_device_t* dev);
00151 static void USBH_enumeration_step1(void);
00152 static void USBH_enumeration_step2(void);
00153 static void USBH_enumeration_step3(void);
00154 static void USBH_enumeration_step4(void);
00155 static void USBH_enumeration_step5(void);
00156 static void USBH_enumeration_step6(
00157         USBHS_Add_t add,
00158         USBH_XfrStatus_t status,
00159         uint16_t payload_trans);
00160 static void USBH_enumeration_step7(void);
00161 static void USBH_enumeration_step8(void);
00162 static void USBH_enumeration_step9(void);
00163 static void USBH_enumeration_step10(
00164         USBHS_Add_t add,
00165         USBH_XfrStatus_t status,
00166         uint16_t payload_trans);
00167 static void USBH_enumeration_step11(void);
00168 static void USBH_enumeration_step12(
00169         USBHS_Add_t add,
00170         USBH_XfrStatus_t status,
00171         uint16_t payload_trans);
00172 static void USBH_enumeration_step13(
00173         USBHS_Add_t add,
00174         USBH_XfrStatus_t status,
00175         uint16_t payload_trans);
00176 static void USBH_enumeration_step14(
00177         USBHS_Add_t add,
00178         USBH_XfrStatus_t status,
00179         uint16_t payload_trans);
00180 static void USBH_enumeration_step15(
00181         USBHS_Add_t add,
00182         USBH_XfrStatus_t status,
00183         uint16_t payload_trans);
00184 #ifdef USB_HOST_LPM_SUPPORT
00185 static void USBH_enumeration_step16_lpm(void);
00186 static void USBH_enumeration_step17_lpm(
00187         USBHS_Add_t add,
00188         USBH_XfrStatus_t status,
00189         uint16_t payload_trans);
00190 #endif // USB_HOST_LPM_SUPPORT
00191 static void USBH_enumeration_error(USBH_enum_status_t status);
00192 //! @}
00193 
00194 static void USBH_remotewakeup(bool b_enable);
00195 static void USBH_setup_request_callback(
00196         USBHS_Add_t add,
00197         USBH_XfrStatus_t status,
00198         uint16_t payload_trans);
00199 
00200 
00201 
00202 /**
00203  * \brief Enable a internal timeout on SOF events
00204  *
00205  * \param timeout  value of timeout (ms)
00206  * \param callback Callback to call at the end of timeout
00207  */
00208 static void USBH_enable_timeout_callback(uint8_t timeout,
00209         USBH_sof_timeout_callback_t callback)
00210 {
00211     USBH_sof_timeout_callback = callback;
00212     USBH_sof_timeout = timeout;
00213 }
00214 
00215 /**
00216  * \brief Enters a specific device in USB suspend mode
00217  * Suspend the USB line or a port on USB hub.
00218  */
00219 static void USBH_enumeration_suspend(void)
00220 {
00221 #ifdef USB_HOST_HUB_SUPPORT
00222     if (&USBH_device_root != USBH_dev_enum) {
00223         // Device connected on USB hub
00224         uhi_hub_suspend(USBH_dev_enum);
00225     } else
00226 #endif
00227     {
00228         // Suspend USB line
00229         USBH_HAL_Suspend();
00230     }
00231 }
00232 
00233 /**
00234  * \brief Sends the USB Reset signal on the USB line of a device
00235  *
00236  * \param callback Callback to call at the end of Reset signal
00237  */
00238 static void USBH_enumeration_reset(uhd_callback_reset_t callback)
00239 {
00240     // Reset USB line
00241 #ifdef USB_HOST_HUB_SUPPORT
00242     if (&USBH_device_root != USBH_dev_enum) {
00243         // Device connected on USB hub
00244         uhi_hub_send_reset(USBH_dev_enum, callback);
00245     } else
00246 #endif
00247     {
00248         USBH_HAL_Reset(callback);
00249     }
00250 }
00251 
00252 /**
00253  * \brief Manage a device plug or unplug on the USB tree
00254  *
00255  * \param b_plug   true, if it is a device connection
00256  * \param dev      Information about device connected or disconnected
00257  */
00258 static void USBH_connection_tree(bool b_plug, USBH_device_t* dev)
00259 {
00260     uint8_t i;
00261     if (b_plug) {
00262         TRACE_INFO_WP("DevAdd ");
00263         USBH_enum_try = 1;
00264 #ifdef USB_HOST_HUB_SUPPORT
00265         USBH_dev_enum = dev;
00266 #endif
00267         USBH_dev_enum->conf_desc = NULL;
00268         USBH_dev_enum->address = 0;
00269         UHC_CONNECTION_EVENT(USBH_dev_enum, true);
00270         USBH_enumeration_step1();
00271     } else {
00272         TRACE_INFO_WP("DevRem");
00273         if (USBH_dev_enum == dev) {
00274             // Eventually stop enumeration timeout on-going on this device
00275             USBH_sof_timeout = 0;
00276         }
00277         // Abort all transfers (endpoint control and other) and free pipe(s)
00278         USBH_HAL_FreePipe(dev->address, 0xFF);
00279 
00280         // Disable all USB interfaces (this includes HUB interface)
00281         for (i = 0; i < UHC_NB_UHI; i++) {
00282             USBH_uhis[i].uninstall(dev);
00283         }
00284 
00285         UHC_CONNECTION_EVENT(dev, false);
00286         dev->address = UHC_USB_ADD_NOT_VALID;
00287         // Free USB configuration descriptor buffer
00288         if (dev->conf_desc != NULL) {
00289             free(dev->conf_desc);
00290         }
00291 #ifdef USB_HOST_HUB_SUPPORT
00292         USBH_power_running -= dev->power;
00293         if (&USBH_device_root != dev) {
00294             // It is on a USB hub
00295             dev->prev->next = dev->next;
00296             dev->next->prev = dev->prev;
00297             free(dev);
00298         }
00299 #endif
00300     }
00301 }
00302 
00303 /**
00304  * \brief Device enumeration step 1
00305  * Reset USB line.
00306  */
00307 static void USBH_enumeration_step1(void)
00308 {
00309     TRACE_INFO_WP("Enum1 ");
00310     USBH_enumeration_reset(USBH_enumeration_step2);
00311 }
00312 
00313 /**
00314  * \brief Device enumeration step 2
00315  * Lets USB line in IDLE state during 20ms.
00316  */
00317 static void USBH_enumeration_step2(void)
00318 {
00319     TRACE_INFO_WP("Enum2 ");
00320     USBH_enable_timeout_callback(20, USBH_enumeration_step3);
00321 }
00322 
00323 /**
00324  * \brief Device enumeration step 3
00325  * Reset USB line.
00326  */
00327 static void USBH_enumeration_step3(void)
00328 {
00329     TRACE_INFO_WP("Enum3 ");
00330     USBH_enumeration_reset(USBH_enumeration_step4);
00331 }
00332 
00333 /**
00334  * \brief Device enumeration step 4
00335  * Lets USB line in IDLE state during 100ms.
00336  */
00337 static void USBH_enumeration_step4(void)
00338 {
00339     TRACE_INFO_WP("Enum4 ");
00340     USBH_dev_enum->speed = USBH_HAL_GetSpeed();
00341     USBH_enable_timeout_callback(100, USBH_enumeration_step5);
00342 }
00343 
00344 /**
00345  * \brief Device enumeration step 5
00346  * Requests the USB device descriptor.
00347  * This setup request can be aborted
00348  * because the control endpoint size is unknown.
00349  */
00350 static void USBH_enumeration_step5(void)
00351 {
00352     USBGenericRequest req;
00353     TRACE_INFO_WP("Enum5 ");
00354     req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00355     req.bRequest = USB_REQ_GET_DESCRIPTOR;
00356     req.wValue = (USBGenericDescriptor_DEVICE << 8);
00357     req.wIndex = 0;
00358     req.wLength = offsetof(USBH_device_t, dev_desc.bMaxPacketSize0)
00359             + sizeof(USBH_dev_enum->dev_desc.bMaxPacketSize0);
00360 
00361     // After a USB reset, the reallocation is required
00362     USBH_HAL_FreePipe(0, 0);
00363     if (!USBH_HAL_ConfigureControlPipe(0, 64)) {
00364         USBH_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
00365         return;
00366     }
00367     if (!USBH_HAL_SetupReq(0,
00368             &req,
00369             (uint8_t*)&USBH_dev_enum->dev_desc,
00370             sizeof(USBDeviceDescriptor),
00371             NULL,
00372             USBH_enumeration_step6)) {
00373         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00374         return;
00375     }
00376 }
00377 
00378 /**
00379  * \brief Device enumeration step 6
00380  * End of Get device descriptor request.
00381  * Wait 20ms in IDLE state.
00382  *
00383  * \param add           USB address of the setup request
00384  * \param status        Transfer status
00385  * \param payload_trans Number of data transfered during DATA phase
00386  */
00387 static void USBH_enumeration_step6(
00388         USBHS_Add_t add,
00389         USBH_XfrStatus_t status,
00390         uint16_t payload_trans)
00391 {
00392     UNUSED(add);
00393     TRACE_INFO_WP("Enum6 ");
00394     if ((status != UHD_TRANS_NOERROR) || (payload_trans < 8)
00395             || (USBH_dev_enum->dev_desc.bDescriptorType != USBGenericDescriptor_DEVICE)) {
00396         USBH_enumeration_error((status == UHD_TRANS_DISCONNECT)?
00397                 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00398         return;
00399     }
00400     // Wait 20ms
00401     USBH_enable_timeout_callback(20, USBH_enumeration_step7);
00402 }
00403 
00404 /**
00405  * \brief Device enumeration step 7
00406  * Reset USB line.
00407  */
00408 static void USBH_enumeration_step7(void)
00409 {
00410     TRACE_INFO_WP("Enum7 ");
00411     USBH_enumeration_reset(USBH_enumeration_step8);
00412 }
00413 
00414 /**
00415  * \brief Device enumeration step 8
00416  * Lets USB line in IDLE state during 100ms.
00417  */
00418 static void USBH_enumeration_step8(void)
00419 {
00420     // Wait 100ms
00421     TRACE_INFO_WP("Enum8 ");
00422     USBH_enable_timeout_callback(100, USBH_enumeration_step9);
00423 }
00424 
00425 /**
00426  * \brief Device enumeration step 9
00427  * Send a Set address setup request.
00428  */
00429 static void USBH_enumeration_step9(void)
00430 {
00431     USBGenericRequest req;
00432 
00433     TRACE_INFO_WP("Enum9 ");
00434     req.bmRequestType = USB_REQ_RECIP_DEVICE
00435             | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
00436     req.bRequest = USB_REQ_SET_ADDRESS;
00437 #ifdef USB_HOST_HUB_SUPPORT
00438     uint8_t usb_addr_free = 0;
00439     USBH_device_t *dev;
00440 
00441     // Search free address
00442     dev = &USBH_device_root;
00443     while (usb_addr_free++) {
00444         if (dev->address == usb_addr_free) {
00445             continue;
00446         }
00447         if (dev->next != NULL) {
00448             dev = dev->next;
00449             continue;
00450         }
00451         break;
00452     }
00453     req.wValue = usb_addr_free;
00454     USBH_dev_enum->address = usb_addr_free;
00455 #else
00456     req.wValue = UHC_DEVICE_ENUM_ADD;
00457     USBH_dev_enum->address = UHC_DEVICE_ENUM_ADD;
00458 #endif
00459     req.wIndex = 0;
00460     req.wLength = 0;
00461 
00462     // After a USB reset, the reallocation is required
00463     USBH_HAL_FreePipe(0, 0);
00464     if (!USBH_HAL_ConfigureControlPipe(0, USBH_dev_enum->dev_desc.bMaxPacketSize0)) {
00465         USBH_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
00466         return;
00467     }
00468 
00469     if (!USBH_HAL_SetupReq(0,
00470             &req,
00471             (uint8_t*)&USBH_dev_enum->dev_desc,
00472             sizeof(USBDeviceDescriptor),
00473             NULL,
00474             USBH_enumeration_step10)) {
00475         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00476         return;
00477     }
00478 }
00479 
00480 /**
00481  * \brief Device enumeration step 10
00482  * End of Set address request.
00483  * Lets USB line in IDLE state during 20ms.
00484  *
00485  * \param add           USB address of the setup request
00486  * \param status        Transfer status
00487  * \param payload_trans Number of data transfered during DATA phase
00488  */
00489 static void USBH_enumeration_step10(
00490         USBHS_Add_t add,
00491         USBH_XfrStatus_t status,
00492         uint16_t payload_trans)
00493 {
00494     UNUSED(add);
00495     UNUSED(payload_trans);
00496     TRACE_INFO_WP("Enum10 ");
00497     if (status != UHD_TRANS_NOERROR) {
00498         USBH_enumeration_error((status == UHD_TRANS_DISCONNECT) ?
00499                 UHC_ENUM_DISCONNECT : UHC_ENUM_FAIL);
00500         return;
00501     }
00502     // Wait 20ms
00503     USBH_enable_timeout_callback(20, USBH_enumeration_step11);
00504 }
00505 
00506 /**
00507  * \brief Device enumeration step 11
00508  * Updates USB host pipe with the new USB address.
00509  * Requests a complete USB device descriptor.
00510  */
00511 static void USBH_enumeration_step11(void)
00512 {
00513     USBGenericRequest req;
00514 
00515     TRACE_INFO_WP("Enum11 ");
00516     // Free address 0 used to start enumeration
00517     USBH_HAL_FreePipe(0, 0);
00518 
00519     // Alloc control endpoint with the new USB address
00520     if (!USBH_HAL_ConfigureControlPipe(UHC_DEVICE_ENUM_ADD,
00521             USBH_dev_enum->dev_desc.bMaxPacketSize0)) {
00522         USBH_enumeration_error(UHC_ENUM_HARDWARE_LIMIT);
00523         return;
00524     }
00525     // Send USB device descriptor request
00526     req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00527     req.bRequest = USB_REQ_GET_DESCRIPTOR;
00528     req.wValue = (USBGenericDescriptor_DEVICE << 8);
00529     req.wIndex = 0;
00530     req.wLength = sizeof(USBDeviceDescriptor);
00531     if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00532             &req,
00533             (uint8_t *) & USBH_dev_enum->dev_desc,
00534             sizeof(USBDeviceDescriptor),
00535             NULL, USBH_enumeration_step12)) {
00536         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00537         return;
00538     }
00539 }
00540 
00541 /**
00542  * \brief Device enumeration step 12
00543  * Requests the first USB structure of the USB configuration descriptor.
00544  *
00545  * \param add           USB address of the setup request
00546  * \param status        Transfer status
00547  * \param payload_trans Number of data transfered during DATA phase
00548  */
00549 static void USBH_enumeration_step12(
00550         USBHS_Add_t add,
00551         USBH_XfrStatus_t status,
00552         uint16_t payload_trans)
00553 {
00554     USBGenericRequest req;
00555     uint8_t conf_num;
00556     UNUSED(add);
00557 
00558     TRACE_INFO_WP("Enum12 ");
00559     if ((status != UHD_TRANS_NOERROR) || (payload_trans != sizeof(USBDeviceDescriptor))
00560             || (USBH_dev_enum->dev_desc.bDescriptorType != USBGenericDescriptor_DEVICE)) {
00561         USBH_enumeration_error((status==UHD_TRANS_DISCONNECT)?
00562                 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00563         return;
00564     }
00565     // Choose USB device configuration
00566     if (USBH_dev_enum->dev_desc.bNumConfigurations > 1) {
00567         conf_num = UHC_DEVICE_CONF(USBH_dev_enum);
00568     } else {
00569         conf_num = 1;
00570     }
00571 
00572     USBH_dev_enum->conf_desc = malloc(sizeof(USBConfigurationDescriptor));
00573     if (USBH_dev_enum->conf_desc == NULL) {
00574         assert(false);
00575         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00576         return;
00577     }
00578     // Send USB device descriptor request
00579     req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00580     req.bRequest = USB_REQ_GET_DESCRIPTOR;
00581     req.wValue = (USBGenericDescriptor_CONFIGURATION << 8) | (conf_num - 1);
00582     req.wIndex = 0;
00583     req.wLength = sizeof(USBConfigurationDescriptor);
00584     if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00585             &req,
00586             (uint8_t *) USBH_dev_enum->conf_desc,
00587             sizeof(USBConfigurationDescriptor),
00588             NULL, USBH_enumeration_step13)) {
00589         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00590         return;
00591     }
00592 }
00593 
00594 /**
00595  * \brief Device enumeration step 13
00596  * Requests a complete Get configuration descriptor.
00597  *
00598  * \param add           USB address of the setup request
00599  * \param status        Transfer status
00600  * \param payload_trans Number of data transfered during DATA phase
00601  */
00602 static void USBH_enumeration_step13(
00603         USBHS_Add_t add,
00604         USBH_XfrStatus_t status,
00605         uint16_t payload_trans)
00606 {
00607     uint8_t conf_num;
00608     uint16_t conf_size;
00609     uint16_t bus_power = 0;
00610     USBGenericRequest req;
00611     UNUSED(add);
00612 
00613     TRACE_INFO_WP("Enum13 ");
00614     if ((status != UHD_TRANS_NOERROR) || (payload_trans != sizeof(USBConfigurationDescriptor))
00615             || (USBH_dev_enum->conf_desc->bDescriptorType != USBGenericDescriptor_CONFIGURATION)) {
00616         USBH_enumeration_error((status == UHD_TRANS_DISCONNECT)?
00617                 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00618         return;
00619     }
00620 #ifdef USB_HOST_HUB_SUPPORT
00621     USBH_device_t *dev;
00622     dev = USBH_dev_enum;
00623     while (1) {
00624         if (dev->conf_desc->bmAttributes & USB_CONFIG_ATTR_SELF_POWERED) {
00625             // The device or a parent HUB is SELF power, then no power on root
00626             break;
00627         }
00628         if (dev == (&USBH_device_root)) {
00629             bus_power = USBH_dev_enum->conf_desc->bMaxPower * 2;
00630             break; // End of USB tree
00631         }
00632         // Go to USB HUB parent
00633         dev = dev->hub;
00634     }
00635 #else
00636     if (!(USBH_dev_enum->conf_desc->bmAttributes
00637             &USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP)) {
00638         bus_power = USBH_dev_enum->conf_desc->bMaxPower * 2;
00639     }
00640 #endif
00641     if ((bus_power + USBH_power_running) > USB_HOST_POWER_MAX) {
00642         // USB interfaces consumption too high
00643         UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_OVERCURRENT);
00644 
00645         // Abort enumeration, set line in suspend mode
00646         USBH_enumeration_suspend();
00647         return;
00648     }
00649 #ifdef USB_HOST_HUB_SUPPORT
00650     USBH_dev_enum->power = bus_power;
00651     USBH_power_running += bus_power;
00652 #endif
00653 
00654     // Save information about USB configuration descriptor size
00655     conf_size = (USBH_dev_enum->conf_desc->wTotalLength);
00656     conf_num = USBH_dev_enum->conf_desc->bConfigurationValue;
00657     assert(conf_num);
00658     // Re alloc USB configuration descriptor
00659     free(USBH_dev_enum->conf_desc);
00660     USBH_dev_enum->conf_desc = malloc(conf_size);
00661     if (USBH_dev_enum->conf_desc == NULL) {
00662         assert(false);
00663         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00664         return;
00665     }
00666     // Send USB device descriptor request
00667     req.bmRequestType =
00668             USB_REQ_RECIP_DEVICE | USB_REQ_TYPE_STANDARD |
00669             USB_REQ_DIR_IN;
00670     req.bRequest = USB_REQ_GET_DESCRIPTOR;
00671     req.wValue = (USBGenericDescriptor_CONFIGURATION << 8) | (conf_num - 1);
00672     req.wIndex = 0;
00673     req.wLength = conf_size;
00674     if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00675             &req,
00676             (uint8_t *) USBH_dev_enum->conf_desc,
00677             conf_size,
00678             NULL, USBH_enumeration_step14)) {
00679         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00680         return;
00681     }
00682 }
00683 
00684 /**
00685  * \brief Device enumeration step 14
00686  * Enable USB configuration, if unless one USB interface is supported by UHIs.
00687  *
00688  * \param add           USB address of the setup request
00689  * \param status        Transfer status
00690  * \param payload_trans Number of data transfered during DATA phase
00691  */
00692 static void USBH_enumeration_step14(
00693         USBHS_Add_t add,
00694         USBH_XfrStatus_t status,
00695         uint16_t payload_trans)
00696 {
00697     USBGenericRequest req;
00698     uint8_t i;
00699     bool b_conf_supported = false;
00700     UNUSED(add);
00701 
00702     TRACE_INFO_WP("Enum14 ");
00703     if ((status != UHD_TRANS_NOERROR)
00704             || (payload_trans < sizeof(USBConfigurationDescriptor))
00705             || (USBH_dev_enum->conf_desc->bDescriptorType != USBGenericDescriptor_CONFIGURATION)
00706             || (payload_trans != (USBH_dev_enum->conf_desc->wTotalLength))) {
00707         USBH_enumeration_error((status==UHD_TRANS_DISCONNECT)?
00708                 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00709         return;
00710     }
00711     // Check if unless one USB interface is supported by UHIs
00712     for (i = 0; i < UHC_NB_UHI; i++) {
00713         switch (USBH_uhis[i].install(USBH_dev_enum)) {
00714         case UHC_ENUM_SUCCESS:
00715             TRACE_INFO("Device Driver installed");
00716             b_conf_supported = true;
00717             break;
00718 
00719         case UHC_ENUM_UNSUPPORTED:
00720             TRACE_INFO(" \n\rUnsupported Device");
00721             TRACE_INFO(" \n\rRestarting enumeration");
00722             break;
00723 
00724         default:
00725             // USB host hardware limitation
00726             // Free all endpoints
00727             USBH_HAL_FreePipe(UHC_DEVICE_ENUM_ADD,0xFF);
00728             UHC_ENUM_EVENT(USBH_dev_enum,UHC_ENUM_HARDWARE_LIMIT);
00729 
00730             // Abort enumeration, set line in suspend mode
00731             USBH_enumeration_suspend();
00732             return;
00733         }
00734     }
00735     if (!b_conf_supported) {
00736         // No USB interface supported
00737         UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_UNSUPPORTED);
00738 
00739         // Abort enumeration, set line in suspend mode
00740         USBH_enumeration_suspend();
00741         return;
00742     }
00743     // Enable device configuration
00744     req.bmRequestType = USB_REQ_RECIP_DEVICE
00745             | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_OUT;
00746     req.bRequest = USB_REQ_SET_CONFIGURATION;
00747     req.wValue = USBH_dev_enum->conf_desc->bConfigurationValue;
00748     req.wIndex = 0;
00749     req.wLength = 0;
00750     if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00751             &req,
00752             NULL,
00753             0,
00754             NULL, USBH_enumeration_step15)) {
00755         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00756         return;
00757     }
00758 }
00759 
00760 /**
00761  * \brief Device enumeration step 15
00762  * Enables UHI interfaces
00763  *
00764  * \param add           USB address of the setup request
00765  * \param status        Transfer status
00766  * \param payload_trans Number of data transfered during DATA phase
00767  */
00768 static void USBH_enumeration_step15(
00769         USBHS_Add_t add,
00770         USBH_XfrStatus_t status,
00771         uint16_t payload_trans)
00772 {
00773     UNUSED(add);
00774     uint8_t i;
00775     TRACE_INFO_WP("Enum15 ");
00776     if ((status!=UHD_TRANS_NOERROR) || (payload_trans!=0)) {
00777         for( i = 0; i < UHC_NB_UHI; i++) {
00778             USBH_uhis[i].uninstall(USBH_dev_enum);
00779         }
00780         USBH_enumeration_error((status == UHD_TRANS_DISCONNECT)?
00781                 UHC_ENUM_DISCONNECT : UHC_ENUM_FAIL);
00782         return;
00783     }
00784 
00785     // Enable all UHIs supported
00786     for (i = 0; i < UHC_NB_UHI; i++) {
00787         USBH_uhis[i].enable(USBH_dev_enum);
00788     }
00789 
00790 #ifdef USB_HOST_LPM_SUPPORT
00791     // Check LPM support
00792     if (USBH_device_root.dev_desc.bcdUSB >= (USBDeviceDescriptor_USB2_00)) {
00793         // Device can support LPM
00794         // Start LPM support check
00795         USBH_enumeration_step16_lpm();
00796         return;
00797     }
00798     USBH_dev_enum->lpm_desc = NULL;
00799 #endif
00800 
00801     USBH_enum_try = 0;
00802 
00803     UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_SUCCESS);
00804 }
00805 
00806 #ifdef USB_HOST_LPM_SUPPORT
00807 /**
00808  * \brief Device enumeration step 16 (LPM only)
00809  * Requests the USB structure of the USB BOS / LPM descriptor.
00810  */
00811 static void USBH_enumeration_step16_lpm(void)
00812 {
00813     USBGenericRequest req;
00814 
00815     TRACE_INFO_WP("Enum16_lpm");
00816     USBH_dev_enum->lpm_desc = malloc(sizeof(USB_DeviceLPMDescriptor));
00817     if (USBH_dev_enum->lpm_desc == NULL) {
00818         assert(false);
00819         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00820         return;
00821     }
00822     // Send USB device descriptor request
00823     req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
00824     req.bRequest = USB_REQ_GET_DESCRIPTOR;
00825     req.wValue = USB_DT_BOS << 8;
00826     req.wIndex = 0;
00827     req.wLength = sizeof(USB_DeviceLPMDescriptor);
00828     if (!USBH_HAL_SetupReq(UHC_DEVICE_ENUM_ADD,
00829             &req,
00830             (uint8_t *) USBH_dev_enum->lpm_desc,
00831             sizeof(USB_DeviceLPMDescriptor),
00832             NULL, USBH_enumeration_step17_lpm)) {
00833         USBH_enumeration_error(UHC_ENUM_MEMORY_LIMIT);
00834         return;
00835     }
00836 }
00837 
00838 /**
00839  * \brief Device enumeration step 17 (LPM only)
00840  * Check LPM support through the BOS descriptor received
00841  *
00842  * \param add           USB address of the setup request
00843  * \param status        Transfer status
00844  * \param payload_trans Number of data transfered during DATA phase
00845  */
00846 static void USBH_enumeration_step17_lpm(
00847         USBHS_Add_t add,
00848         USBH_XfrStatus_t status,
00849         uint16_t payload_trans)
00850 {
00851     UNUSED(add);
00852     
00853     TRACE_INFO_WP("Enum17_lpm ");
00854 
00855     if (status == UHD_TRANS_STALL) {
00856         free(USBH_dev_enum->lpm_desc);
00857         USBH_dev_enum->lpm_desc = NULL;
00858     } else if ((status != UHD_TRANS_NOERROR)
00859             || (payload_trans < sizeof(USB_DeviceLPMDescriptor))
00860             || (USBH_dev_enum->lpm_desc->bos.bDescriptorType != USB_DT_BOS)
00861             || (payload_trans != (USBH_dev_enum->lpm_desc->bos.wTotalLength))) {
00862         USBH_enumeration_error((status==UHD_TRANS_DISCONNECT)?
00863                 UHC_ENUM_DISCONNECT:UHC_ENUM_FAIL);
00864         return;
00865     } else if (status == UHD_TRANS_NOERROR) {
00866         // Check LPM support
00867         if ((USBH_dev_enum->lpm_desc->capa_ext.bDescriptorType != USBGenericDescriptor_DEVICE_CAPABILITY)
00868                 || (USBH_dev_enum->lpm_desc->capa_ext.bDevCapabilityType != USB_DC_USB20_EXTENSION)
00869                     || (!(USBH_dev_enum->lpm_desc->capa_ext.bmAttributes & (USB_DC_EXT_LPM)))) {
00870             free(USBH_dev_enum->lpm_desc);
00871             USBH_dev_enum->lpm_desc = NULL;
00872         }
00873     }
00874 
00875     USBH_enum_try = 0;
00876     UHC_ENUM_EVENT(USBH_dev_enum, UHC_ENUM_SUCCESS);
00877 }
00878 #endif // USB_HOST_LPM_SUPPORT
00879 
00880 /**
00881  * \brief Manage error during device enumeration
00882  *
00883  * \param status        Enumeration error occurred
00884  */
00885 static void USBH_enumeration_error(USBH_enum_status_t status)
00886 {
00887     if (status == UHC_ENUM_DISCONNECT) {
00888         USBH_enum_try = 0;
00889         TRACE_INFO_WP("Enum_Abort ");
00890         return; // Abort enumeration process
00891     }
00892     USBH_HAL_FreePipe(USBH_dev_enum->address, 0xFF);
00893 
00894     // Free USB configuration descriptor buffer
00895     if (USBH_dev_enum->conf_desc != NULL) {
00896         free(USBH_dev_enum->conf_desc);
00897         USBH_dev_enum->conf_desc = NULL;
00898     }
00899     USBH_dev_enum->address = 0;
00900     if (USBH_enum_try++ < UHC_ENUM_NB_TRY) {
00901         // Restart enumeration at beginning
00902         USBH_enumeration_step1();
00903         return;
00904     }
00905     // Abort enumeration, set line in suspend mode
00906     USBH_enumeration_suspend();
00907     UHC_ENUM_EVENT(USBH_dev_enum, status);
00908     USBH_enum_try = 0;
00909 }
00910 
00911 /**
00912  * \brief Enables or disables the remote wakeup feature
00913  * of all devices connected
00914  *
00915  * \param b_enable   true to enable remote wakeup feature, else disable.
00916  */
00917 static void USBH_remotewakeup(bool b_enable)
00918 {
00919     USBGenericRequest req;
00920     USBH_device_t *dev;
00921 
00922     dev = &USBH_device_root;
00923     while(1) {
00924         if (dev->conf_desc->bmAttributes & USBConfigurationDescriptor_REMOTE_WAKEUP) {
00925             if (b_enable) {
00926                 req.bRequest = USB_REQ_SET_FEATURE;
00927             } else {
00928                 req.bRequest = USB_REQ_CLEAR_FEATURE;
00929             }
00930             req.bmRequestType = USB_REQ_RECIP_DEVICE
00931                     |USB_REQ_TYPE_STANDARD|USB_REQ_DIR_OUT;
00932             req.wValue = USB_DEV_FEATURE_REMOTE_WAKEUP;
00933             req.wIndex = 0;
00934             req.wLength = 0;
00935             USBH_HAL_SetupReq(dev->address,&req,NULL,0,NULL,NULL);
00936         }
00937 #ifdef USB_HOST_HUB_SUPPORT
00938         if (dev->next == NULL) {
00939             break;
00940         }
00941         dev = dev->next;
00942 #else
00943         break;
00944 #endif
00945     }
00946 }
00947 
00948 /**
00949  * \brief Callback used to signal the end of a setup request
00950  *
00951  * \param add           USB address of the setup request
00952  * \param status        Transfer status
00953  * \param payload_trans Number of data transfered during DATA phase
00954  */
00955 static void USBH_setup_request_callback(
00956         USBHS_Add_t add,
00957         USBH_XfrStatus_t status,
00958         uint16_t payload_trans)
00959 {
00960     UNUSED(add);
00961     UNUSED(payload_trans);
00962     USBH_setup_request_finish_status = (status == UHD_TRANS_NOERROR);
00963     USBH_setup_request_finish = true;
00964 }
00965 
00966 
00967 /**
00968  * \name Callbacks used by USB Host Driver (UHD) to notify events
00969  * @{
00970  */
00971 void USBH_notify_connection(bool b_plug)
00972 {
00973     if (b_plug) {
00974         assert(USBH_device_root.address == UHC_USB_ADD_NOT_VALID);
00975 
00976 #ifdef USB_HOST_HUB_SUPPORT
00977         USBH_power_running = 0;
00978 #endif
00979     } else {
00980         if (USBH_device_root.address == UHC_USB_ADD_NOT_VALID) {
00981             // Already disconnected
00982             // Ignore the noise from host stop process
00983             return;
00984         }
00985     }
00986     // Device connection on root
00987     USBH_connection_tree(b_plug, &USBH_device_root);
00988 }
00989 
00990 void USBH_notify_sof(bool b_micro)
00991 {
00992     // Call all UHIs
00993     uint8_t i;
00994     for ( i = 0; i < UHC_NB_UHI; i++) {
00995         if (USBH_uhis[i].sof_notify != NULL) {
00996             USBH_uhis[i].sof_notify(b_micro);
00997         }
00998     }
00999 
01000     if (!b_micro) {
01001         // Manage SOF timeout
01002         if (USBH_sof_timeout) {
01003             if (--USBH_sof_timeout == 0) {
01004                 USBH_sof_timeout_callback();
01005             }
01006         }
01007     }
01008 }
01009 
01010 void USBH_notify_resume(void)
01011 {
01012     USBH_remotewakeup(false);
01013     UHC_WAKEUP_EVENT();
01014 }
01015 
01016 #ifdef USB_HOST_LPM_SUPPORT
01017 void USBH_notify_resume_lpm(void)
01018 {
01019     UHC_WAKEUP_EVENT();
01020 }
01021 #endif
01022 
01023 //! @}
01024 
01025 
01026 /**
01027  * \name Functions to control the USB host stack
01028  *
01029  * @{
01030  */
01031 void USBH_start(void)
01032 {
01033     USBH_device_root.address = UHC_USB_ADD_NOT_VALID;
01034     USBH_sof_timeout = 0; // No callback registered on a SOF timeout
01035     USBH_HAL_EnableUsbHost();
01036 }
01037 
01038 void USBH_stop(bool b_id_stop)
01039 {
01040     // Stop UHD
01041     USBH_HAL_DisableUsb(b_id_stop);
01042 }
01043 
01044 void USBH_suspend(bool b_remotewakeup)
01045 {
01046     if (USBH_enum_try) {
01047         // enumeration on-going, the USB suspend can't be done
01048         return;
01049     }
01050 
01051     if (b_remotewakeup) {
01052         USBH_remotewakeup(true);
01053     }
01054     // Suspend all USB devices
01055     USBH_HAL_Suspend();
01056 }
01057 
01058 bool USBH_is_suspend(void)
01059 {
01060     if (USBH_device_root.address == UHC_USB_ADD_NOT_VALID) {
01061         return true;
01062     }
01063     return USBH_HAL_IsSuspended();
01064 }
01065 
01066 void USBH_resume(void)
01067 {
01068     if (!USBH_is_suspend()) {
01069         return;
01070     }
01071     // Resume all USB devices
01072     USBH_HAL_Resume();
01073 }
01074 
01075 #ifdef USB_HOST_LPM_SUPPORT
01076 bool USBH_suspend_lpm(bool b_remotewakeup, uint8_t besl)
01077 {
01078     if (USBH_enum_try) {
01079         // enumeration on-going, the USB suspend can't be done
01080         return false;
01081     }
01082 
01083     // Check LPM support
01084     if (USBH_dev_enum->lpm_desc == NULL) {
01085         // Device cannot support LPM
01086         return false;
01087     }
01088 
01089     // Suspend all USB devices
01090     return uhd_suspend_lpm(b_remotewakeup, besl);
01091 }
01092 #endif // USB_HOST_LPM_SUPPORT
01093 
01094 //! @}
01095 
01096 
01097 /**
01098  * \name User functions to manage the devices
01099  *
01100  * @{
01101  */
01102 uint8_t USBH_get_device_number(void)
01103 {
01104 #ifdef USB_HOST_HUB_SUPPORT
01105     uint8_t nb_dev = 0;
01106     USBH_device_t *dev;
01107 
01108     if (USBH_device_root.address != UHC_USB_ADD_NOT_VALID) {
01109         dev = &USBH_device_root;
01110         while (nb_dev++) {
01111             if (dev->next == NULL) {
01112                 break;
01113             }
01114             dev = dev->next;
01115         }
01116     }
01117     return nb_dev;
01118 #else
01119     return (USBH_device_root.address != UHC_USB_ADD_NOT_VALID) ? 1 : 0;
01120 #endif
01121 }
01122 
01123 char *USBH_dev_get_string_manufacturer(USBH_device_t * dev)
01124 {
01125     if (!dev->dev_desc.iManufacturer) {
01126         return NULL; // No manufacturer string available
01127     }
01128     return USBH_dev_get_string(dev, dev->dev_desc.iManufacturer);
01129 }
01130 
01131 char *USBH_dev_get_string_product(USBH_device_t * dev)
01132 {
01133     if (!dev->dev_desc.iProduct) {
01134         return NULL; // No product string available
01135     }
01136     return USBH_dev_get_string(dev, dev->dev_desc.iProduct);
01137 }
01138 
01139 char *USBH_dev_get_string_serial(USBH_device_t * dev)
01140 {
01141     if (!dev->dev_desc.iSerialNumber) {
01142         return NULL; // No serial string available
01143     }
01144     return USBH_dev_get_string(dev, dev->dev_desc.iSerialNumber);
01145 }
01146 
01147 char *USBH_dev_get_string(USBH_device_t * dev, uint8_t str_id)
01148 {
01149     USBGenericRequest req;
01150     USBStringDescriptor str_header;
01151     USBStringLangIdDescriptor *str_desc;
01152     char *string;
01153     uint8_t i;
01154     UNUSED(dev);
01155 
01156     req.bmRequestType = USB_REQ_RECIP_DEVICE|USB_REQ_TYPE_STANDARD|USB_REQ_DIR_IN;
01157     req.bRequest = USB_REQ_GET_DESCRIPTOR;
01158     req.wValue = (USBGenericDescriptor_STRING << 8) | str_id;
01159     req.wIndex = 0;
01160     req.wLength = sizeof(USBStringDescriptor);
01161 
01162     // Get the size of string
01163     USBH_setup_request_finish = false;
01164     if (!USBH_HAL_SetupReq(0,
01165             &req,
01166             (uint8_t*)&str_header,
01167             sizeof(USBStringDescriptor),
01168             NULL,
01169             USBH_setup_request_callback)) {
01170         return NULL;
01171     }
01172     while (!USBH_setup_request_finish);
01173     if (!USBH_setup_request_finish_status) {
01174         return NULL;
01175     }
01176     // Get the size of string
01177     str_desc = malloc(str_header.bLength);
01178     if (str_desc == NULL) {
01179         return NULL;
01180     }
01181     req.wLength = str_header.bLength;
01182     USBH_setup_request_finish = false;
01183     if (!USBH_HAL_SetupReq(0,
01184             &req,
01185             (uint8_t*)str_desc,
01186             str_header.bLength,
01187             NULL,
01188             USBH_setup_request_callback)) {
01189         return NULL;
01190     }
01191     while (!USBH_setup_request_finish);
01192     if (!USBH_setup_request_finish_status) {
01193         free(str_desc);
01194         return NULL;
01195     }
01196     // The USB strings are "always" in ASCII format, then translate it.
01197     str_header.bLength = (str_header.bLength - 2) / 2; // Number of character
01198     string = malloc(str_header.bLength + 1); // +1 for NULL terminal
01199     if (string == NULL) {
01200         free(str_desc);
01201         return NULL;
01202     }
01203     for (i = 0; i < str_header.bLength; i++) {
01204         string[i] = (str_desc->string[i]) & 0xFF;
01205     }
01206     string[i] = 0;
01207     free(str_desc);
01208 
01209     return string;
01210 }
01211 
01212 uint16_t USBH_dev_get_power(USBH_device_t* dev)
01213 {
01214     return dev->conf_desc->bMaxPower * 2;
01215 }
01216 
01217 USBH_Speed_t USBH_dev_get_speed(USBH_device_t * dev)
01218 {
01219     return dev->speed;
01220 }
01221 
01222 bool USBH_dev_is_high_speed_support(USBH_device_t* dev)
01223 {
01224     USBGenericRequest req;
01225     USBDeviceQualifierDescriptor qualifier;
01226 
01227     if (dev->speed == UHD_SPEED_HIGH) {
01228         return true;
01229     }
01230     if (dev->speed == UHD_SPEED_FULL) {
01231         req.bmRequestType = USB_REQ_RECIP_DEVICE
01232                 | USB_REQ_TYPE_STANDARD | USB_REQ_DIR_IN;
01233         req.bRequest = USB_REQ_GET_DESCRIPTOR;
01234         req.wValue = (USBGenericDescriptor_DEVICEQUALIFIER << 8);
01235         req.wIndex = 0;
01236         req.wLength = sizeof(qualifier);
01237 
01238         // Get the size of string
01239         USBH_setup_request_finish = false;
01240         if (!USBH_HAL_SetupReq(0,
01241                 &req,
01242                 (uint8_t*)&qualifier,
01243                 sizeof(qualifier),
01244                 NULL,
01245                 USBH_setup_request_callback)) {
01246             return NULL;
01247         }
01248         while (!USBH_setup_request_finish);
01249         return USBH_setup_request_finish_status;
01250     }
01251     return false; // Low speed device
01252 }
01253 
01254 //! @}
01255 
01256 //! @}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines