]> begriffs open source - cmsis-freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c
Set error state if no delay or already expired
[cmsis-freertos] / Demo / lwIP_Demo_Rowley_ARM7 / USB / USB-CDC.c
1 /*
2  * FreeRTOS Kernel V10.1.1
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28 /*
29         USB Communications Device Class driver.
30         Implements task vUSBCDCTask and provides an Abstract Control Model serial 
31         interface.  Control is through endpoint 0, device-to-host notification is 
32         provided by interrupt-in endpoint 3, and raw data is transferred through 
33         bulk endpoints 1 and 2.
34
35         - developed from original FreeRTOS HID example by Scott Miller
36         - modified to support 3.2 GCC by najay
37 */
38
39 /* Standard includes. */
40 #include <string.h>
41 #include <stdio.h>
42
43 /* Demo board includes. */
44 #include "Board.h"
45
46 /* Scheduler includes. */
47 #include "FreeRTOS.h"
48 #include "task.h"
49 #include "queue.h"
50
51 /* Demo app includes. */
52 #include "USB-CDC.h"
53 #include "descriptors.h"
54
55 #define usbNO_BLOCK ( ( TickType_t ) 0 )
56
57 /* Reset all endpoints */
58 static void prvResetEndPoints( void );
59
60 /* Clear pull up resistor to detach device from host */
61 static void vDetachUSBInterface( void );
62
63 /* Set up interface and initialize variables */
64 static void vInitUSBInterface( void );
65
66 /* Handle control endpoint events. */
67 static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage );
68
69 /* Handle standard device requests. */
70 static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest );
71
72 /* Handle standard interface requests. */
73 static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest );
74
75 /* Handle endpoint requests. */
76 static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest );
77
78 /* Handle class interface requests. */
79 static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest );
80
81 /* Prepare control data transfer.  prvSendNextSegment starts transfer. */
82 static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthLeftToSend, long lSendingDescriptor );
83
84 /* Send next segment of data for the control transfer */
85 static void prvSendNextSegment( void );
86
87 /* Send stall - used to respond to unsupported requests */
88 static void prvSendStall( void );
89
90 /* Send a zero-length (null) packet */
91 static void prvSendZLP( void );
92
93 /* Handle requests for standard interface descriptors */
94 static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest );
95
96 /*------------------------------------------------------------*/
97
98 /* File scope static variables */
99 static unsigned char ucUSBConfig = ( unsigned char ) 0;
100 static unsigned long ulReceivedAddress = ( unsigned long ) 0;
101 static eDRIVER_STATE eDriverState = eNOTHING;
102
103 /* Incoming and outgoing control data structures */
104 static xCONTROL_MESSAGE pxControlTx;
105 static xCONTROL_MESSAGE pxControlRx;
106
107 /* Queue holding pointers to pending messages */
108 QueueHandle_t xUSBInterruptQueue; 
109
110 /* Queues used to hold received characters, and characters waiting to be
111 transmitted.  Rx queue must be larger than FIFO size. */
112 static QueueHandle_t xRxCDC; 
113 static QueueHandle_t xTxCDC; 
114
115 /* Line coding - 115,200 baud, N-8-1 */
116 static const unsigned char pxLineCoding[] = { 0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08 };
117
118 /* Status variables. */
119 static unsigned char ucControlState;
120 static unsigned int uiCurrentBank;
121
122
123 /*------------------------------------------------------------*/
124
125
126 void vUSBCDCTask( void *pvParameters )
127 {
128 xISRStatus *pxMessage;
129 unsigned long ulStatus;
130 unsigned long ulRxBytes;
131 unsigned char ucByte;
132 portBASE_TYPE xByte;
133
134         ( void ) pvParameters;
135
136         /* Disconnect USB device from hub.  For debugging - causes host to register reset */
137         portENTER_CRITICAL();
138                  vDetachUSBInterface();
139         portEXIT_CRITICAL();
140         
141         vTaskDelay( portTICK_PERIOD_MS * 60 );
142
143         /* Init USB interface */
144         portENTER_CRITICAL();
145                 vInitUSBInterface();
146         portEXIT_CRITICAL();
147         
148         /* Main task loop.  Process incoming endpoint 0 interrupts, handle data transfers. */
149          
150         for( ;; )
151         {
152                 /* Look for data coming from the ISR. */
153                 if( xQueueReceive( xUSBInterruptQueue, &pxMessage, usbSHORTEST_DELAY ) )
154                 {
155                         if( pxMessage->ulISR & AT91C_UDP_EPINT0 )
156                         {
157                                 /* All endpoint 0 interrupts are handled here. */
158                                 prvProcessEndPoint0Interrupt( pxMessage );
159                         }
160
161                         if( pxMessage->ulISR & AT91C_UDP_ENDBUSRES )
162                         {
163                                 /* End of bus reset - reset the endpoints and de-configure. */
164                                 prvResetEndPoints();            
165                         }
166                 }
167                 
168                 /* See if we're ready to send and receive data. */
169                 if( eDriverState == eREADY_TO_SEND && ucControlState ) 
170                 {
171                         if( ( !(AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] & AT91C_UDP_TXPKTRDY) ) && uxQueueMessagesWaiting( xTxCDC ) )
172                         {
173                                 for( xByte = 0; xByte < 64; xByte++ )
174                                 {                                  
175                                         if( !xQueueReceive( xTxCDC, &ucByte, 0 ) ) 
176                                         {
177                                                 /* No data buffered to transmit. */
178                                                 break;
179                                         }
180
181                                         /* Got a byte to transmit. */
182                                         AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_2 ] = ucByte;
183                                 } 
184                                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] |= AT91C_UDP_TXPKTRDY;
185                         }
186
187                         /* Check for incoming data (host-to-device) on endpoint 1. */
188                         while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) )
189                         {
190                                 ulRxBytes = (AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] >> 16) & usbRX_COUNT_MASK;
191
192                                 /* Only process FIFO if there's room to store it in the queue */
193                                 if( ulRxBytes < ( USB_CDC_QUEUE_SIZE - uxQueueMessagesWaiting( xRxCDC ) ) )
194                                 {
195                                         while( ulRxBytes-- )
196                                         {
197                                                 ucByte = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ];
198                                                 xQueueSend( xRxCDC, &ucByte, 0 );
199                                         }
200
201                                         /* Release the FIFO */
202                                         portENTER_CRITICAL();
203                                         {
204                                                 ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
205                                                 usbCSR_CLEAR_BIT( &ulStatus, uiCurrentBank );
206                                                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulStatus;
207                                         }
208                                         portEXIT_CRITICAL();
209
210                                         /* Re-enable endpoint 1's interrupts */
211                                         AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
212                                 
213                                         /* Update the current bank in use */
214                                         if( uiCurrentBank == AT91C_UDP_RX_DATA_BK0 ) 
215                                         {
216                                                 uiCurrentBank = AT91C_UDP_RX_DATA_BK1;
217                                         }
218                                         else 
219                                         {
220                                                 uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
221                                         }
222
223                                 }
224                                 else 
225                                 {
226                                         break;
227                                 }
228                         }
229                 }
230         }
231 }
232 /*------------------------------------------------------------*/
233
234 void vUSBSendByte( char cByte )
235 {
236         /* Queue the byte to be sent.  The USB task will send it. */
237         xQueueSend( xTxCDC, &cByte, usbNO_BLOCK );
238 }
239 /*------------------------------------------------------------*/
240
241 static void prvSendZLP( void )
242 {
243 unsigned long ulStatus;
244
245         /* Wait until the FIFO is free - even though we are not going to use it.
246         THERE IS NO TIMEOUT HERE! */
247         while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
248         {
249                 vTaskDelay( usbSHORTEST_DELAY );
250         }
251
252         portENTER_CRITICAL();
253         {
254                 /* Cancel any further pending data */
255                 pxControlTx.ulTotalDataLength = pxControlTx.ulNextCharIndex;
256
257                 /* Set the TXPKTRDY bit to cause a transmission with no data. */
258                 ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
259                 usbCSR_SET_BIT( &ulStatus, AT91C_UDP_TXPKTRDY );
260                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
261         }
262         portEXIT_CRITICAL();
263 }
264 /*------------------------------------------------------------*/
265
266 static void prvSendStall( void )
267 {
268         unsigned long ulStatus;
269
270         portENTER_CRITICAL();
271         {
272                 /* Force a stall by simply setting the FORCESTALL bit in the CSR. */
273                 ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
274                 usbCSR_SET_BIT( &ulStatus, AT91C_UDP_FORCESTALL );
275                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
276         }
277         portEXIT_CRITICAL();
278 }
279 /*------------------------------------------------------------*/
280
281 static void prvResetEndPoints( void )
282 {
283 unsigned long ulTemp;
284
285         eDriverState = eJUST_RESET;
286         ucControlState = 0;
287
288         /* Reset all the end points. */
289         AT91C_BASE_UDP->UDP_RSTEP  = usbEND_POINT_RESET_MASK;
290         AT91C_BASE_UDP->UDP_RSTEP  = ( unsigned long ) 0x00;
291
292         /* Enable data to be sent and received. */
293         AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
294
295         /* Repair the configuration end point. */
296         portENTER_CRITICAL();
297         {
298                 ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
299                 usbCSR_SET_BIT( &ulTemp, ( ( unsigned long ) ( AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL ) ) );
300                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
301                 AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
302         }
303         portEXIT_CRITICAL();
304         uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
305 }
306 /*------------------------------------------------------------*/
307
308 static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage )
309 {
310 static xUSB_REQUEST xRequest;
311 unsigned long ulRxBytes;
312
313         /* Get number of bytes received, if any */
314         ulRxBytes = pxMessage->ulCSR0 >> 16;
315         ulRxBytes &= usbRX_COUNT_MASK;
316
317         if( pxMessage->ulCSR0 & AT91C_UDP_TXCOMP )
318         {
319                 /* We received a TX complete interrupt.  What we do depends on
320                 what we sent to get this interrupt. */
321
322                 if( eDriverState == eJUST_GOT_CONFIG )
323                 {
324                         /* We sent an acknowledgement of a SET_CONFIG request.  We
325                         are now at the end of the enumeration.
326                         
327                         TODO: Config 0 sets unconfigured state, should enter Address state.
328                         Request for unsupported config should stall. */
329                         AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
330                         
331                         /* Set up endpoints */
332                         portENTER_CRITICAL();
333                         {
334                                 unsigned long ulTemp;
335
336                                 /* Set endpoint 1 to bulk-out */
337                                 ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];                                     
338                                 usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT );
339                                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;             
340                                 AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
341                                 /* Set endpoint 2 to bulk-in */
342                                 ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ];                                     
343                                 usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN );
344                                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] = ulTemp;             
345                                 AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT2;
346                                         /* Set endpoint 3 to interrupt-in, enable it, and enable interrupts */
347                                 ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ];                                     
348                                 usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN );
349                                 AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ] = ulTemp;             
350                                 /*AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT3 );                                */
351                         }
352                         portEXIT_CRITICAL();
353
354                         eDriverState = eREADY_TO_SEND;
355                 }               
356                 else if( eDriverState == eJUST_GOT_ADDRESS )
357                 {
358                         /* We sent an acknowledgement of a SET_ADDRESS request.  Move
359                         to the addressed state. */
360                         if( ulReceivedAddress != ( unsigned long ) 0 )
361                         {                       
362                                 AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
363                         }
364                         else
365                         {
366                                 AT91C_BASE_UDP->UDP_GLBSTATE = 0;
367                         }                       
368
369                         AT91C_BASE_UDP->UDP_FADDR = ( AT91C_UDP_FEN | ulReceivedAddress );              
370                         eDriverState = eNOTHING;
371                 }
372                 else
373                 {               
374                         /* The TXCOMP was not for any special type of transmission.  See
375                         if there is any more data to send. */
376                         prvSendNextSegment();
377                 }
378         }
379
380         if( pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0 )
381         {
382                 /* Received a control data packet.  May be a 0-length ACK or a data stage. */
383                 unsigned char ucBytesToGet;
384          
385                 /* Got data.  Cancel any outgoing data. */
386                 pxControlTx.ulNextCharIndex = pxControlTx.ulTotalDataLength;
387                 
388                  /* Determine how many bytes we need to receive. */
389                 ucBytesToGet = pxControlRx.ulTotalDataLength - pxControlRx.ulNextCharIndex;
390                 if( ucBytesToGet > ulRxBytes ) 
391                 {       
392                         ucBytesToGet = ulRxBytes;
393                 }
394
395                 /* If we're not expecting any data, it's an ack - just quit now. */
396                 if( !ucBytesToGet )
397                 {
398                          return;
399                 }
400
401                 /* Get the required data and update the index. */
402                 memcpy( pxControlRx.ucBuffer, pxMessage->ucFifoData, ucBytesToGet );
403                 pxControlRx.ulNextCharIndex += ucBytesToGet;    
404         }
405
406         if( pxMessage->ulCSR0 & AT91C_UDP_RXSETUP )
407         {
408                 /* Received a SETUP packet.  May be followed by data packets. */
409
410                 if( ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES )
411                 {                               
412                         /* Create an xUSB_REQUEST variable from the raw bytes array. */
413
414                         xRequest.ucReqType = pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ];
415                         xRequest.ucRequest = pxMessage->ucFifoData[ usbREQUEST_INDEX ];
416
417                         xRequest.usValue = pxMessage->ucFifoData[ usbVALUE_HIGH_BYTE ];
418                         xRequest.usValue <<= 8;
419                         xRequest.usValue |= pxMessage->ucFifoData[ usbVALUE_LOW_BYTE ];
420                                                 
421                         xRequest.usIndex = pxMessage->ucFifoData[ usbINDEX_HIGH_BYTE ];
422                         xRequest.usIndex <<= 8;
423                         xRequest.usIndex |= pxMessage->ucFifoData[ usbINDEX_LOW_BYTE ];
424                         
425                         xRequest.usLength = pxMessage->ucFifoData[ usbLENGTH_HIGH_BYTE ];
426                         xRequest.usLength <<= 8;
427                         xRequest.usLength |= pxMessage->ucFifoData[ usbLENGTH_LOW_BYTE ];
428
429                         pxControlRx.ulNextCharIndex = 0;
430                         if( ! (xRequest.ucReqType & 0x80) ) /* Host-to-Device transfer, may need to get data first */
431                         {
432                                 if( xRequest.usLength > usbMAX_CONTROL_MESSAGE_SIZE )
433                                 {       
434                                         /* Too big!  No space for control data, stall and abort. */
435                                         prvSendStall();
436                                         return;
437                                 }
438
439                                 pxControlRx.ulTotalDataLength = xRequest.usLength;
440                         }
441                         else
442                         {
443                                 /* We're sending the data, don't wait for any. */
444                                 pxControlRx.ulTotalDataLength = 0; 
445                         }
446                 }
447         }
448
449         /* See if we've got a pending request and all its associated data ready */
450         if( ( pxMessage->ulCSR0 & ( AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP ) ) 
451                 && ( pxControlRx.ulNextCharIndex >= pxControlRx.ulTotalDataLength ) )
452         {
453                 unsigned char ucRequest;
454
455                 /* Manipulate the ucRequestType and the ucRequest parameters to 
456                 generate a zero based request selection.  This is just done to 
457                 break up the requests into subsections for clarity.  The 
458                 alternative would be to have more huge switch statement that would
459                 be difficult to optimise. */
460                 ucRequest = ( ( xRequest.ucReqType & 0x60 ) >> 3 );
461                 ucRequest |= ( xRequest.ucReqType & 0x03 );
462                         
463                 switch( ucRequest )
464                 {
465                         case usbSTANDARD_DEVICE_REQUEST:        
466                                 /* Standard Device request */
467                                 prvHandleStandardDeviceRequest( &xRequest );
468                                 break;
469
470                         case usbSTANDARD_INTERFACE_REQUEST:     
471                                 /* Standard Interface request */
472                                 prvHandleStandardInterfaceRequest( &xRequest );
473                                 break;
474
475                         case usbSTANDARD_END_POINT_REQUEST:     
476                                 /* Standard Endpoint request */
477                                 prvHandleStandardEndPointRequest( &xRequest );
478                                 break;
479
480                         case usbCLASS_INTERFACE_REQUEST:        
481                                 /* Class Interface request */
482                                 prvHandleClassInterfaceRequest( &xRequest );
483                                 break;
484
485                         default:        /* This is not something we want to respond to. */
486                                 prvSendStall(); 
487                 }
488         }
489 }
490 /*------------------------------------------------------------*/
491
492 static void prvGetStandardDeviceDescriptor( xUSB_REQUEST *pxRequest )
493 {
494         /* The type is in the high byte.  Return whatever has been requested. */
495         switch( ( pxRequest->usValue & 0xff00 ) >> 8 )
496         {
497                 case usbDESCRIPTOR_TYPE_DEVICE:
498                         prvSendControlData( ( unsigned char * ) &pxDeviceDescriptor, pxRequest->usLength, sizeof( pxDeviceDescriptor ), pdTRUE );
499                         break;
500
501                 case usbDESCRIPTOR_TYPE_CONFIGURATION:
502                         prvSendControlData( ( unsigned char * ) &( pxConfigDescriptor ), pxRequest->usLength, sizeof( pxConfigDescriptor ), pdTRUE );
503                         break;
504
505                 case usbDESCRIPTOR_TYPE_STRING:
506
507                         /* The index to the string descriptor is the lower byte. */
508                         switch( pxRequest->usValue & 0xff )
509                         {                       
510                                 case usbLANGUAGE_STRING:
511                                         prvSendControlData( ( unsigned char * ) &pxLanguageStringDescriptor, pxRequest->usLength, sizeof(pxLanguageStringDescriptor), pdTRUE );
512                                         break;
513
514                                 case usbMANUFACTURER_STRING:
515                                         prvSendControlData( ( unsigned char * ) &pxManufacturerStringDescriptor, pxRequest->usLength, sizeof( pxManufacturerStringDescriptor ), pdTRUE );
516                                         break;
517
518                                 case usbPRODUCT_STRING:
519                                         prvSendControlData( ( unsigned char * ) &pxProductStringDescriptor, pxRequest->usLength, sizeof( pxProductStringDescriptor ), pdTRUE );
520                                         break;
521
522                                 case usbCONFIGURATION_STRING:
523                                         prvSendControlData( ( unsigned char * ) &pxConfigurationStringDescriptor, pxRequest->usLength, sizeof( pxConfigurationStringDescriptor ), pdTRUE );
524                                         break;
525
526                                 case usbINTERFACE_STRING:
527                                         prvSendControlData( ( unsigned char * ) &pxInterfaceStringDescriptor, pxRequest->usLength, sizeof( pxInterfaceStringDescriptor ), pdTRUE );
528                                         break;
529
530                                 default:
531                                         prvSendStall();
532                                         break;
533                         }
534                         break;
535
536                 default:
537                         prvSendStall();
538                         break;
539         }
540 }
541 /*------------------------------------------------------------*/
542
543 static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest )
544 {
545 unsigned short usStatus = 0;
546
547         switch( pxRequest->ucRequest )
548         {
549                 case usbGET_STATUS_REQUEST:
550                         /* Just send two byte dummy status. */
551                         prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
552                         break;
553
554                 case usbGET_DESCRIPTOR_REQUEST:
555                         /* Send device descriptor */
556                         prvGetStandardDeviceDescriptor( pxRequest );
557                         break;
558
559                 case usbGET_CONFIGURATION_REQUEST:
560                         /* Send selected device configuration */
561                         prvSendControlData( ( unsigned char * ) &ucUSBConfig, sizeof( ucUSBConfig ), sizeof( ucUSBConfig ), pdFALSE );
562                         break;
563
564                 case usbSET_FEATURE_REQUEST:
565                         prvSendZLP();
566                         break;
567
568                 case usbSET_ADDRESS_REQUEST:                    
569                         /* Get assigned address and send ack, but don't implement new address until we get a TXCOMP */
570                         prvSendZLP();                   
571                         eDriverState = eJUST_GOT_ADDRESS;                       
572                         ulReceivedAddress = ( unsigned long ) pxRequest->usValue;
573                         break;
574
575                 case usbSET_CONFIGURATION_REQUEST:
576                         /* Ack SET_CONFIGURATION request, but don't implement until TXCOMP */
577                         ucUSBConfig = ( unsigned char ) ( pxRequest->usValue & 0xff );
578                         eDriverState = eJUST_GOT_CONFIG;
579                         prvSendZLP();
580                         break;
581
582                 default:
583                         /* Any unsupported request results in a STALL response. */
584                         prvSendStall();
585                         break;
586         }
587 }
588 /*------------------------------------------------------------*/
589
590 static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest )
591 {
592         switch( pxRequest->ucRequest )
593         {
594                 case usbSEND_ENCAPSULATED_COMMAND:
595                         prvSendStall();
596                         break;
597
598                 case usbGET_ENCAPSULATED_RESPONSE:
599                         prvSendStall();
600                         break;
601
602                 case usbSET_LINE_CODING:
603                         /* Set line coding - baud rate, data bits, parity, stop bits */
604                         prvSendZLP();
605                         memcpy( ( void * ) pxLineCoding, pxControlRx.ucBuffer, sizeof( pxLineCoding ) );
606                         break;
607
608                 case usbGET_LINE_CODING:
609                         /* Get line coding */
610                         prvSendControlData( (unsigned char *) &pxLineCoding, pxRequest->usLength, sizeof( pxLineCoding ), pdFALSE );
611                         break;
612
613                 case usbSET_CONTROL_LINE_STATE:
614                         /* D0: 1=DTR, 0=No DTR,  D1: 1=Activate Carrier, 0=Deactivate carrier (RTS, half-duplex) */
615                         prvSendZLP();
616                         ucControlState = pxRequest->usValue;
617                         break;
618
619                 default:
620                         prvSendStall();
621                         break;
622         }
623 }
624 /*------------------------------------------------------------*/
625
626 static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest )
627 {
628         switch( ( pxRequest->usValue & ( unsigned short ) 0xff00 ) >> 8 )
629         {
630                 default:
631                         prvSendStall();
632                         break;
633         }
634 }
635 /*-----------------------------------------------------------*/
636
637 static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest )
638 {
639 unsigned short usStatus = 0;
640
641         switch( pxRequest->ucRequest )
642         {
643                 case usbGET_STATUS_REQUEST:
644                         /* Send dummy 2 bytes. */
645                         prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
646                         break;
647
648                 case usbGET_DESCRIPTOR_REQUEST:
649                         prvGetStandardInterfaceDescriptor( pxRequest ); 
650                         break;
651
652                 /* This minimal implementation does not respond to these. */
653                 case usbGET_INTERFACE_REQUEST:
654                 case usbSET_FEATURE_REQUEST:
655                 case usbSET_INTERFACE_REQUEST:  
656
657                 default:
658                         prvSendStall();
659                         break;
660         }
661 }
662 /*-----------------------------------------------------------*/
663
664 static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest )
665 {
666         switch( pxRequest->ucRequest )
667         {
668                 /* This minimal implementation does not expect to respond to these. */
669                 case usbGET_STATUS_REQUEST:
670                 case usbCLEAR_FEATURE_REQUEST: 
671                 case usbSET_FEATURE_REQUEST:
672
673                 default:                        
674                         prvSendStall();
675                         break;
676         }
677 }
678 /*-----------------------------------------------------------*/
679
680 static void vDetachUSBInterface( void)
681 {
682         /* Setup the PIO for the USB pull up resistor. */
683         AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
684         AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
685
686
687         /* Disable pull up */
688         AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
689
690 /*-----------------------------------------------------------*/
691
692 static void vInitUSBInterface( void )
693 {
694 extern void ( vUSB_ISR_Wrapper )( void );
695
696         /* Create the queue used to communicate between the USB ISR and task. */
697         xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );
698         
699         /* Create the queues used to hold Rx and Tx characters. */
700         xRxCDC = xQueueCreate( USB_CDC_QUEUE_SIZE, ( unsigned char ) sizeof( signed char ) );
701         xTxCDC = xQueueCreate( USB_CDC_QUEUE_SIZE + 1, ( unsigned char ) sizeof( signed char ) );
702
703         if( (!xUSBInterruptQueue) || (!xRxCDC) || (!xTxCDC) )
704         {       
705                 /* Not enough RAM to create queues!. */
706                 return;
707         }
708         
709         /* Initialise a few state variables. */
710         pxControlTx.ulNextCharIndex = ( unsigned long ) 0;
711         pxControlRx.ulNextCharIndex = ( unsigned long ) 0;
712         ucUSBConfig = ( unsigned char ) 0;
713         eDriverState = eNOTHING;
714         ucControlState = 0;
715         uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
716
717
718         /* HARDWARE SETUP */
719
720         /* Set the PLL USB Divider */
721         AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
722
723         /* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
724         AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
725         AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
726
727         /* Setup the PIO for the USB pull up resistor. */
728         AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
729         AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
730
731
732         /* Start without the pullup - this will get set at the end of this 
733         function. */
734         AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
735
736
737         /* When using the USB debugger the peripheral registers do not always get
738         set to the correct default values.  To make sure set the relevant registers
739         manually here. */
740         AT91C_BASE_UDP->UDP_IDR = ( unsigned long ) 0xffffffff;
741         AT91C_BASE_UDP->UDP_ICR = ( unsigned long ) 0xffffffff;
742         AT91C_BASE_UDP->UDP_CSR[ 0 ] = ( unsigned long ) 0x00;
743         AT91C_BASE_UDP->UDP_CSR[ 1 ] = ( unsigned long ) 0x00;
744         AT91C_BASE_UDP->UDP_CSR[ 2 ] = ( unsigned long ) 0x00;
745         AT91C_BASE_UDP->UDP_CSR[ 3 ] = ( unsigned long ) 0x00;
746         AT91C_BASE_UDP->UDP_GLBSTATE = 0;
747         AT91C_BASE_UDP->UDP_FADDR = 0;
748
749         /* Enable the transceiver. */
750         AT91C_UDP_TRANSCEIVER_ENABLE = 0;
751
752         /* Enable the USB interrupts - other interrupts get enabled as the 
753         enumeration process progresses. */
754         AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR_Wrapper );
755         AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;
756
757
758         /* Wait a short while before making our presence known. */
759         vTaskDelay( usbINIT_DELAY );
760         AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
761 }
762 /*-----------------------------------------------------------*/
763
764 static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthToSend, long lSendingDescriptor )
765 {
766         if( ( ( unsigned long ) usRequestedLength < ulLengthToSend ) )
767         {
768                 /* Cap the data length to that requested. */
769                 ulLengthToSend = ( unsigned short ) usRequestedLength;
770         }
771         else if( ( ulLengthToSend < ( unsigned long ) usRequestedLength ) && lSendingDescriptor )
772         {
773                 /* We are sending a descriptor.  If the descriptor is an exact 
774                 multiple of the FIFO length then it will have to be terminated
775                 with a NULL packet.  Set the state to indicate this if
776                 necessary. */
777                 if( ( ulLengthToSend % usbFIFO_LENGTH ) == 0 )
778                 {
779                         eDriverState = eSENDING_EVEN_DESCRIPTOR;
780                 }
781         }
782
783         /* Here we assume that the previous message has been sent.  THERE IS NO
784         BUFFER OVERFLOW PROTECTION HERE.
785
786         Copy the data to send into the buffer as we cannot send it all at once
787         (if it is greater than 8 bytes in length). */
788         memcpy( pxControlTx.ucBuffer, pucData, ulLengthToSend );
789
790         /* Reinitialise the buffer index so we start sending from the start of 
791         the data. */
792         pxControlTx.ulTotalDataLength = ulLengthToSend;
793         pxControlTx.ulNextCharIndex = ( unsigned long ) 0;
794
795         /* Send the first 8 bytes now.  The rest will get sent in response to 
796         TXCOMP interrupts. */
797         prvSendNextSegment();
798 }
799 /*-----------------------------------------------------------*/
800
801 static void prvSendNextSegment( void )
802 {
803 volatile unsigned long ulNextLength, ulStatus, ulLengthLeftToSend;
804
805         /* Is there any data to send? */
806         if( pxControlTx.ulTotalDataLength > pxControlTx.ulNextCharIndex )
807         {
808                 ulLengthLeftToSend = pxControlTx.ulTotalDataLength - pxControlTx.ulNextCharIndex;
809         
810                 /* We can only send 8 bytes to the fifo at a time. */
811                 if( ulLengthLeftToSend > usbFIFO_LENGTH )
812                 {
813                         ulNextLength = usbFIFO_LENGTH;
814                 }
815                 else
816                 {
817                         ulNextLength = ulLengthLeftToSend;
818                 }
819
820                 /* Wait until we can place data in the fifo.  THERE IS NO TIMEOUT
821                 HERE! */
822                 while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
823                 {
824                         vTaskDelay( usbSHORTEST_DELAY );
825                 }
826
827                 /* Write the data to the FIFO. */
828                 while( ulNextLength > ( unsigned long ) 0 )
829                 {
830                         AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ] = pxControlTx.ucBuffer[ pxControlTx.ulNextCharIndex ];
831         
832                         ulNextLength--;
833                         pxControlTx.ulNextCharIndex++;
834                 }
835         
836                 /* Start the transmission. */
837                 portENTER_CRITICAL();
838                 {
839                         ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
840                         usbCSR_SET_BIT( &ulStatus, ( ( unsigned long ) 0x10 ) );
841                         AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
842                 }
843                 portEXIT_CRITICAL();
844         }
845         else
846         {
847                 /* There is no data to send.  If we were sending a descriptor and the 
848                 descriptor was an exact multiple of the max packet size then we need
849                 to send a null to terminate the transmission. */
850                 if( eDriverState == eSENDING_EVEN_DESCRIPTOR )
851                 {
852                         prvSendZLP();
853                         eDriverState = eNOTHING;
854                 }
855         }
856 }
857
858