SAMV71 Xplained Ultra Software Package 1.5

USBD.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  *  \section Purpose
00033  *
00034  *  Implementation of USB device functions on a UDP controller.
00035  *
00036  *  See \ref usbd_api "USBD API Methods".
00037  */
00038 
00039 /** \addtogroup usbd_interface
00040  *@{
00041  */
00042 
00043 /*---------------------------------------------------------------------------
00044  *      Headers
00045  *---------------------------------------------------------------------------*/
00046 
00047 #include "USBD.h"
00048 #include "USBD_HAL.h"
00049 
00050 #include <USBLib_Trace.h>
00051 
00052 /*---------------------------------------------------------------------------
00053  *      Definitions
00054  *---------------------------------------------------------------------------*/
00055 
00056 /*---------------------------------------------------------------------------
00057  *      Internal variables
00058  *---------------------------------------------------------------------------*/
00059 
00060 /** Device current state. */
00061 static uint8_t deviceState;
00062 /** Indicates the previous device state */
00063 static uint8_t previousDeviceState;
00064 
00065 uint8_t ForceFS = 0;
00066 
00067 /*---------------------------------------------------------------------------
00068  *      Internal Functions
00069  *---------------------------------------------------------------------------*/
00070 
00071 /*---------------------------------------------------------------------------
00072  *      Exported functions
00073  *---------------------------------------------------------------------------*/
00074 
00075 /*---------------------------------------------------------------------------
00076  *      USBD: Event handlers
00077  *---------------------------------------------------------------------------*/
00078 
00079 /**
00080  *  Handle the USB suspend event, should be invoked whenever
00081  *  HW reports a suspend signal.
00082  */
00083 void USBD_SuspendHandler(void)
00084 {
00085     /* Don't do anything if the device is already suspended */
00086     if (deviceState != USBD_STATE_SUSPENDED) {
00087 
00088         /* Switch to the Suspended state */
00089         previousDeviceState = deviceState;
00090         deviceState = USBD_STATE_SUSPENDED;
00091 
00092         /* Suspend HW interface */
00093         USBD_HAL_Suspend();
00094 
00095         /* Invoke the User Suspended callback (Suspend System?) */
00096         if (NULL != (void *)USBDCallbacks_Suspended)
00097             USBDCallbacks_Suspended();
00098     }
00099 }
00100 
00101 /**
00102  *  Handle the USB resume event, should be invoked whenever
00103  *  HW reports a resume signal.
00104  */
00105 void USBD_ResumeHandler(void)
00106 {
00107     /* Don't do anything if the device was not suspended */
00108     if (deviceState == USBD_STATE_SUSPENDED) {
00109         /* Active the device */
00110         USBD_HAL_Activate();
00111         deviceState = previousDeviceState;
00112 
00113         if (deviceState >= USBD_STATE_DEFAULT) {
00114             /* Invoke the Resume callback */
00115             if (NULL != (void *)USBDCallbacks_Resumed)
00116                 USBDCallbacks_Resumed();
00117         }
00118     }
00119 }
00120 
00121 /**
00122  *  Handle the USB reset event, should be invoked whenever
00123  *  HW found USB reset signal on bus, which usually is called
00124  *  "end of bus reset" status.
00125  */
00126 void USBD_ResetHandler()
00127 {
00128     /* The device enters the Default state */
00129     deviceState = USBD_STATE_DEFAULT;
00130     /* Active the USB HW */
00131     USBD_HAL_Activate();
00132     /* Only EP0 enabled */
00133     USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0);
00134     USBD_ConfigureEndpoint(0);
00135 
00136     /* Invoke the Reset callback */
00137     if (NULL != (void *)USBDCallbacks_Reset)
00138         USBDCallbacks_Reset();
00139 }
00140 
00141 /**
00142  *  Handle the USB setup package received, should be invoked
00143  *  when an endpoint got a setup package as request.
00144  *  \param bEndpoint Endpoint number.
00145  *  \param pRequest  Pointer to content of request.
00146  */
00147 void USBD_RequestHandler(uint8_t bEndpoint,
00148                          const USBGenericRequest *pRequest)
00149 {
00150     if (bEndpoint != 0) {
00151         TRACE_WARNING("EP%d request not supported, default EP only",
00152                       bEndpoint);
00153     } else if (NULL != (void *)USBDCallbacks_RequestReceived)
00154         USBDCallbacks_RequestReceived(pRequest);
00155 }
00156 
00157 /*---------------------------------------------------------------------------
00158  *      USBD: Library interface
00159  *---------------------------------------------------------------------------*/
00160 
00161 /**
00162  * Configures an endpoint according to its Endpoint Descriptor.
00163  * \param pDescriptor Pointer to an Endpoint descriptor.
00164  */
00165 void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor)
00166 {
00167     USBD_HAL_ConfigureEP(pDescriptor);
00168 }
00169 
00170 /**
00171  * Sends data through a USB endpoint. Sets up the transfer descriptor,
00172  * writes one or two data payloads (depending on the number of FIFO bank
00173  * for the endpoint) and then starts the actual transfer. The operation is
00174  * complete when all the data has been sent.
00175  *
00176  * *If the size of the buffer is greater than the size of the endpoint
00177  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00178  *  must be kept allocated until the transfer is finished*. This means that
00179  *  it is not possible to declare it on the stack (i.e. as a local variable
00180  *  of a function which returns after starting a transfer).
00181  *
00182  * \param bEndpoint Endpoint number.
00183  * \param pData Pointer to a buffer with the data to send.
00184  * \param dLength Size of the data buffer.
00185  * \param fCallback Optional callback function to invoke when the transfer is
00186  *        complete.
00187  * \param pArgument Optional argument to the callback function.
00188  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00189  *         otherwise, the corresponding error status code.
00190  */
00191 uint8_t USBD_Write(uint8_t          bEndpoint,
00192                     const void       *pData,
00193                     uint32_t         dLength,
00194                     TransferCallback fCallback,
00195                     void             *pArgument)
00196 {
00197     USBD_HAL_SetTransferCallback(bEndpoint, fCallback, pArgument);
00198     return USBD_HAL_Write(bEndpoint, pData, dLength);
00199 }
00200 #if 0
00201 /**
00202  * Sends data frames through a USB endpoint. Sets up the transfer descriptor
00203  * list, writes one or two data payloads (depending on the number of FIFO bank
00204  * for the endpoint) and then starts the actual transfer. The operation is
00205  * complete when all the data has been sent.
00206  *
00207  * *If the size of the frame is greater than the size of the endpoint
00208  *  (or twice the size if the endpoint has two FIFO banks), then the buffer
00209  *  must be kept allocated until the frame is finished*. This means that
00210  *  it is not possible to declare it on the stack (i.e. as a local variable
00211  *  of a function which returns after starting a transfer).
00212  *
00213  * \param bEndpoint Endpoint number.
00214  * \param pMbl Pointer to a frame (USBDTransferBuffer) list that describes
00215  *             the buffer list to send.
00216  * \param wListSize Size of the frame list.
00217  * \param bCircList Circle the list.
00218  * \param wStartNdx For circled list only, the first buffer index to transfer.
00219  * \param fCallback Optional callback function to invoke when the transfer is
00220  *        complete.
00221  * \param pArgument Optional argument to the callback function.
00222  * \return USBD_STATUS_SUCCESS if the transfer has been started;
00223  *         otherwise, the corresponding error status code.
00224  * \see USBDTransferBuffer, MblTransferCallback, USBD_MblReuse
00225  */
00226 uint8_t USBD_MblWrite(uint8_t       bEndpoint,
00227                        void                *pMbl,
00228                        uint16_t      wListSize,
00229                        uint8_t       bCircList,
00230                        uint16_t      wStartNdx,
00231                        MblTransferCallback fCallback,
00232                        void                *pArgument)
00233 {
00234     Endpoint    *pEndpoint = &(endpoints[bEndpoint]);
00235     MblTransfer *pTransfer = (MblTransfer *) & (pEndpoint->transfer);
00236     uint16_t i;
00237 
00238     /* EP0 is not suitable for Mbl */
00239 
00240     if (bEndpoint == 0)
00241 
00242         return USBD_STATUS_INVALID_PARAMETER;
00243 
00244     /* Check that the endpoint is in Idle state */
00245 
00246     if (pEndpoint->state != UDP_ENDPOINT_IDLE)
00247 
00248         return USBD_STATUS_LOCKED;
00249 
00250     pEndpoint->state = UDP_ENDPOINT_SENDINGM;
00251 
00252     TRACE_DEBUG_WP("WriteM%d(0x%x,%d) ", bEndpoint, pMbl, wListSize);
00253 
00254     /* Start from first if not circled list */
00255 
00256     if (!bCircList) wStartNdx = 0;
00257 
00258     /* Setup the transfer descriptor */
00259 
00260     pTransfer->pMbl        = (USBDTransferBuffer *)pMbl;
00261     pTransfer->listSize    = wListSize;
00262     pTransfer->fCallback   = fCallback;
00263     pTransfer->pArgument   = pArgument;
00264     pTransfer->currBuffer  = wStartNdx;
00265     pTransfer->freedBuffer = 0;
00266     pTransfer->pLastLoaded = &(((USBDTransferBuffer *)pMbl)[wStartNdx]);
00267     pTransfer->circList    = bCircList;
00268     pTransfer->allUsed     = 0;
00269 
00270     /* Clear all buffer */
00271 
00272     for (i = 0; i < wListSize; i ++) {
00273 
00274         pTransfer->pMbl[i].transferred = 0;
00275         pTransfer->pMbl[i].buffered   = 0;
00276         pTransfer->pMbl[i].remaining   = pTransfer->pMbl[i].size;
00277     }
00278 
00279     /* Send the first packet */
00280 
00281     while ((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY) == UDP_CSR_TXPKTRDY);
00282 
00283     UDP_MblWriteFifo(bEndpoint);
00284     SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY);
00285 
00286     /* If double buffering is enabled and there is data remaining, */
00287 
00288     /* prepare another packet */
00289 
00290     if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1)
00291         && (pTransfer->pMbl[pTransfer->currBuffer].remaining > 0))
00292 
00293         UDP_MblWriteFifo(bEndpoint);
00294 
00295     /* Enable interrupt on endpoint */
00296 
00297     UDP->UDP_IER = 1 << bEndpoint;
00298 
00299     return USBD_STATUS_SUCCESS;
00300 }
00301 #endif
00302 /**
00303  * Reads incoming data on an USB endpoint This methods sets the transfer
00304  * descriptor and activate the endpoint interrupt. The actual transfer is
00305  * then carried out by the endpoint interrupt handler. The Read operation
00306  * finishes either when the buffer is full, or a short packet (inferior to
00307  * endpoint maximum  size) is received.
00308  *
00309  * *The buffer must be kept allocated until the transfer is finished*.
00310  * \param bEndpoint Endpoint number.
00311  * \param pData Pointer to a data buffer.
00312  * \param dLength Size of the data buffer in bytes.
00313  * \param fCallback Optional end-of-transfer callback function.
00314  * \param pArgument Optional argument to the callback function.
00315  * \return USBD_STATUS_SUCCESS if the read operation has been started;
00316  *         otherwise, the corresponding error code.
00317  */
00318 uint8_t USBD_Read(uint8_t          bEndpoint,
00319                   void             *pData,
00320                   uint32_t         dLength,
00321                   TransferCallback fCallback,
00322                   void             *pArgument)
00323 {
00324     USBD_HAL_SetTransferCallback(bEndpoint, fCallback, pArgument);
00325     return USBD_HAL_Read(bEndpoint, pData, dLength);
00326 }
00327 #if 0
00328 /**
00329  * Reuse first used/released buffer with new buffer address and size to be used
00330  * in transfer again. Only valid when frame list is ringed. Can be used for
00331  * both read & write.
00332  * \param bEndpoint  Endpoint number.
00333  * \param pNewBuffer Pointer to new buffer with data to send (0 to keep last).
00334  * \param wNewSize   Size of the data buffer
00335  */
00336 uint8_t USBD_MblReuse(uint8_t  bEndpoint,
00337                        uint8_t  *pNewBuffer,
00338                        uint16_t wNewSize)
00339 {
00340     Endpoint *pEndpoint = &(endpoints[bEndpoint]);
00341     MblTransfer *pTransfer = (MblTransfer *)&(pEndpoint->transfer);
00342     USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->freedBuffer]);
00343 
00344     TRACE_DEBUG_WP("MblReuse(%d), st%x, circ%d\n\r",
00345                    bEndpoint, pEndpoint->state, pTransfer->circList);
00346 
00347     /* Only for Multi-buffer-circle list */
00348 
00349     if (bEndpoint != 0
00350         && (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM
00351             || pEndpoint->state == UDP_ENDPOINT_SENDINGM)
00352         && pTransfer->circList) {
00353     } else
00354 
00355         return USBD_STATUS_WRONG_STATE;
00356 
00357     /* Check if there is freed buffer */
00358 
00359     if (pTransfer->freedBuffer == pTransfer->currBuffer
00360         && !pTransfer->allUsed)
00361 
00362         return USBD_STATUS_LOCKED;
00363 
00364     /* Update transfer information */
00365 
00366     if ((++ pTransfer->freedBuffer) == pTransfer->listSize)
00367         pTransfer->freedBuffer = 0;
00368 
00369     if (pNewBuffer) {
00370         pBi->pBuffer = pNewBuffer;
00371         pBi->size    = wNewSize;
00372     }
00373 
00374     pBi->buffered    = 0;
00375     pBi->transferred = 0;
00376     pBi->remaining   = pBi->size;
00377 
00378     /* At least one buffer is not processed */
00379 
00380     pTransfer->allUsed = 0;
00381     return USBD_STATUS_SUCCESS;
00382 }
00383 #endif
00384 /**
00385  * Sets the HALT feature on the given endpoint (if not already in this state).
00386  * \param bEndpoint Endpoint number.
00387  */
00388 void USBD_Halt(uint8_t bEndpoint)
00389 {
00390     USBD_HAL_Halt(bEndpoint, 1);
00391 }
00392 
00393 /**
00394  * Clears the Halt feature on the given endpoint.
00395  * \param bEndpoint Index of endpoint
00396  */
00397 void USBD_Unhalt(uint8_t bEndpoint)
00398 {
00399     USBD_HAL_Halt(bEndpoint, 0);
00400 }
00401 
00402 /**
00403  * Returns the current Halt status of an endpoint.
00404  * \param bEndpoint Index of endpoint
00405  * \return 1 if the endpoint is currently halted; otherwise 0
00406  */
00407 uint8_t USBD_IsHalted(uint8_t bEndpoint)
00408 {
00409     return USBD_HAL_Halt(bEndpoint, 0xFF);
00410 }
00411 
00412 /**
00413  * Indicates if the device is running in high or full-speed. Always returns 0
00414  * since UDP does not support high-speed mode.
00415  */
00416 uint8_t USBD_IsHighSpeed(void)
00417 {
00418     return USBD_HAL_IsHighSpeed();
00419 }
00420 
00421 /**
00422  * Causes the given endpoint to acknowledge the next packet it receives
00423  * with a STALL handshake.
00424  * \param bEndpoint Endpoint number.
00425  * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED.
00426  */
00427 uint8_t USBD_Stall(uint8_t bEndpoint)
00428 
00429 {
00430     return USBD_HAL_Stall(bEndpoint);
00431 }
00432 
00433 /**
00434  * Sets the device address to the given value.
00435  * \param address New device address.
00436  */
00437 void USBD_SetAddress(uint8_t address)
00438 {
00439     TRACE_INFO_WP("SetAddr(%d) ", address);
00440 
00441     USBD_HAL_SetAddress(address);
00442 
00443     if (address == 0)
00444         deviceState = USBD_STATE_DEFAULT;
00445     else
00446         deviceState = USBD_STATE_ADDRESS;
00447 }
00448 
00449 /**
00450  * Sets the current device configuration.
00451  * \param cfgnum - Configuration number to set.
00452  */
00453 void USBD_SetConfiguration(uint8_t cfgnum)
00454 {
00455     TRACE_INFO_WP("SetCfg(%d) ", cfgnum);
00456 
00457     USBD_HAL_SetConfiguration(cfgnum);
00458 
00459     if (cfgnum != 0)
00460         deviceState = USBD_STATE_CONFIGURED;
00461     else {
00462         deviceState = USBD_STATE_ADDRESS;
00463         /* Reset all endpoints but Control 0 */
00464         USBD_HAL_ResetEPs(0xFFFFFFFE, USBD_STATUS_RESET, 0);
00465     }
00466 }
00467 
00468 /*---------------------------------------------------------------------------
00469  *      USBD: Library API
00470  *---------------------------------------------------------------------------*/
00471 
00472 /**
00473  * Starts a remote wake-up procedure.
00474  */
00475 void USBD_RemoteWakeUp(void)
00476 {
00477     /* Device is NOT suspended */
00478     if (deviceState != USBD_STATE_SUSPENDED) {
00479         TRACE_INFO("USBD_RemoteWakeUp: Device is not suspended\n\r");
00480         return;
00481     }
00482 
00483     USBD_HAL_Activate();
00484     USBD_HAL_RemoteWakeUp();
00485 }
00486 
00487 /**
00488  * Connects the pull-up on the D+ line of the USB.
00489  */
00490 void USBD_Connect(void)
00491 {
00492     TRACE_INFO(" Connect -");
00493     USBD_HAL_Connect();
00494 }
00495 
00496 /**
00497  * Disconnects the pull-up from the D+ line of the USB.
00498  */
00499 void USBD_Disconnect(void)
00500 {
00501     TRACE_INFO(" DisConnect -");
00502     USBD_HAL_Disconnect();
00503 
00504     /* Device returns to the Powered state */
00505 
00506     if (deviceState > USBD_STATE_POWERED)
00507 
00508         deviceState = USBD_STATE_POWERED;
00509 
00510     if (previousDeviceState > USBD_STATE_POWERED)
00511 
00512         previousDeviceState = USBD_STATE_POWERED;
00513 }
00514 
00515 /**
00516  * Initializes the USB driver.
00517  */
00518 void USBD_Init(void)
00519 {
00520     TRACE_INFO_WP("USBD_Init\n\r");
00521 
00522     /* HW Layer Initialize */
00523     USBD_HAL_Init();
00524 
00525     /* Device is in the Attached state */
00526     deviceState = USBD_STATE_SUSPENDED;
00527     previousDeviceState = USBD_STATE_POWERED;
00528 
00529     /* Upper Layer Initialize */
00530     if (NULL != (void *)USBDCallbacks_Initialized)
00531         USBDCallbacks_Initialized();
00532 }
00533 
00534 /**
00535  * Returns the current state of the USB device.
00536  * \return Device current state.
00537  */
00538 uint8_t USBD_GetState(void)
00539 {
00540     return deviceState;
00541 }
00542 
00543 /**
00544  * Certification test for High Speed device.
00545  * \param bIndex Test to be done
00546  */
00547 void USBD_Test(uint8_t bIndex)
00548 {
00549     USBD_HAL_Test(bIndex);
00550 }
00551 
00552 
00553 void USBD_ForceFullSpeed(void)
00554 {
00555     ForceFS = 1;
00556 }
00557 
00558 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines