SAMV71 Xplained Ultra Software Package 1.5

USBDDriver.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  * \addtogroup usbd_interface
00032  *@{
00033  */
00034 
00035 /*------------------------------------------------------------------------------
00036  *      Headers
00037  *------------------------------------------------------------------------------*/
00038 
00039 #include <USBLib_Trace.h>
00040 
00041 #include "USBDDriver.h"
00042 #include "USBD.h"
00043 #include "USBD_HAL.h"
00044 
00045 #include <string.h>
00046 
00047 /*------------------------------------------------------------------------------
00048  *      Local variables
00049  *------------------------------------------------------------------------------*/
00050 
00051 /** Default device driver instance, for all class drivers in USB Lib. */
00052 static USBDDriver usbdDriver;
00053 
00054 /*------------------------------------------------------------------------------
00055  *      Local functions
00056  *------------------------------------------------------------------------------*/
00057 
00058 /**
00059  * Send a NULL packet
00060  */
00061 static void TerminateCtrlInWithNull(void *pArg,
00062                                     uint8_t status,
00063                                     uint32_t transferred,
00064                                     uint32_t remaining)
00065 {
00066     pArg = pArg; status = status;
00067     transferred = transferred; remaining = remaining;
00068     USBD_Write(0, /* Endpoint #0 */
00069                0, /* No data buffer */
00070                0, /* No data buffer */
00071                (TransferCallback) 0,
00072                (void *)  0);
00073 }
00074 
00075 /**
00076  * Configures the device by setting it into the Configured state and
00077  * initializing all endpoints.
00078  * \param pDriver  Pointer to a USBDDriver instance.
00079  * \param cfgnum  Configuration number to set.
00080  */
00081 static void SetConfiguration(USBDDriver *pDriver, uint8_t cfgnum)
00082 {
00083     USBEndpointDescriptor *pEndpoints[17];
00084     const USBConfigurationDescriptor *pConfiguration;
00085 
00086     /* Use different descriptor depending on device speed */
00087     if (USBD_HAL_IsHighSpeed()
00088            && pDriver->pDescriptors->pHsConfiguration)
00089 
00090         pConfiguration = pDriver->pDescriptors->pHsConfiguration;
00091     else
00092 
00093         pConfiguration = pDriver->pDescriptors->pFsConfiguration;
00094 
00095     /* Set & save the desired configuration */
00096     USBD_SetConfiguration(cfgnum);
00097 
00098     pDriver->cfgnum = cfgnum;
00099     pDriver->isRemoteWakeUpEnabled =
00100         ((pConfiguration->bmAttributes & 0x20) > 0);
00101 
00102     /* If the configuration is not 0, configure endpoints */
00103     if (cfgnum != 0) {
00104 
00105         /* Parse configuration to get endpoint descriptors */
00106         USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);
00107 
00108         /* Configure endpoints */
00109         int i = 0;
00110 
00111         while (pEndpoints[i] != 0) {
00112 
00113             USBD_ConfigureEndpoint(pEndpoints[i]);
00114             i++;
00115         }
00116     }
00117 
00118     /* Should be done before send the ZLP */
00119     if (NULL != (void *)USBDDriverCallbacks_ConfigurationChanged)
00120         USBDDriverCallbacks_ConfigurationChanged(cfgnum);
00121 
00122     /* Acknowledge the request */
00123     USBD_Write(0, /* Endpoint #0 */
00124                0, /* No data buffer */
00125                0, /* No data buffer */
00126                (TransferCallback) 0,
00127                (void *)  0);
00128 }
00129 
00130 /**
00131  * Sends the current configuration number to the host.
00132  * \param pDriver  Pointer to a USBDDriver instance.
00133  */
00134 static void GetConfiguration(const USBDDriver *pDriver)
00135 {
00136     unsigned long
00137     tmp;   // Coud be unsigned char : unsigned long has been chose to avoid any potential alignment issue with DMA
00138 
00139     if (USBD_GetState() <  USBD_STATE_CONFIGURED)
00140         tmp = 0;    // If device is unconfigured, returned configuration must be 0
00141     else
00142         tmp = pDriver->cfgnum;
00143 
00144     USBD_Write(0, &tmp, 1, 0, 0);
00145 }
00146 
00147 /**
00148  * Sends the current status of the device to the host.
00149  * \param pDriver  Pointer to a USBDDriver instance.
00150  */
00151 static void GetDeviceStatus(const USBDDriver *pDriver)
00152 {
00153     static unsigned short data;
00154     const USBConfigurationDescriptor *pConfiguration;
00155 
00156     data = 0;
00157     /* Use different configuration depending on device speed */
00158 
00159     if (USBD_IsHighSpeed())
00160 
00161         pConfiguration = pDriver->pDescriptors->pHsConfiguration;
00162     else
00163 
00164         pConfiguration = pDriver->pDescriptors->pFsConfiguration;
00165 
00166     /* Check current configuration for power mode (if device is configured) */
00167 
00168     if (pDriver->cfgnum != 0) {
00169 
00170         if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration))
00171 
00172             data |= 1;
00173     }
00174 
00175     /* Check if remote wake-up is enabled */
00176 
00177     if (pDriver->isRemoteWakeUpEnabled)
00178 
00179         data |= 2;
00180 
00181     /* Send the device status */
00182 
00183     USBD_Write(0, &data, 2, 0, 0);
00184 }
00185 
00186 /**
00187  * Sends the current status of an endpoints to the USB host.
00188  * \param bEndpoint  Endpoint number.
00189  */
00190 static void GetEndpointStatus(uint8_t bEndpoint)
00191 {
00192     static unsigned short data;
00193 
00194     data = 0;
00195 
00196     switch (USBD_HAL_Halt(bEndpoint, 0xFF)) {
00197 
00198     case USBD_STATUS_INVALID_PARAMETER: /* the endpoint not exists */
00199         USBD_Stall(0);
00200         break;
00201 
00202     case 1:
00203         data = 1;
00204 
00205     case 0:
00206         /* Send the endpoint status */
00207         USBD_Write(0, &data, 2, 0, 0);
00208         break;
00209     }
00210 }
00211 
00212 /**
00213  * Sends the requested USB descriptor to the host if available, or STALLs  the
00214  * request.
00215  * \param pDriver  Pointer to a USBDDriver instance.
00216  * \param type  Type of the requested descriptor
00217  * \param index  Index of the requested descriptor.
00218  * \param length  Maximum number of bytes to return.
00219  */
00220 static void GetDescriptor(
00221     const USBDDriver *pDriver,
00222     uint8_t type,
00223     uint8_t indexRDesc,
00224     uint32_t length)
00225 {
00226     const USBDeviceDescriptor *pDevice;
00227     const USBConfigurationDescriptor *pConfiguration;
00228     const USBDeviceQualifierDescriptor *pQualifier;
00229     const USBConfigurationDescriptor *pOtherSpeed;
00230     const USBGenericDescriptor **pStrings =
00231         (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
00232     const USBGenericDescriptor *pString;
00233     uint8_t numStrings = pDriver->pDescriptors->numStrings;
00234     uint8_t terminateWithNull = 0;
00235 
00236     /* Use different set of descriptors depending on device speed */
00237 
00238     /* By default, we uses full speed values */
00239     pDevice = pDriver->pDescriptors->pFsDevice;
00240     pConfiguration = pDriver->pDescriptors->pFsConfiguration;
00241 
00242     /* HS, we try HS values */
00243     if (USBD_HAL_IsHighSpeed()) {
00244 
00245         TRACE_DEBUG_WP("HS ");
00246 
00247         if (pDriver->pDescriptors->pHsDevice)
00248             pDevice = pDriver->pDescriptors->pHsDevice;
00249 
00250         if (pDriver->pDescriptors->pHsConfiguration)
00251             pConfiguration = pDriver->pDescriptors->pHsConfiguration;
00252 
00253         pQualifier = pDriver->pDescriptors->pHsQualifier;
00254         pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
00255     } else {
00256 
00257         TRACE_DEBUG_WP("FS ");
00258         pQualifier = pDriver->pDescriptors->pFsQualifier;
00259         pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
00260     }
00261 
00262     /* Check the descriptor type */
00263 
00264     switch (type) {
00265 
00266     case USBGenericDescriptor_DEVICE:
00267         TRACE_INFO_WP("Dev ");
00268 
00269         /* Adjust length and send descriptor */
00270 
00271         if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice))
00272 
00273             length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
00274 
00275         USBD_Write(0, pDevice, length, 0, 0);
00276         break;
00277 
00278     case USBGenericDescriptor_CONFIGURATION:
00279         TRACE_INFO_WP("Cfg ");
00280 
00281         /* Adjust length and send descriptor */
00282 
00283         if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {
00284 
00285             length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
00286             terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
00287         }
00288 
00289         USBD_Write(0,
00290                    pConfiguration,
00291                    length,
00292                    terminateWithNull ? TerminateCtrlInWithNull : 0,
00293                    0);
00294         break;
00295 
00296     case USBGenericDescriptor_DEVICEQUALIFIER:
00297         TRACE_INFO_WP("Qua ");
00298 
00299         /* Check if descriptor exists */
00300 
00301         if (!pQualifier)
00302 
00303             USBD_Stall(0);
00304         else {
00305 
00306             /* Adjust length and send descriptor */
00307 
00308             if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *)
00309                     pQualifier))
00310 
00311                 length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
00312 
00313             USBD_Write(0, pQualifier, length, 0, 0);
00314         }
00315 
00316         break;
00317 
00318     case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
00319         TRACE_INFO_WP("OSC ");
00320 
00321         /* Check if descriptor exists */
00322 
00323         if (!pOtherSpeed)
00324 
00325             USBD_Stall(0);
00326         else {
00327 
00328             /* Adjust length and send descriptor */
00329 
00330             if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {
00331 
00332                 length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
00333                 terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
00334             }
00335 
00336             USBD_Write(0,
00337                        pOtherSpeed,
00338                        length,
00339                        terminateWithNull ? TerminateCtrlInWithNull : 0,
00340                        0);
00341         }
00342 
00343         break;
00344 
00345     case USBGenericDescriptor_STRING:
00346         TRACE_INFO_WP("Str%d ", indexRDesc);
00347 
00348         /* Check if descriptor exists */
00349 
00350         if (indexRDesc >= numStrings)
00351 
00352             USBD_Stall(0);
00353         else {
00354 
00355             pString = pStrings[indexRDesc];
00356 
00357             /* Adjust length and send descriptor */
00358 
00359             if (length > USBGenericDescriptor_GetLength(pString)) {
00360 
00361                 length = USBGenericDescriptor_GetLength(pString);
00362                 terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
00363             }
00364 
00365             USBD_Write(0,
00366                        pString,
00367                        length,
00368                        terminateWithNull ? TerminateCtrlInWithNull : 0,
00369                        0);
00370         }
00371 
00372         break;
00373 
00374     default:
00375         TRACE_WARNING(
00376             "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
00377             type);
00378         USBD_Stall(0);
00379     }
00380 }
00381 
00382 /**
00383  * Sets the active setting of the given interface if the configuration supports
00384  * it; otherwise, the control pipe is STALLed. If the setting of an interface
00385  * changes.
00386  * \parma pDriver  Pointer to a USBDDriver instance.
00387  * \parma infnum  Interface number.
00388  * \parma setting  New active setting for the interface.
00389  */
00390 static void SetInterface(
00391     USBDDriver *pDriver,
00392     uint8_t infnum,
00393     uint8_t setting)
00394 {
00395     /* Make sure alternate settings are supported */
00396 
00397     TRACE_INFO_WP("Setting %d ", setting);
00398 
00399     if (!pDriver->pInterfaces)
00400 
00401         USBD_Stall(0);
00402     else {
00403 
00404         /* Change the current setting of the interface and trigger the callback */
00405         /* if necessary */
00406         if (pDriver->pInterfaces[infnum] != setting) {
00407 
00408             pDriver->pInterfaces[infnum] = setting;
00409 
00410             if (NULL != (void *)USBDDriverCallbacks_InterfaceSettingChanged)
00411                 USBDDriverCallbacks_InterfaceSettingChanged(infnum, setting);
00412         }
00413 
00414         /* Acknowledge the request */
00415 
00416         USBD_Write(0, 0, 0, 0, 0);
00417     }
00418 }
00419 
00420 /**
00421  * Sends the currently active setting of the given interface to the USB
00422  * host. If alternate settings are not supported, this function STALLs the
00423  * control pipe.
00424  * \param pDriver  Pointer to a USBDDriver instance.
00425  * \param infnum  Interface number.
00426  */
00427 static void GetInterface(
00428     const USBDDriver *pDriver,
00429     uint8_t infnum)
00430 {
00431     /* Make sure alternate settings are supported, or STALL the control pipe */
00432 
00433     if (!pDriver->pInterfaces)
00434 
00435         USBD_Stall(0);
00436     else {
00437 
00438         /* Sends the current interface setting to the host */
00439 
00440         USBD_Write(0, &(pDriver->pInterfaces[infnum]), 1, 0, 0);
00441     }
00442 }
00443 
00444 /**
00445  * Performs the selected test on the USB device (high-speed only).
00446  * \param test  Test selector value.
00447  */
00448 static void USBDDriver_Test(const USBDDriver *pDriver, uint8_t test)
00449 {
00450     pDriver = pDriver;
00451     TRACE_DEBUG("UDPHS_Test\n\r");
00452 
00453     /* the lower byte of wIndex must be zero
00454        the most significant byte of wIndex is used to specify the specific test mode */
00455 
00456     switch (test) {
00457     case USBFeatureRequest_TESTPACKET:
00458         /*Test mode Test_Packet: */
00459         /*Upon command, a port must repetitively transmit the following test packet until */
00460         /*the exit action is taken. This enables the testing of rise and fall times, eye */
00461         /*patterns, jitter, and any other dynamic waveform specifications. */
00462         /*The test packet is made up by concatenating the following strings. */
00463         /*(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one */
00464         /*transmitted. “S?indicates that a bit stuff occurs, which inserts an “extra?NRZI data bit. */
00465         /*? N?is used to indicate N occurrences of a string of bits or symbols.) */
00466         /*A port in Test_Packet mode must send this packet repetitively. The inter-packet timing */
00467         /*must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and */
00468         /*no greater than 125 us. */
00469 
00470         /* Send ZLP */
00471         USBD_Test(USBFeatureRequest_TESTSENDZLP);
00472         /* Tst PACKET */
00473         USBD_Test(USBFeatureRequest_TESTPACKET);
00474 
00475         while (1);
00476 
00477     /*break; not reached */
00478 
00479 
00480     case USBFeatureRequest_TESTJ:
00481         /*Test mode Test_J: */
00482         /*Upon command, a port’s transceiver must enter the high-speed J state and remain in that */
00483         /*state until the exit action is taken. This enables the testing of the high output drive */
00484         /*level on the D+ line. */
00485 
00486         /* Send ZLP */
00487         USBD_Test(USBFeatureRequest_TESTSENDZLP);
00488         /* Tst J */
00489         USBD_Test(USBFeatureRequest_TESTJ);
00490 
00491         while (1);
00492 
00493     /*break; not reached */
00494 
00495 
00496     case USBFeatureRequest_TESTK:
00497         /*Test mode Test_K: */
00498         /*Upon command, a port’s transceiver must enter the high-speed K state and remain in */
00499         /*that state until the exit action is taken. This enables the testing of the high output drive */
00500         /*level on the D- line. */
00501 
00502         /* Send a ZLP */
00503         USBD_Test(USBFeatureRequest_TESTSENDZLP);
00504         USBD_Test(USBFeatureRequest_TESTK);
00505 
00506         while (1);
00507 
00508     /*break; not reached */
00509 
00510 
00511     case USBFeatureRequest_TESTSE0NAK:
00512         /*Test mode Test_SE0_NAK: */
00513         /*Upon command, a port’s transceiver must enter the high-speed receive mode */
00514         /*and remain in that mode until the exit action is taken. This enables the testing */
00515         /*of output impedance, low level output voltage, and loading characteristics. */
00516         /*In addition, while in this mode, upstream facing ports (and only upstream facing ports) */
00517         /*must respond to any IN token packet with a NAK handshake (only if the packet CRC is */
00518         /*determined to be correct) within the normal allowed device response time. This enables testing of */
00519         /*the device squelch level circuitry and, additionally, provides a general purpose stimulus/response */
00520         /*test for basic functional testing. */
00521 
00522         /* Send a ZLP */
00523         USBD_Test(USBFeatureRequest_TESTSENDZLP);
00524         /* Test SE0_NAK */
00525         USBD_Test(USBFeatureRequest_TESTSE0NAK);
00526 
00527         while (1);
00528 
00529     /*break; not reached */
00530 
00531 
00532     default:
00533         USBD_Stall(0);
00534         break;
00535 
00536     }
00537 
00538     /* The exit action is to power cycle the device. */
00539     /* The device must be disconnected from the host */
00540 }
00541 
00542 /*------------------------------------------------------------------------------
00543  *      Exported functions
00544  *------------------------------------------------------------------------------*/
00545 
00546 /**
00547  * Return USBDDriver instance pointer for global usage.
00548  */
00549 USBDDriver *USBD_GetDriver(void)
00550 {
00551     return &usbdDriver;
00552 }
00553 
00554 /**
00555  * Initializes a USBDDriver instance with a list of descriptors. If
00556  * interfaces can have multiple alternate settings, an array to store the
00557  * current setting for each interface must be provided.
00558  * \param pDriver  Pointer to a USBDDriver instance.
00559  * \param pDescriptors  Pointer to a USBDDriverDescriptors instance.
00560  * \param pInterfaces  Pointer to an array for storing the current alternate
00561  *                     setting of each interface (optional).
00562  */
00563 void USBDDriver_Initialize(
00564     USBDDriver *pDriver,
00565     const USBDDriverDescriptors *pDescriptors,
00566     uint8_t *pInterfaces)
00567 {
00568 
00569     pDriver->cfgnum = 0;
00570     pDriver->isRemoteWakeUpEnabled = 0;
00571 
00572     pDriver->pDescriptors = pDescriptors;
00573     pDriver->pInterfaces = pInterfaces;
00574 
00575     /* Initialize interfaces array if not null */
00576 
00577     if (pInterfaces != 0)
00578 
00579         memset(pInterfaces, sizeof(pInterfaces), 0);
00580 }
00581 
00582 /**
00583  * Returns configuration descriptor list.
00584  * \param pDriver  Pointer to a USBDDriver instance.
00585  * \param cfgNum   Reserved.
00586  */
00587 USBConfigurationDescriptor *USBDDriver_GetCfgDescriptors(
00588     USBDDriver *pDriver, uint8_t cfgNum)
00589 {
00590     USBDDriverDescriptors *pDescList = (USBDDriverDescriptors *)
00591                                        pDriver->pDescriptors;
00592     USBConfigurationDescriptor *pCfg;
00593 
00594     cfgNum = cfgNum;
00595 
00596     if (USBD_HAL_IsHighSpeed() && pDescList->pHsConfiguration)
00597         pCfg = (USBConfigurationDescriptor *)pDescList->pHsConfiguration;
00598     else
00599         pCfg = (USBConfigurationDescriptor *)pDescList->pFsConfiguration;
00600 
00601     return pCfg;
00602 }
00603 
00604 /**
00605  * Handles the given request if it is standard, otherwise STALLs it.
00606  * \param pDriver  Pointer to a USBDDriver instance.
00607  * \param pRequest  Pointer to a USBGenericRequest instance.
00608  */
00609 void USBDDriver_RequestHandler(
00610     USBDDriver *pDriver,
00611     const USBGenericRequest *pRequest)
00612 {
00613     uint8_t cfgnum;
00614     uint8_t infnum;
00615     uint8_t eptnum;
00616     uint8_t setting;
00617     uint8_t type;
00618     uint8_t indexDesc;
00619     uint32_t length;
00620     uint32_t address;
00621 
00622     TRACE_INFO_WP("Std ");
00623 
00624     /* Check request code */
00625     switch (USBGenericRequest_GetRequest(pRequest)) {
00626 
00627     case USBGenericRequest_GETDESCRIPTOR:
00628         TRACE_INFO_WP("gDesc ");
00629 
00630         /* Send the requested descriptor */
00631         type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
00632         indexDesc = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
00633         length = USBGenericRequest_GetLength(pRequest);
00634         GetDescriptor(pDriver, type, indexDesc, length);
00635         break;
00636 
00637     case USBGenericRequest_SETADDRESS:
00638         TRACE_INFO_WP("sAddr ");
00639 
00640         /* Sends a zero-length packet and then set the device address */
00641         address = USBSetAddressRequest_GetAddress(pRequest);
00642         USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
00643         break;
00644 
00645     case USBGenericRequest_SETCONFIGURATION:
00646         TRACE_INFO_WP("sCfg ");
00647 
00648         /* Set the requested configuration */
00649         cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
00650         SetConfiguration(pDriver, cfgnum);
00651         break;
00652 
00653     case USBGenericRequest_GETCONFIGURATION:
00654         TRACE_INFO_WP("gCfg ");
00655 
00656         /* Send the current configuration number */
00657         GetConfiguration(pDriver);
00658         break;
00659 
00660     case USBGenericRequest_GETSTATUS:
00661         TRACE_INFO_WP("gSta ");
00662 
00663         /* Check who is the recipient */
00664         switch (USBGenericRequest_GetRecipient(pRequest)) {
00665 
00666         case USBGenericRequest_DEVICE:
00667             TRACE_INFO_WP("Dev ");
00668 
00669             /* Send the device status */
00670             GetDeviceStatus(pDriver);
00671             break;
00672 
00673         case USBGenericRequest_ENDPOINT:
00674             TRACE_INFO_WP("Ept ");
00675 
00676             /* Send the endpoint status */
00677             eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
00678             GetEndpointStatus(eptnum);
00679             break;
00680 
00681         default:
00682             TRACE_WARNING(
00683                 "USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
00684                 USBGenericRequest_GetRecipient(pRequest));
00685             USBD_Stall(0);
00686         }
00687 
00688         break;
00689 
00690     case USBGenericRequest_CLEARFEATURE:
00691         TRACE_INFO_WP("cFeat ");
00692 
00693         /* Check which is the requested feature */
00694         switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
00695 
00696         case USBFeatureRequest_ENDPOINTHALT:
00697             TRACE_INFO_WP("Hlt ");
00698             TRACE_INFO_WP(" ");
00699 
00700             /* Unhalt endpoint and send a zero-length packet */
00701             USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
00702             USBD_Write(0, 0, 0, 0, 0);
00703             break;
00704 
00705         case USBFeatureRequest_DEVICEREMOTEWAKEUP:
00706             TRACE_INFO_WP("RmWU ");
00707 
00708             /* Disable remote wake-up and send a zero-length packet */
00709             pDriver->isRemoteWakeUpEnabled = 0;
00710             USBD_Write(0, 0, 0, 0, 0);
00711             break;
00712 
00713         default:
00714             TRACE_WARNING(
00715                 "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
00716                 USBFeatureRequest_GetFeatureSelector(pRequest));
00717             USBD_Stall(0);
00718         }
00719 
00720         break;
00721 
00722     case USBGenericRequest_SETFEATURE:
00723         TRACE_INFO_WP("sFeat ");
00724 
00725         /* Check which is the selected feature */
00726         switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
00727 
00728         case USBFeatureRequest_DEVICEREMOTEWAKEUP:
00729             TRACE_INFO_WP("RmWU ");
00730 
00731             /* Enable remote wake-up and send a ZLP */
00732             pDriver->isRemoteWakeUpEnabled = 1;
00733             USBD_Write(0, 0, 0, 0, 0);
00734             break;
00735 
00736         case USBFeatureRequest_ENDPOINTHALT:
00737             TRACE_INFO_WP("Halt ");
00738             /* Halt endpoint */
00739             USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
00740             USBD_Write(0, 0, 0, 0, 0);
00741             break;
00742 
00743         case USBFeatureRequest_TESTMODE:
00744 
00745             /* 7.1.20 Test Mode Support, 9.4.9 Set Feature */
00746             if ((USBGenericRequest_GetRecipient(pRequest) == USBGenericRequest_DEVICE)
00747                 && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {
00748 
00749                 /* Handle test request */
00750                 USBDDriver_Test(pDriver,
00751                                 USBFeatureRequest_GetTestSelector(pRequest));
00752             } else
00753 
00754                 USBD_Stall(0);
00755 
00756             break;
00757 
00758 #if 0
00759 
00760         case USBFeatureRequest_OTG_B_HNP_ENABLE:
00761             TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
00762             pDriver->otg_features_supported |=
00763                 1 << USBFeatureRequest_OTG_B_HNP_ENABLE;
00764             USBD_Write(0, 0, 0, 0, 0);
00765             break;
00766 
00767         case USBFeatureRequest_OTG_A_HNP_SUPPORT:
00768             TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
00769             pDriver->otg_features_supported |=
00770                 1 << USBFeatureRequest_OTG_A_HNP_SUPPORT;
00771             USBD_Write(0, 0, 0, 0, 0);
00772             break;
00773 
00774         case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
00775             TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
00776             pDriver->otg_features_supported |=
00777                 1 << USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
00778             USBD_Write(0, 0, 0, 0, 0);
00779             break;
00780 #endif
00781 
00782         default:
00783             TRACE_WARNING(
00784                 "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
00785                 USBFeatureRequest_GetFeatureSelector(pRequest));
00786             USBD_Stall(0);
00787         }
00788 
00789         break;
00790 
00791     case USBGenericRequest_SETINTERFACE:
00792         TRACE_INFO_WP("sInterface ");
00793 
00794         infnum = USBInterfaceRequest_GetInterface(pRequest);
00795         setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
00796         SetInterface(pDriver, infnum, setting);
00797         break;
00798 
00799     case USBGenericRequest_GETINTERFACE:
00800         TRACE_INFO_WP("gInterface ");
00801 
00802         infnum = USBInterfaceRequest_GetInterface(pRequest);
00803         GetInterface(pDriver, infnum);
00804         break;
00805 
00806     default:
00807         TRACE_WARNING(
00808             "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
00809             USBGenericRequest_GetRequest(pRequest));
00810         USBD_Stall(0);
00811     }
00812 }
00813 
00814 
00815 /**
00816  * Test if RemoteWakeUP feature is enabled
00817  * \param pDriver  Pointer to an USBDDriver instance.
00818  * \return 1 if remote wake up has been enabled by the host; otherwise, returns
00819  * 0
00820  */
00821 uint8_t USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver)
00822 {
00823     return pDriver->isRemoteWakeUpEnabled;
00824 }
00825 
00826 /**
00827  * Return OTG features supported
00828  * \param pDriver  Pointer to an USBDDriver instance.
00829  * \return the OTG features
00830  */
00831 uint8_t USBDDriver_returnOTGFeatures(const USBDDriver *pDriver)
00832 {
00833     return pDriver->otg_features_supported;
00834 }
00835 
00836 /**
00837  * Clear OTG features supported
00838  * \param pDriver  Pointer to an USBDDriver instance.
00839  * \return none
00840  */
00841 void USBDDriver_clearOTGFeatures(USBDDriver *pDriver)
00842 {
00843     pDriver->otg_features_supported = 0;
00844 }
00845 
00846 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines