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 * 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 != 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 if (deviceState >= USBD_STATE_DEFAULT) { 00113 /* Invoke the Resume callback */ 00114 if (NULL != USBDCallbacks_Resumed) 00115 USBDCallbacks_Resumed(); 00116 } 00117 } 00118 } 00119 00120 /** 00121 * Handle the USB reset event, should be invoked whenever 00122 * HW found USB reset signal on bus, which usually is called 00123 * "end of bus reset" status. 00124 */ 00125 void USBD_ResetHandler() 00126 { 00127 /* The device enters the Default state */ 00128 deviceState = USBD_STATE_DEFAULT; 00129 /* Active the USB HW */ 00130 USBD_HAL_Activate(); 00131 /* Only EP0 enabled */ 00132 USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0); 00133 USBD_ConfigureEndpoint(0); 00134 /* Invoke the Reset callback */ 00135 if (NULL != USBDCallbacks_Reset) 00136 USBDCallbacks_Reset(); 00137 } 00138 00139 /** 00140 * Handle the USB setup package received, should be invoked 00141 * when an endpoint got a setup package as request. 00142 * \param bEndpoint Endpoint number. 00143 * \param pRequest Pointer to content of request. 00144 */ 00145 void USBD_RequestHandler(uint8_t bEndpoint, 00146 const USBGenericRequest* pRequest) 00147 { 00148 if (bEndpoint != 0) { 00149 TRACE_WARNING("EP%d request not supported, default EP only", 00150 bEndpoint); 00151 } 00152 else if (NULL != USBDCallbacks_RequestReceived) { 00153 USBDCallbacks_RequestReceived(pRequest); 00154 } 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 00245 /* Check that the endpoint is in Idle state */ 00246 00247 if (pEndpoint->state != UDP_ENDPOINT_IDLE) { 00248 00249 return USBD_STATUS_LOCKED; 00250 } 00251 pEndpoint->state = UDP_ENDPOINT_SENDINGM; 00252 00253 TRACE_DEBUG_WP("WriteM%d(0x%x,%d) ", bEndpoint, pMbl, wListSize); 00254 00255 /* Start from first if not circled list */ 00256 00257 if (!bCircList) wStartNdx = 0; 00258 00259 /* Setup the transfer descriptor */ 00260 00261 pTransfer->pMbl = (USBDTransferBuffer*)pMbl; 00262 pTransfer->listSize = wListSize; 00263 pTransfer->fCallback = fCallback; 00264 pTransfer->pArgument = pArgument; 00265 pTransfer->currBuffer = wStartNdx; 00266 pTransfer->freedBuffer = 0; 00267 pTransfer->pLastLoaded = &(((USBDTransferBuffer*)pMbl)[wStartNdx]); 00268 pTransfer->circList = bCircList; 00269 pTransfer->allUsed = 0; 00270 00271 /* Clear all buffer */ 00272 00273 for (i = 0; i < wListSize; i ++) { 00274 00275 pTransfer->pMbl[i].transferred = 0; 00276 pTransfer->pMbl[i].buffered = 0; 00277 pTransfer->pMbl[i].remaining = pTransfer->pMbl[i].size; 00278 } 00279 00280 /* Send the first packet */ 00281 00282 while((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY)==UDP_CSR_TXPKTRDY); 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 00296 /* Enable interrupt on endpoint */ 00297 00298 UDP->UDP_IER = 1 << bEndpoint; 00299 00300 return USBD_STATUS_SUCCESS; 00301 } 00302 #endif 00303 /** 00304 * Reads incoming data on an USB endpoint This methods sets the transfer 00305 * descriptor and activate the endpoint interrupt. The actual transfer is 00306 * then carried out by the endpoint interrupt handler. The Read operation 00307 * finishes either when the buffer is full, or a short packet (inferior to 00308 * endpoint maximum size) is received. 00309 * 00310 * *The buffer must be kept allocated until the transfer is finished*. 00311 * \param bEndpoint Endpoint number. 00312 * \param pData Pointer to a data buffer. 00313 * \param dLength Size of the data buffer in bytes. 00314 * \param fCallback Optional end-of-transfer callback function. 00315 * \param pArgument Optional argument to the callback function. 00316 * \return USBD_STATUS_SUCCESS if the read operation has been started; 00317 * otherwise, the corresponding error code. 00318 */ 00319 uint8_t USBD_Read(uint8_t bEndpoint, 00320 void *pData, 00321 uint32_t dLength, 00322 TransferCallback fCallback, 00323 void *pArgument) 00324 { 00325 USBD_HAL_SetTransferCallback(bEndpoint, fCallback, pArgument); 00326 return USBD_HAL_Read(bEndpoint, pData, dLength); 00327 } 00328 #if 0 00329 /** 00330 * Reuse first used/released buffer with new buffer address and size to be used 00331 * in transfer again. Only valid when frame list is ringed. Can be used for 00332 * both read & write. 00333 * \param bEndpoint Endpoint number. 00334 * \param pNewBuffer Pointer to new buffer with data to send (0 to keep last). 00335 * \param wNewSize Size of the data buffer 00336 */ 00337 uint8_t USBD_MblReuse( uint8_t bEndpoint, 00338 uint8_t *pNewBuffer, 00339 uint16_t wNewSize ) 00340 { 00341 Endpoint *pEndpoint = &(endpoints[bEndpoint]); 00342 MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer); 00343 USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->freedBuffer]); 00344 00345 TRACE_DEBUG_WP("MblReuse(%d), st%x, circ%d\n\r", 00346 bEndpoint, pEndpoint->state, pTransfer->circList); 00347 00348 /* Only for Multi-buffer-circle list */ 00349 00350 if (bEndpoint != 0 00351 && (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM 00352 || pEndpoint->state == UDP_ENDPOINT_SENDINGM) 00353 && pTransfer->circList) { 00354 } 00355 else { 00356 00357 return USBD_STATUS_WRONG_STATE; 00358 } 00359 00360 /* Check if there is freed buffer */ 00361 00362 if (pTransfer->freedBuffer == pTransfer->currBuffer 00363 && !pTransfer->allUsed) { 00364 00365 return USBD_STATUS_LOCKED; 00366 } 00367 00368 /* Update transfer information */ 00369 00370 if ((++ pTransfer->freedBuffer) == pTransfer->listSize) 00371 pTransfer->freedBuffer = 0; 00372 if (pNewBuffer) { 00373 pBi->pBuffer = pNewBuffer; 00374 pBi->size = wNewSize; 00375 } 00376 pBi->buffered = 0; 00377 pBi->transferred = 0; 00378 pBi->remaining = pBi->size; 00379 00380 /* At least one buffer is not processed */ 00381 00382 pTransfer->allUsed = 0; 00383 return USBD_STATUS_SUCCESS; 00384 } 00385 #endif 00386 /** 00387 * Sets the HALT feature on the given endpoint (if not already in this state). 00388 * \param bEndpoint Endpoint number. 00389 */ 00390 void USBD_Halt(uint8_t bEndpoint) 00391 { 00392 USBD_HAL_Halt(bEndpoint, 1); 00393 } 00394 00395 /** 00396 * Clears the Halt feature on the given endpoint. 00397 * \param bEndpoint Index of endpoint 00398 */ 00399 void USBD_Unhalt(uint8_t bEndpoint) 00400 { 00401 USBD_HAL_Halt(bEndpoint, 0); 00402 } 00403 00404 /** 00405 * Returns the current Halt status of an endpoint. 00406 * \param bEndpoint Index of endpoint 00407 * \return 1 if the endpoint is currently halted; otherwise 0 00408 */ 00409 uint8_t USBD_IsHalted(uint8_t bEndpoint) 00410 { 00411 return USBD_HAL_Halt(bEndpoint, 0xFF); 00412 } 00413 00414 /** 00415 * Indicates if the device is running in high or full-speed. Always returns 0 00416 * since UDP does not support high-speed mode. 00417 */ 00418 uint8_t USBD_IsHighSpeed(void) 00419 { 00420 return USBD_HAL_IsHighSpeed(); 00421 } 00422 00423 /** 00424 * Causes the given endpoint to acknowledge the next packet it receives 00425 * with a STALL handshake. 00426 * \param bEndpoint Endpoint number. 00427 * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED. 00428 */ 00429 uint8_t USBD_Stall(uint8_t bEndpoint) 00430 00431 { 00432 return USBD_HAL_Stall(bEndpoint); 00433 } 00434 00435 /** 00436 * Sets the device address to the given value. 00437 * \param address New device address. 00438 */ 00439 void USBD_SetAddress(uint8_t address) 00440 { 00441 TRACE_INFO_WP("SetAddr(%d) ", address); 00442 00443 USBD_HAL_SetAddress(address); 00444 if (address == 0) deviceState = USBD_STATE_DEFAULT; 00445 else deviceState = USBD_STATE_ADDRESS; 00446 } 00447 00448 /** 00449 * Sets the current device configuration. 00450 * \param cfgnum - Configuration number to set. 00451 */ 00452 void USBD_SetConfiguration(uint8_t cfgnum) 00453 { 00454 TRACE_INFO_WP("SetCfg(%d) ", cfgnum); 00455 00456 USBD_HAL_SetConfiguration(cfgnum); 00457 00458 if (cfgnum != 0) { 00459 deviceState = USBD_STATE_CONFIGURED; 00460 } 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 00480 TRACE_INFO("USBD_RemoteWakeUp: Device is not suspended\n\r"); 00481 return; 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 00511 if (previousDeviceState > USBD_STATE_POWERED) { 00512 00513 previousDeviceState = USBD_STATE_POWERED; 00514 } 00515 } 00516 00517 /** 00518 * Initializes the USB driver. 00519 */ 00520 void USBD_Init(void) 00521 { 00522 TRACE_INFO_WP("USBD_Init\n\r"); 00523 00524 /* HW Layer Initialize */ 00525 USBD_HAL_Init(); 00526 00527 /* Device is in the Attached state */ 00528 deviceState = USBD_STATE_SUSPENDED; 00529 previousDeviceState = USBD_STATE_POWERED; 00530 00531 /* Upper Layer Initialize */ 00532 if (NULL != USBDCallbacks_Initialized) 00533 USBDCallbacks_Initialized(); 00534 } 00535 00536 /** 00537 * Returns the current state of the USB device. 00538 * \return Device current state. 00539 */ 00540 uint8_t USBD_GetState(void) 00541 { 00542 return deviceState; 00543 } 00544 00545 /** 00546 * Certification test for High Speed device. 00547 * \param bIndex Test to be done 00548 */ 00549 void USBD_Test(uint8_t bIndex) 00550 { 00551 USBD_HAL_Test(bIndex); 00552 } 00553 00554 00555 void USBD_ForceFullSpeed(void) 00556 { 00557 ForceFS = 1; 00558 } 00559 00560 /**@}*/