SAMV71 Xplained Ultra Software Package 1.5

USBH.c

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