SAMV71 Xplained Ultra Software Package 1.3

USBDDriver.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2008, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
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     }
00092     else {
00093 
00094         pConfiguration = pDriver->pDescriptors->pFsConfiguration;
00095     }
00096 
00097     /* Set & save the desired configuration */
00098     USBD_SetConfiguration(cfgnum);
00099 
00100     pDriver->cfgnum = cfgnum;
00101     pDriver->isRemoteWakeUpEnabled =
00102         ((pConfiguration->bmAttributes & 0x20) > 0);
00103 
00104     /* If the configuration is not 0, configure endpoints */
00105     if (cfgnum != 0) {
00106 
00107         /* Parse configuration to get endpoint descriptors */
00108         USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);
00109 
00110         /* Configure endpoints */
00111         int i = 0;
00112         while (pEndpoints[i] != 0) {
00113 
00114             USBD_ConfigureEndpoint(pEndpoints[i]);
00115             i++;
00116         }
00117     }
00118     /* Should be done before send the ZLP */
00119     if (NULL != 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 tmp;   // Coud be unsigned char : unsigned long has been chose to avoid any potential alignment issue with DMA 
00137   
00138     if( USBD_GetState() <  USBD_STATE_CONFIGURED) 
00139         tmp = 0;    // If device is unconfigured, returned configuration must be 0 
00140     else 
00141         tmp = pDriver->cfgnum; 
00142 
00143     USBD_Write(0, &tmp, 1, 0, 0); 
00144 }
00145 
00146 /**
00147  * Sends the current status of the device to the host.
00148  * \param pDriver  Pointer to a USBDDriver instance.
00149  */
00150 static void GetDeviceStatus(const USBDDriver *pDriver)
00151 {
00152     static unsigned short data;
00153     const USBConfigurationDescriptor *pConfiguration;
00154 
00155     data = 0;
00156     /* Use different configuration depending on device speed */
00157 
00158     if (USBD_IsHighSpeed()) {
00159 
00160         pConfiguration = pDriver->pDescriptors->pHsConfiguration;
00161     }
00162     else {
00163 
00164         pConfiguration = pDriver->pDescriptors->pFsConfiguration;
00165     }
00166 
00167     /* Check current configuration for power mode (if device is configured) */
00168 
00169     if (pDriver->cfgnum != 0) {
00170 
00171         if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) {
00172 
00173             data |= 1;
00174         }
00175     }
00176 
00177     /* Check if remote wake-up is enabled */
00178 
00179     if (pDriver->isRemoteWakeUpEnabled) {
00180 
00181         data |= 2;
00182     }
00183 
00184     /* Send the device status */
00185 
00186     USBD_Write(0, &data, 2, 0, 0);
00187 }
00188 
00189 /**
00190  * Sends the current status of an endpoints to the USB host.
00191  * \param bEndpoint  Endpoint number.
00192  */
00193 static void GetEndpointStatus(uint8_t bEndpoint)
00194 {
00195     static unsigned short data;
00196 
00197     data = 0;
00198 
00199     switch (USBD_HAL_Halt(bEndpoint, 0xFF)) {
00200 
00201         case USBD_STATUS_INVALID_PARAMETER: /* the endpoint not exists */
00202             USBD_Stall(0);
00203             break;
00204 
00205         case 1:
00206             data = 1;
00207         case 0:
00208             /* Send the endpoint status */
00209             USBD_Write(0, &data, 2, 0, 0);
00210             break;
00211     }
00212 }
00213 
00214 /**
00215  * Sends the requested USB descriptor to the host if available, or STALLs  the
00216  * request.
00217  * \param pDriver  Pointer to a USBDDriver instance.
00218  * \param type  Type of the requested descriptor
00219  * \param index  Index of the requested descriptor.
00220  * \param length  Maximum number of bytes to return.
00221  */
00222 static void GetDescriptor(
00223     const USBDDriver *pDriver,
00224     uint8_t type,
00225     uint8_t indexRDesc,
00226     uint32_t length)
00227 {
00228     const USBDeviceDescriptor *pDevice;
00229     const USBConfigurationDescriptor *pConfiguration;
00230     const USBDeviceQualifierDescriptor *pQualifier;
00231     const USBConfigurationDescriptor *pOtherSpeed;
00232     const USBGenericDescriptor **pStrings =
00233         (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
00234     const USBGenericDescriptor *pString;
00235     uint8_t numStrings = pDriver->pDescriptors->numStrings;
00236     uint8_t terminateWithNull = 0;
00237 
00238     /* Use different set of descriptors depending on device speed */
00239 
00240     /* By default, we uses full speed values */
00241     pDevice = pDriver->pDescriptors->pFsDevice;
00242     pConfiguration = pDriver->pDescriptors->pFsConfiguration;
00243 
00244     /* HS, we try HS values */
00245     if (USBD_HAL_IsHighSpeed()) {
00246 
00247         TRACE_DEBUG_WP("HS ");
00248         if (pDriver->pDescriptors->pHsDevice)
00249             pDevice = pDriver->pDescriptors->pHsDevice;
00250         if (pDriver->pDescriptors->pHsConfiguration)
00251             pConfiguration = pDriver->pDescriptors->pHsConfiguration;
00252         pQualifier = pDriver->pDescriptors->pHsQualifier;
00253         pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
00254     }
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             USBD_Write(0,
00289                        pConfiguration,
00290                        length,
00291                        terminateWithNull ? TerminateCtrlInWithNull : 0,
00292                        0);
00293             break;
00294 
00295         case USBGenericDescriptor_DEVICEQUALIFIER:
00296             TRACE_INFO_WP("Qua ");
00297 
00298             /* Check if descriptor exists */
00299 
00300             if (!pQualifier) {
00301 
00302                 USBD_Stall(0);
00303             }
00304             else {
00305 
00306                 /* Adjust length and send descriptor */
00307 
00308                 if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {
00309 
00310                     length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
00311                 }
00312                 USBD_Write(0, pQualifier, length, 0, 0);
00313             }
00314             break;
00315 
00316         case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
00317             TRACE_INFO_WP("OSC ");
00318 
00319             /* Check if descriptor exists */
00320 
00321             if (!pOtherSpeed) {
00322 
00323                 USBD_Stall(0);
00324             }
00325             else {
00326 
00327                 /* Adjust length and send descriptor */
00328 
00329                 if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {
00330 
00331                     length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
00332                     terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
00333                 }
00334                 USBD_Write(0,
00335                            pOtherSpeed,
00336                            length,
00337                            terminateWithNull ? TerminateCtrlInWithNull : 0,
00338                            0);
00339             }
00340             break;
00341 
00342         case USBGenericDescriptor_STRING:
00343             TRACE_INFO_WP("Str%d ", indexRDesc);
00344 
00345             /* Check if descriptor exists */
00346 
00347             if (indexRDesc >= numStrings) {
00348 
00349                 USBD_Stall(0);
00350             }
00351             else {
00352 
00353                 pString = pStrings[indexRDesc];
00354 
00355                 /* Adjust length and send descriptor */
00356 
00357                 if (length > USBGenericDescriptor_GetLength(pString)) {
00358 
00359                     length = USBGenericDescriptor_GetLength(pString);
00360                     terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
00361                 }
00362                 USBD_Write(0,
00363                            pString,
00364                            length,
00365                            terminateWithNull ? TerminateCtrlInWithNull : 0,
00366                            0);
00367             }
00368             break;
00369 
00370         default:
00371             TRACE_WARNING(
00372                       "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
00373                       type);
00374             USBD_Stall(0);
00375     }
00376 }
00377 
00378 /**
00379  * Sets the active setting of the given interface if the configuration supports
00380  * it; otherwise, the control pipe is STALLed. If the setting of an interface
00381  * changes.
00382  * \parma pDriver  Pointer to a USBDDriver instance.
00383  * \parma infnum  Interface number.
00384  * \parma setting  New active setting for the interface.
00385  */
00386 static void SetInterface(
00387     USBDDriver *pDriver,
00388     uint8_t infnum,
00389     uint8_t setting)
00390 {
00391     /* Make sure alternate settings are supported */
00392 
00393    TRACE_INFO_WP( "Setting %d ", setting);
00394     if (!pDriver->pInterfaces) {
00395 
00396         USBD_Stall(0);
00397     }
00398     else {
00399 
00400         /* Change the current setting of the interface and trigger the callback */
00401         /* if necessary */
00402         if (pDriver->pInterfaces[infnum] != setting) {
00403 
00404             pDriver->pInterfaces[infnum] = setting;
00405             if (NULL != USBDDriverCallbacks_InterfaceSettingChanged)
00406                 USBDDriverCallbacks_InterfaceSettingChanged(infnum, setting);
00407         }
00408 
00409         /* Acknowledge the request */
00410 
00411         USBD_Write(0, 0, 0, 0, 0);
00412     }
00413 }
00414 
00415 /**
00416  * Sends the currently active setting of the given interface to the USB
00417  * host. If alternate settings are not supported, this function STALLs the
00418  * control pipe.
00419  * \param pDriver  Pointer to a USBDDriver instance.
00420  * \param infnum  Interface number.
00421  */
00422 static void GetInterface(
00423     const USBDDriver *pDriver,
00424     uint8_t infnum)
00425 {
00426     /* Make sure alternate settings are supported, or STALL the control pipe */
00427 
00428     if (!pDriver->pInterfaces) {
00429 
00430         USBD_Stall(0);
00431     }
00432     else {
00433 
00434         /* Sends the current interface setting to the host */
00435 
00436         USBD_Write(0, &(pDriver->pInterfaces[infnum]), 1, 0, 0);
00437     }
00438 }
00439 
00440 /**
00441  * Performs the selected test on the USB device (high-speed only).
00442  * \param test  Test selector value.
00443  */
00444 static void USBDDriver_Test(const USBDDriver *pDriver, uint8_t test)
00445 {
00446     pDriver = pDriver;
00447     TRACE_DEBUG("UDPHS_Test\n\r");
00448 
00449     /* the lower byte of wIndex must be zero
00450        the most significant byte of wIndex is used to specify the specific test mode */
00451 
00452     switch (test) {
00453         case USBFeatureRequest_TESTPACKET:
00454             /*Test mode Test_Packet: */
00455             /*Upon command, a port must repetitively transmit the following test packet until */
00456             /*the exit action is taken. This enables the testing of rise and fall times, eye */
00457             /*patterns, jitter, and any other dynamic waveform specifications. */
00458             /*The test packet is made up by concatenating the following strings. */
00459             /*(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one */
00460             /*transmitted. “S?indicates that a bit stuff occurs, which inserts an “extra?NRZI data bit. */
00461             /*? N?is used to indicate N occurrences of a string of bits or symbols.) */
00462             /*A port in Test_Packet mode must send this packet repetitively. The inter-packet timing */
00463             /*must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and */
00464             /*no greater than 125 us. */
00465 
00466             /* Send ZLP */
00467             USBD_Test(USBFeatureRequest_TESTSENDZLP);
00468             /* Tst PACKET */
00469             USBD_Test(USBFeatureRequest_TESTPACKET);
00470             while (1);
00471             /*break; not reached */
00472 
00473 
00474         case USBFeatureRequest_TESTJ:
00475             /*Test mode Test_J: */
00476             /*Upon command, a port’s transceiver must enter the high-speed J state and remain in that */
00477             /*state until the exit action is taken. This enables the testing of the high output drive */
00478             /*level on the D+ line. */
00479 
00480             /* Send ZLP */
00481             USBD_Test(USBFeatureRequest_TESTSENDZLP);
00482             /* Tst J */
00483             USBD_Test(USBFeatureRequest_TESTJ);
00484             while (1);
00485             /*break; not reached */
00486 
00487 
00488         case USBFeatureRequest_TESTK:
00489             /*Test mode Test_K: */
00490             /*Upon command, a port’s transceiver must enter the high-speed K state and remain in */
00491             /*that state until the exit action is taken. This enables the testing of the high output drive */
00492             /*level on the D- line. */
00493 
00494             /* Send a ZLP */
00495             USBD_Test(USBFeatureRequest_TESTSENDZLP);
00496             USBD_Test(USBFeatureRequest_TESTK);
00497             while (1);
00498             /*break; not reached */
00499 
00500 
00501         case USBFeatureRequest_TESTSE0NAK:
00502             /*Test mode Test_SE0_NAK: */
00503             /*Upon command, a port’s transceiver must enter the high-speed receive mode */
00504             /*and remain in that mode until the exit action is taken. This enables the testing */
00505             /*of output impedance, low level output voltage, and loading characteristics. */
00506             /*In addition, while in this mode, upstream facing ports (and only upstream facing ports) */
00507             /*must respond to any IN token packet with a NAK handshake (only if the packet CRC is */
00508             /*determined to be correct) within the normal allowed device response time. This enables testing of */
00509             /*the device squelch level circuitry and, additionally, provides a general purpose stimulus/response */
00510             /*test for basic functional testing. */
00511 
00512             /* Send a ZLP */
00513             USBD_Test(USBFeatureRequest_TESTSENDZLP);
00514             /* Test SE0_NAK */
00515             USBD_Test(USBFeatureRequest_TESTSE0NAK);
00516             while (1);
00517             /*break; not reached */
00518 
00519 
00520         default:
00521             USBD_Stall(0);
00522             break;
00523 
00524     }
00525     /* The exit action is to power cycle the device. */
00526     /* The device must be disconnected from the host */
00527 }
00528 
00529 /*------------------------------------------------------------------------------
00530  *      Exported functions
00531  *------------------------------------------------------------------------------*/
00532 
00533 /**
00534  * Return USBDDriver instance pointer for global usage.
00535  */
00536 USBDDriver *USBD_GetDriver(void)
00537 {
00538     return &usbdDriver;
00539 }
00540 
00541 /**
00542  * Initializes a USBDDriver instance with a list of descriptors. If
00543  * interfaces can have multiple alternate settings, an array to store the
00544  * current setting for each interface must be provided.
00545  * \param pDriver  Pointer to a USBDDriver instance.
00546  * \param pDescriptors  Pointer to a USBDDriverDescriptors instance.
00547  * \param pInterfaces  Pointer to an array for storing the current alternate
00548  *                     setting of each interface (optional).
00549  */
00550 void USBDDriver_Initialize(
00551     USBDDriver *pDriver,
00552     const USBDDriverDescriptors *pDescriptors,
00553     uint8_t *pInterfaces)
00554 {
00555 
00556     pDriver->cfgnum = 0;
00557     pDriver->isRemoteWakeUpEnabled = 0;
00558 
00559     pDriver->pDescriptors = pDescriptors;
00560     pDriver->pInterfaces = pInterfaces;
00561 
00562     /* Initialize interfaces array if not null */
00563 
00564     if (pInterfaces != 0) {
00565 
00566         memset(pInterfaces, sizeof(pInterfaces), 0);
00567     }
00568 }
00569 
00570 /**
00571  * Returns configuration descriptor list.
00572  * \param pDriver  Pointer to a USBDDriver instance.
00573  * \param cfgNum   Reserved.
00574  */
00575 USBConfigurationDescriptor *USBDDriver_GetCfgDescriptors(
00576     USBDDriver *pDriver, uint8_t cfgNum)
00577 {
00578     USBDDriverDescriptors *pDescList = (USBDDriverDescriptors *)pDriver->pDescriptors;
00579     USBConfigurationDescriptor *pCfg;
00580 
00581     cfgNum = cfgNum;
00582     if (USBD_HAL_IsHighSpeed() && pDescList->pHsConfiguration)
00583         pCfg = (USBConfigurationDescriptor *)pDescList->pHsConfiguration;
00584     else
00585         pCfg = (USBConfigurationDescriptor *)pDescList->pFsConfiguration;
00586 
00587     return pCfg;
00588 }
00589 
00590 /**
00591  * Handles the given request if it is standard, otherwise STALLs it.
00592  * \param pDriver  Pointer to a USBDDriver instance.
00593  * \param pRequest  Pointer to a USBGenericRequest instance.
00594  */
00595 void USBDDriver_RequestHandler(
00596     USBDDriver *pDriver,
00597     const USBGenericRequest *pRequest)
00598 {
00599     uint8_t cfgnum;
00600     uint8_t infnum;
00601     uint8_t eptnum;
00602     uint8_t setting;
00603     uint8_t type;
00604     uint8_t indexDesc;
00605     uint32_t length;
00606     uint32_t address;
00607 
00608     TRACE_INFO_WP("Std ");
00609 
00610     /* Check request code */
00611     switch (USBGenericRequest_GetRequest(pRequest)) {
00612 
00613         case USBGenericRequest_GETDESCRIPTOR:
00614             TRACE_INFO_WP("gDesc ");
00615 
00616             /* Send the requested descriptor */
00617             type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
00618             indexDesc = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
00619             length = USBGenericRequest_GetLength(pRequest);
00620             GetDescriptor(pDriver, type, indexDesc, length);
00621             break;
00622 
00623         case USBGenericRequest_SETADDRESS:
00624             TRACE_INFO_WP("sAddr ");
00625 
00626             /* Sends a zero-length packet and then set the device address */
00627             address = USBSetAddressRequest_GetAddress(pRequest);
00628             USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
00629             break;
00630 
00631         case USBGenericRequest_SETCONFIGURATION:
00632             TRACE_INFO_WP("sCfg ");
00633 
00634             /* Set the requested configuration */
00635             cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
00636             SetConfiguration(pDriver, cfgnum);
00637             break;
00638 
00639         case USBGenericRequest_GETCONFIGURATION:
00640             TRACE_INFO_WP("gCfg ");
00641 
00642             /* Send the current configuration number */
00643             GetConfiguration(pDriver);
00644             break;
00645 
00646         case USBGenericRequest_GETSTATUS:
00647             TRACE_INFO_WP("gSta ");
00648 
00649             /* Check who is the recipient */
00650             switch (USBGenericRequest_GetRecipient(pRequest)) {
00651 
00652                 case USBGenericRequest_DEVICE:
00653                     TRACE_INFO_WP("Dev ");
00654 
00655                     /* Send the device status */
00656                     GetDeviceStatus(pDriver);
00657                     break;
00658 
00659                 case USBGenericRequest_ENDPOINT:
00660                     TRACE_INFO_WP("Ept ");
00661 
00662                     /* Send the endpoint status */
00663                     eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
00664                     GetEndpointStatus(eptnum);
00665                     break;
00666 
00667                 default:
00668                     TRACE_WARNING(
00669                               "USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
00670                               USBGenericRequest_GetRecipient(pRequest));
00671                     USBD_Stall(0);
00672             }
00673             break;
00674 
00675         case USBGenericRequest_CLEARFEATURE:
00676             TRACE_INFO_WP("cFeat ");
00677 
00678             /* Check which is the requested feature */
00679             switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
00680 
00681                 case USBFeatureRequest_ENDPOINTHALT:
00682                     TRACE_INFO_WP("Hlt ");
00683                     TRACE_INFO_WP(" ");
00684 
00685                     /* Unhalt endpoint and send a zero-length packet */
00686                     USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
00687                     USBD_Write(0, 0, 0, 0, 0);
00688                     break;
00689 
00690                 case USBFeatureRequest_DEVICEREMOTEWAKEUP:
00691                     TRACE_INFO_WP("RmWU ");
00692 
00693                     /* Disable remote wake-up and send a zero-length packet */
00694                     pDriver->isRemoteWakeUpEnabled = 0;
00695                     USBD_Write(0, 0, 0, 0, 0);
00696                     break;
00697 
00698                 default:
00699                     TRACE_WARNING(
00700                               "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
00701                               USBFeatureRequest_GetFeatureSelector(pRequest));
00702                     USBD_Stall(0);
00703             }
00704             break;
00705 
00706     case USBGenericRequest_SETFEATURE:
00707         TRACE_INFO_WP("sFeat ");
00708 
00709         /* Check which is the selected feature */
00710         switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
00711 
00712             case USBFeatureRequest_DEVICEREMOTEWAKEUP:
00713                 TRACE_INFO_WP("RmWU ");
00714 
00715                 /* Enable remote wake-up and send a ZLP */
00716                 pDriver->isRemoteWakeUpEnabled = 1;
00717                 USBD_Write(0, 0, 0, 0, 0);
00718                 break;
00719 
00720             case USBFeatureRequest_ENDPOINTHALT:
00721                 TRACE_INFO_WP("Halt ");
00722                 /* Halt endpoint */
00723                 USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
00724                 USBD_Write(0, 0, 0, 0, 0);
00725                 break;
00726 
00727             case USBFeatureRequest_TESTMODE:
00728                 /* 7.1.20 Test Mode Support, 9.4.9 Set Feature */
00729                 if ((USBGenericRequest_GetRecipient(pRequest) == USBGenericRequest_DEVICE)
00730                     && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {
00731 
00732                     /* Handle test request */
00733                     USBDDriver_Test(pDriver,
00734                                     USBFeatureRequest_GetTestSelector(pRequest));
00735                 }
00736                 else {
00737 
00738                     USBD_Stall(0);
00739                 }
00740                 break;
00741 
00742 #if 0
00743             case USBFeatureRequest_OTG_B_HNP_ENABLE:
00744                     TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
00745                     pDriver->otg_features_supported |=
00746                         1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
00747                     USBD_Write(0, 0, 0, 0, 0);
00748                 break;
00749             case USBFeatureRequest_OTG_A_HNP_SUPPORT:
00750                     TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
00751                     pDriver->otg_features_supported |=
00752                         1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
00753                     USBD_Write(0, 0, 0, 0, 0);
00754                 break;
00755             case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
00756                     TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
00757                     pDriver->otg_features_supported |=
00758                         1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
00759                     USBD_Write(0, 0, 0, 0, 0);
00760                 break;
00761 #endif
00762             default:
00763                 TRACE_WARNING(
00764                           "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
00765                           USBFeatureRequest_GetFeatureSelector(pRequest));
00766                 USBD_Stall(0);
00767         }
00768         break;
00769 
00770     case USBGenericRequest_SETINTERFACE:
00771         TRACE_INFO_WP("sInterface ");
00772 
00773         infnum = USBInterfaceRequest_GetInterface(pRequest);
00774         setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
00775         SetInterface(pDriver, infnum, setting);
00776         break;
00777 
00778     case USBGenericRequest_GETINTERFACE:
00779         TRACE_INFO_WP("gInterface ");
00780 
00781         infnum = USBInterfaceRequest_GetInterface(pRequest);
00782         GetInterface(pDriver, infnum);
00783         break;
00784 
00785     default:
00786         TRACE_WARNING(
00787                   "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
00788                   USBGenericRequest_GetRequest(pRequest));
00789         USBD_Stall(0);
00790     }
00791 }
00792 
00793 
00794 /**
00795  * Test if RemoteWakeUP feature is enabled
00796  * \param pDriver  Pointer to an USBDDriver instance.
00797  * \return 1 if remote wake up has been enabled by the host; otherwise, returns
00798  * 0
00799  */
00800 uint8_t USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver)
00801 {
00802     return pDriver->isRemoteWakeUpEnabled;
00803 }
00804 
00805 /**
00806  * Return OTG features supported
00807  * \param pDriver  Pointer to an USBDDriver instance.
00808  * \return the OTG features
00809  */
00810 uint8_t USBDDriver_returnOTGFeatures(const USBDDriver *pDriver)
00811 {
00812     return pDriver->otg_features_supported;
00813 }
00814 
00815 /**
00816  * Clear OTG features supported
00817  * \param pDriver  Pointer to an USBDDriver instance.
00818  * \return none
00819  */
00820 void USBDDriver_clearOTGFeatures(USBDDriver *pDriver)
00821 {
00822     pDriver->otg_features_supported = 0;
00823 }
00824 
00825 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines