OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_Demo_Rowley_ARM7/] [USB/] [USB-CDC.c] - Blame information for rev 583

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.