Project

General

Profile

Download (28.1 KB) Statistics
| Branch: | Tag: | Revision:
1
/*
2
	FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
3

    
4
	This file is part of the FreeRTOS.org distribution.
5

    
6
	FreeRTOS.org is free software; you can redistribute it and/or modify
7
	it under the terms of the GNU General Public License as published by
8
	the Free Software Foundation; either version 2 of the License, or
9
	(at your option) any later version.
10

    
11
	FreeRTOS.org is distributed in the hope that it will be useful,
12
	but WITHOUT ANY WARRANTY; without even the implied warranty of
13
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
	GNU General Public License for more details.
15

    
16
	You should have received a copy of the GNU General Public License
17
	along with FreeRTOS.org; if not, write to the Free Software
18
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19

    
20
	A special exception to the GPL can be applied should you wish to distribute
21
	a combined work that includes FreeRTOS.org, without being obliged to provide
22
	the source code for any proprietary components.  See the licensing section
23
	of http://www.FreeRTOS.org for full details of how and when the exception
24
	can be applied.
25

    
26
	***************************************************************************
27
	See http://www.FreeRTOS.org for documentation, latest information, license
28
	and contact details.  Please ensure to read the configuration and relevant
29
	port sections of the online documentation.
30

    
31
	Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
32
	with commercial development and support options.
33
	***************************************************************************
34
*/
35

    
36
/*
37
	USB Communications Device Class driver.
38
	Implements task vUSBCDCTask and provides an Abstract Control Model serial 
39
	interface.  Control is through endpoint 0, device-to-host notification is 
40
	provided by interrupt-in endpoint 3, and raw data is transferred through 
41
	bulk endpoints 1 and 2.
42

    
43
	- developed from original FreeRTOS HID example by Scott Miller
44
	- modified to support 3.2 GCC by najay
45
*/
46

    
47
/* Standard includes. */
48
#include <string.h>
49
#include <stdio.h>
50

    
51
/* Demo board includes. */
52
#include <board.h>
53

    
54
/* Scheduler includes. */
55
#include <FreeRTOS.h>
56
#include <task.h>
57
#include <queue.h>
58

    
59
/* Demo app includes. */
60
#include <USB-CDC.h>
61
#include <descriptors.h>
62

    
63
#define usbNO_BLOCK ( ( portTickType ) 0 )
64

    
65
/* Reset all endpoints */
66
static void prvResetEndPoints (void);
67

    
68
/* Clear pull up resistor to detach device from host */
69
static void vDetachUSBInterface (void);
70

    
71
/* Set up interface and initialize variables */
72
static void vInitUSBInterface (void);
73

    
74
/* Handle control endpoint events. */
75
static void prvProcessEndPoint0Interrupt (xISRStatus * pxMessage);
76

    
77
/* Handle standard device requests. */
78
static void prvHandleStandardDeviceRequest (xUSB_REQUEST * pxRequest);
79

    
80
/* Handle standard interface requests. */
81
static void prvHandleStandardInterfaceRequest (xUSB_REQUEST * pxRequest);
82

    
83
/* Handle endpoint requests. */
84
static void prvHandleStandardEndPointRequest (xUSB_REQUEST * pxRequest);
85

    
86
/* Handle class interface requests. */
87
static void prvHandleClassInterfaceRequest (xUSB_REQUEST * pxRequest);
88

    
89
/* Prepare control data transfer.  prvSendNextSegment starts transfer. */
90
static void prvSendControlData (unsigned portCHAR * pucData,
91
				unsigned portSHORT usRequestedLength,
92
				unsigned portLONG ulLengthLeftToSend,
93
				portLONG lSendingDescriptor);
94

    
95
/* Send next segment of data for the control transfer */
96
static void prvSendNextSegment (void);
97

    
98
/* Send stall - used to respond to unsupported requests */
99
static void prvSendStall (void);
100

    
101
/* Send a zero-length (null) packet */
102
static void prvSendZLP (void);
103

    
104
/* Handle requests for standard interface descriptors */
105
static void prvGetStandardInterfaceDescriptor (xUSB_REQUEST * pxRequest);
106

    
107
/*------------------------------------------------------------*/
108

    
109
/* File scope static variables */
110
static unsigned portCHAR ucUSBConfig = (unsigned portCHAR) 0;
111
static unsigned portLONG ulReceivedAddress = (unsigned portLONG) 0;
112
static eDRIVER_STATE eDriverState = eNOTHING;
113

    
114
/* Incoming and outgoing control data structures */
115
static xCONTROL_MESSAGE pxControlTx;
116
static xCONTROL_MESSAGE pxControlRx;
117

    
118
/* Queue holding pointers to pending messages */
119
xQueueHandle xUSBInterruptQueue;
120

    
121
/* Queues used to hold received characters, and characters waiting to be
122
transmitted.  Rx queue must be larger than FIFO size. */
123
static xQueueHandle xRxCDC;
124
static xQueueHandle xTxCDC;
125

    
126
#define CHUNK_SIZE 9
127

    
128
/* Line coding - 115,200 baud, N-8-1 */
129
static const unsigned portCHAR pxLineCoding[] =
130
  { 0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08 };
131

    
132
/* Status variables. */
133
static unsigned portCHAR ucControlState;
134
static unsigned int uiCurrentBank;
135

    
136

    
137
/*------------------------------------------------------------*/
138

    
139

    
140
void
141
vUSBCDCTask (void *pvParameters)
142
{
143
  xISRStatus *pxMessage;
144
  unsigned portLONG ulStatus;
145
  unsigned portLONG ulRxBytes;
146
  unsigned portCHAR ucByte;
147
  unsigned char chunk[CHUNK_SIZE]; 
148
  portBASE_TYPE i;
149
  portBASE_TYPE xByte;
150

    
151
  (void) pvParameters;
152

    
153
  /* Disconnect USB device from hub.  For debugging - causes host to register reset */
154
  portENTER_CRITICAL ();
155
  vDetachUSBInterface ();
156
  portEXIT_CRITICAL ();
157

    
158
  vTaskDelay (portTICK_RATE_MS * 60);
159

    
160
  /* Init USB interface */
161
  portENTER_CRITICAL ();
162
  vInitUSBInterface ();
163
  portEXIT_CRITICAL ();
164

    
165
  /* Main task loop.  Process incoming endpoint 0 interrupts, handle data transfers. */
166

    
167
  for (;;)
168
    {
169
      /* Look for data coming from the ISR. */
170
      if (xQueueReceive (xUSBInterruptQueue, &pxMessage, usbSHORTEST_DELAY))
171
	{
172
	  if (pxMessage->ulISR & AT91C_UDP_EPINT0)
173
	    {
174
	      /* All endpoint 0 interrupts are handled here. */
175
	      prvProcessEndPoint0Interrupt (pxMessage);
176
	    }
177

    
178
	  if (pxMessage->ulISR & AT91C_UDP_ENDBUSRES)
179
	    {
180
	      /* End of bus reset - reset the endpoints and de-configure. */
181
	      prvResetEndPoints ();
182
	    }
183
	}
184

    
185
      /* See if we're ready to send and receive data. */
186
      if (eDriverState == eREADY_TO_SEND && ucControlState)
187
	{
188
	  if ((!
189
	       (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] & AT91C_UDP_TXPKTRDY))
190
	      && uxQueueMessagesWaiting (xTxCDC))
191
	    {
192
	      for (xByte = 0; xByte < 64-CHUNK_SIZE+1; xByte++)
193
		{
194
		  if (!xQueueReceive (xTxCDC, &chunk, 0))
195
		    {
196
		      /* No data buffered to transmit. */
197
		      break;
198
		    }
199

    
200
		  /* Got a byte (or more) to transmit. */
201
		  for(i=0; i<chunk[0]; i++) {
202
			  AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_2] = chunk[1+i];
203
			  xByte++;
204
		  }
205
		}
206
	      AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] |= AT91C_UDP_TXPKTRDY;
207
	    }
208

    
209
	  /* Check for incoming data (host-to-device) on endpoint 1. */
210
	  while (AT91C_BASE_UDP->
211
		 UDP_CSR[usbEND_POINT_1] & (AT91C_UDP_RX_DATA_BK0 |
212
					    AT91C_UDP_RX_DATA_BK1))
213
	    {
214
	      ulRxBytes =
215
		(AT91C_BASE_UDP->
216
		 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 <
220
		  (USB_CDC_QUEUE_SIZE - uxQueueMessagesWaiting (xRxCDC)))
221
		{
222
		  while (ulRxBytes--)
223
		    {
224
		      ucByte = AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_1];
225
		      xQueueSend (xRxCDC, &ucByte, 0);
226
		    }
227

    
228
		  /* Release the FIFO */
229
		  portENTER_CRITICAL ();
230
		  {
231
		    ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1];
232
		    usbCSR_CLEAR_BIT (&ulStatus, uiCurrentBank);
233
		    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1] = ulStatus;
234
		  }
235
		  portEXIT_CRITICAL ();
236

    
237
		  /* Re-enable endpoint 1's interrupts */
238
		  AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
239

    
240
		  /* Update the current bank in use */
241
		  if (uiCurrentBank == AT91C_UDP_RX_DATA_BK0)
242
		    {
243
		      uiCurrentBank = AT91C_UDP_RX_DATA_BK1;
244
		    }
245
		  else
246
		    {
247
		      uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
248
		    }
249

    
250
		}
251
	      else
252
		{
253
		  break;
254
		}
255
	    }
256
	}
257
    }
258
}
259

    
260
/*------------------------------------------------------------*/
261

    
262
void
263
vUSBSendByte (portCHAR cByte)
264
{
265
	vUSBSendByte_blocking(cByte, usbNO_BLOCK);
266
}
267

    
268
void
269
vUSBSendByte_blocking (portCHAR cByte, portTickType xTicksToWait)
270
{
271
	char chunk[CHUNK_SIZE];
272
	chunk[0] = 1;
273
	chunk[1] = cByte;
274
  /* Queue the byte to be sent.  The USB task will send it. */
275
  xQueueSend (xTxCDC, &chunk, xTicksToWait);
276
}
277

    
278
#define MIN(a,b) ((a)>(b)?(b):(a))
279
void
280
vUSBSendBuffer_blocking (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length, portTickType xTicksToWait)
281
{
282
	unsigned char chunk[CHUNK_SIZE];
283
	while(length > 0) {
284
		int next_size = MIN(length, CHUNK_SIZE-1);
285
		chunk[0] = next_size;
286
		memcpy(chunk+1, buffer+offset, next_size);
287
		/* Queue the bytes to be sent.  The USB task will send it. */
288
		xQueueSend (xTxCDC, &chunk, xTicksToWait);
289
		length -= next_size;
290
		offset += next_size;
291
	}
292
}
293

    
294
void
295
vUSBSendBuffer (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length)
296
{
297
	vUSBSendBuffer_blocking(buffer, offset, length, usbNO_BLOCK);
298
}
299

    
300

    
301
/*------------------------------------------------------------*/
302

    
303
portLONG
304
vUSBRecvByte (portCHAR *cByte, portLONG size, portTickType xTicksToWait)
305
{
306
    portLONG res;
307
    if(size<=0 || !cByte || !xRxCDC)
308
        return 0;
309

    
310
    res=0;
311
    while(size-- && xQueueReceive(xRxCDC, cByte++, xTicksToWait))
312
        res++;
313

    
314
    return res;
315
}
316

    
317
/*------------------------------------------------------------*/
318

    
319
static void
320
prvSendZLP (void)
321
{
322
  unsigned portLONG ulStatus;
323

    
324
  /* Wait until the FIFO is free - even though we are not going to use it.
325
     THERE IS NO TIMEOUT HERE! */
326
  while (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_TXPKTRDY)
327
    {
328
      vTaskDelay (usbSHORTEST_DELAY);
329
    }
330

    
331
  portENTER_CRITICAL ();
332
  {
333
    /* Cancel any further pending data */
334
    pxControlTx.ulTotalDataLength = pxControlTx.ulNextCharIndex;
335

    
336
    /* Set the TXPKTRDY bit to cause a transmission with no data. */
337
    ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
338
    usbCSR_SET_BIT (&ulStatus, AT91C_UDP_TXPKTRDY);
339
    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulStatus;
340
  }
341
  portEXIT_CRITICAL ();
342
}
343

    
344
/*------------------------------------------------------------*/
345

    
346
static void
347
prvSendStall (void)
348
{
349
  unsigned portLONG ulStatus;
350

    
351
  portENTER_CRITICAL ();
352
  {
353
    /* Force a stall by simply setting the FORCESTALL bit in the CSR. */
354
    ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
355
    usbCSR_SET_BIT (&ulStatus, AT91C_UDP_FORCESTALL);
356
    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulStatus;
357
  }
358
  portEXIT_CRITICAL ();
359
}
360

    
361
/*------------------------------------------------------------*/
362

    
363
static void
364
prvResetEndPoints (void)
365
{
366
  unsigned portLONG ulTemp;
367

    
368
  eDriverState = eJUST_RESET;
369
  ucControlState = 0;
370

    
371
  /* Reset all the end points. */
372
  AT91C_BASE_UDP->UDP_RSTEP = usbEND_POINT_RESET_MASK;
373
  AT91C_BASE_UDP->UDP_RSTEP = (unsigned portLONG) 0x00;
374

    
375
  /* Enable data to be sent and received. */
376
  AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
377

    
378
  /* Repair the configuration end point. */
379
  portENTER_CRITICAL ();
380
  {
381
    ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
382
    usbCSR_SET_BIT (&ulTemp,
383
		    ((unsigned portLONG) (AT91C_UDP_EPEDS |
384
					  AT91C_UDP_EPTYPE_CTRL)));
385
    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulTemp;
386
    AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
387
  }
388
  portEXIT_CRITICAL ();
389
  uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
390
}
391

    
392
/*------------------------------------------------------------*/
393

    
394
static void
395
prvProcessEndPoint0Interrupt (xISRStatus * pxMessage)
396
{
397
  static xUSB_REQUEST xRequest;
398
  unsigned portLONG ulRxBytes;
399

    
400
  /* Get number of bytes received, if any */
401
  ulRxBytes = pxMessage->ulCSR0 >> 16;
402
  ulRxBytes &= usbRX_COUNT_MASK;
403

    
404
  if (pxMessage->ulCSR0 & AT91C_UDP_TXCOMP)
405
    {
406
      /* We received a TX complete interrupt.  What we do depends on
407
         what we sent to get this interrupt. */
408

    
409
      if (eDriverState == eJUST_GOT_CONFIG)
410
	{
411
	  /* We sent an acknowledgement of a SET_CONFIG request.  We
412
	     are now at the end of the enumeration.
413

    
414
	     TODO: Config 0 sets unconfigured state, should enter Address state.
415
	     Request for unsupported config should stall. */
416
	  AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
417

    
418
	  /* Set up endpoints */
419
	  portENTER_CRITICAL ();
420
	  {
421
	    unsigned portLONG ulTemp;
422

    
423
	    /* Set endpoint 1 to bulk-out */
424
	    ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1];
425
	    usbCSR_SET_BIT (&ulTemp,
426
			    AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
427
	    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1] = ulTemp;
428
	    AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
429
	    /* Set endpoint 2 to bulk-in */
430
	    ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2];
431
	    usbCSR_SET_BIT (&ulTemp,
432
			    AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
433
	    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] = ulTemp;
434
	    AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT2;
435
	    /* Set endpoint 3 to interrupt-in, enable it, and enable interrupts */
436
	    ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_3];
437
	    usbCSR_SET_BIT (&ulTemp,
438
			    AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
439
	    AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_3] = ulTemp;
440
	    /*AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT3 );                                */
441
	  }
442
	  portEXIT_CRITICAL ();
443

    
444
	  eDriverState = eREADY_TO_SEND;
445
	}
446
      else if (eDriverState == eJUST_GOT_ADDRESS)
447
	{
448
	  /* We sent an acknowledgement of a SET_ADDRESS request.  Move
449
	     to the addressed state. */
450
	  if (ulReceivedAddress != (unsigned portLONG) 0)
451
	    {
452
	      AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
453
	    }
454
	  else
455
	    {
456
	      AT91C_BASE_UDP->UDP_GLBSTATE = 0;
457
	    }
458

    
459
	  AT91C_BASE_UDP->UDP_FADDR = (AT91C_UDP_FEN | ulReceivedAddress);
460
	  eDriverState = eNOTHING;
461
	}
462
      else
463
	{
464
	  /* The TXCOMP was not for any special type of transmission.  See
465
	     if there is any more data to send. */
466
	  prvSendNextSegment ();
467
	}
468
    }
469

    
470
  if (pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0)
471
    {
472
      /* Received a control data packet.  May be a 0-length ACK or a data stage. */
473
      unsigned portCHAR ucBytesToGet;
474

    
475
      /* Got data.  Cancel any outgoing data. */
476
      pxControlTx.ulNextCharIndex = pxControlTx.ulTotalDataLength;
477

    
478
      /* Determine how many bytes we need to receive. */
479
      ucBytesToGet =
480
	pxControlRx.ulTotalDataLength - pxControlRx.ulNextCharIndex;
481
      if (ucBytesToGet > ulRxBytes)
482
	{
483
	  ucBytesToGet = ulRxBytes;
484
	}
485

    
486
      /* If we're not expecting any data, it's an ack - just quit now. */
487
      if (!ucBytesToGet)
488
	{
489
	  return;
490
	}
491

    
492
      /* Get the required data and update the index. */
493
      memcpy (pxControlRx.ucBuffer, pxMessage->ucFifoData, ucBytesToGet);
494
      pxControlRx.ulNextCharIndex += ucBytesToGet;
495
    }
496

    
497
  if (pxMessage->ulCSR0 & AT91C_UDP_RXSETUP)
498
    {
499
      /* Received a SETUP packet.  May be followed by data packets. */
500

    
501
      if (ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES)
502
	{
503
	  /* Create an xUSB_REQUEST variable from the raw bytes array. */
504

    
505
	  xRequest.ucReqType = pxMessage->ucFifoData[usbREQUEST_TYPE_INDEX];
506
	  xRequest.ucRequest = pxMessage->ucFifoData[usbREQUEST_INDEX];
507

    
508
	  xRequest.usValue = pxMessage->ucFifoData[usbVALUE_HIGH_BYTE];
509
	  xRequest.usValue <<= 8;
510
	  xRequest.usValue |= pxMessage->ucFifoData[usbVALUE_LOW_BYTE];
511

    
512
	  xRequest.usIndex = pxMessage->ucFifoData[usbINDEX_HIGH_BYTE];
513
	  xRequest.usIndex <<= 8;
514
	  xRequest.usIndex |= pxMessage->ucFifoData[usbINDEX_LOW_BYTE];
515

    
516
	  xRequest.usLength = pxMessage->ucFifoData[usbLENGTH_HIGH_BYTE];
517
	  xRequest.usLength <<= 8;
518
	  xRequest.usLength |= pxMessage->ucFifoData[usbLENGTH_LOW_BYTE];
519

    
520
	  pxControlRx.ulNextCharIndex = 0;
521
	  if (!(xRequest.ucReqType & 0x80))	/* Host-to-Device transfer, may need to get data first */
522
	    {
523
	      if (xRequest.usLength > usbMAX_CONTROL_MESSAGE_SIZE)
524
		{
525
		  /* Too big!  No space for control data, stall and abort. */
526
		  prvSendStall ();
527
		  return;
528
		}
529

    
530
	      pxControlRx.ulTotalDataLength = xRequest.usLength;
531
	    }
532
	  else
533
	    {
534
	      /* We're sending the data, don't wait for any. */
535
	      pxControlRx.ulTotalDataLength = 0;
536
	    }
537
	}
538
    }
539

    
540
  /* See if we've got a pending request and all its associated data ready */
541
  if ((pxMessage->ulCSR0 & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP))
542
      && (pxControlRx.ulNextCharIndex >= pxControlRx.ulTotalDataLength))
543
    {
544
      unsigned portCHAR ucRequest;
545

    
546
      /* Manipulate the ucRequestType and the ucRequest parameters to 
547
         generate a zero based request selection.  This is just done to 
548
         break up the requests into subsections for clarity.  The 
549
         alternative would be to have more huge switch statement that would
550
         be difficult to optimise. */
551
      ucRequest = ((xRequest.ucReqType & 0x60) >> 3);
552
      ucRequest |= (xRequest.ucReqType & 0x03);
553

    
554
      switch (ucRequest)
555
	{
556
	case usbSTANDARD_DEVICE_REQUEST:
557
	  /* Standard Device request */
558
	  prvHandleStandardDeviceRequest (&xRequest);
559
	  break;
560

    
561
	case usbSTANDARD_INTERFACE_REQUEST:
562
	  /* Standard Interface request */
563
	  prvHandleStandardInterfaceRequest (&xRequest);
564
	  break;
565

    
566
	case usbSTANDARD_END_POINT_REQUEST:
567
	  /* Standard Endpoint request */
568
	  prvHandleStandardEndPointRequest (&xRequest);
569
	  break;
570

    
571
	case usbCLASS_INTERFACE_REQUEST:
572
	  /* Class Interface request */
573
	  prvHandleClassInterfaceRequest (&xRequest);
574
	  break;
575

    
576
	default:		/* This is not something we want to respond to. */
577
	  prvSendStall ();
578
	}
579
    }
580
}
581

    
582
/*------------------------------------------------------------*/
583

    
584
static void
585
prvGetStandardDeviceDescriptor (xUSB_REQUEST * pxRequest)
586
{
587
  /* The type is in the high byte.  Return whatever has been requested. */
588
  switch ((pxRequest->usValue & 0xff00) >> 8)
589
    {
590
    case usbDESCRIPTOR_TYPE_DEVICE:
591
      prvSendControlData ((unsigned portCHAR *) &pxDeviceDescriptor,
592
			  pxRequest->usLength, sizeof (pxDeviceDescriptor),
593
			  pdTRUE);
594
      break;
595

    
596
    case usbDESCRIPTOR_TYPE_CONFIGURATION:
597
      prvSendControlData ((unsigned portCHAR *) &(pxConfigDescriptor),
598
			  pxRequest->usLength, sizeof (pxConfigDescriptor),
599
			  pdTRUE);
600
      break;
601

    
602
    case usbDESCRIPTOR_TYPE_STRING:
603

    
604
      /* The index to the string descriptor is the lower byte. */
605
      switch (pxRequest->usValue & 0xff)
606
	{
607
	case usbLANGUAGE_STRING:
608
	  prvSendControlData ((unsigned portCHAR *)
609
			      &pxLanguageStringDescriptor,
610
			      pxRequest->usLength,
611
			      sizeof (pxLanguageStringDescriptor), pdTRUE);
612
	  break;
613

    
614
	case usbMANUFACTURER_STRING:
615
	  prvSendControlData ((unsigned portCHAR *)
616
			      &pxManufacturerStringDescriptor,
617
			      pxRequest->usLength,
618
			      sizeof (pxManufacturerStringDescriptor),
619
			      pdTRUE);
620
	  break;
621

    
622
	case usbPRODUCT_STRING:
623
	  prvSendControlData ((unsigned portCHAR *)
624
			      &pxProductStringDescriptor, pxRequest->usLength,
625
			      sizeof (pxProductStringDescriptor), pdTRUE);
626
	  break;
627

    
628
	default:
629
	  prvSendStall ();
630
	  break;
631
	}
632
      break;
633

    
634
    default:
635
      prvSendStall ();
636
      break;
637
    }
638
}
639

    
640
/*------------------------------------------------------------*/
641

    
642
static void
643
prvHandleStandardDeviceRequest (xUSB_REQUEST * pxRequest)
644
{
645
  unsigned portSHORT usStatus = 0;
646

    
647
  switch (pxRequest->ucRequest)
648
    {
649
    case usbGET_STATUS_REQUEST:
650
      /* Just send two byte dummy status. */
651
      prvSendControlData ((unsigned portCHAR *) &usStatus, sizeof (usStatus),
652
			  sizeof (usStatus), pdFALSE);
653
      break;
654

    
655
    case usbGET_DESCRIPTOR_REQUEST:
656
      /* Send device descriptor */
657
      prvGetStandardDeviceDescriptor (pxRequest);
658
      break;
659

    
660
    case usbGET_CONFIGURATION_REQUEST:
661
      /* Send selected device configuration */
662
      prvSendControlData ((unsigned portCHAR *) &ucUSBConfig,
663
			  sizeof (ucUSBConfig), sizeof (ucUSBConfig),
664
			  pdFALSE);
665
      break;
666

    
667
    case usbSET_FEATURE_REQUEST:
668
      prvSendZLP ();
669
      break;
670

    
671
    case usbSET_ADDRESS_REQUEST:
672
      /* Get assigned address and send ack, but don't implement new address until we get a TXCOMP */
673
      prvSendZLP ();
674
      eDriverState = eJUST_GOT_ADDRESS;
675
      ulReceivedAddress = (unsigned portLONG) pxRequest->usValue;
676
      break;
677

    
678
    case usbSET_CONFIGURATION_REQUEST:
679
      /* Ack SET_CONFIGURATION request, but don't implement until TXCOMP */
680
      ucUSBConfig = (unsigned portCHAR) (pxRequest->usValue & 0xff);
681
      eDriverState = eJUST_GOT_CONFIG;
682
      prvSendZLP ();
683
      break;
684

    
685
    default:
686
      /* Any unsupported request results in a STALL response. */
687
      prvSendStall ();
688
      break;
689
    }
690
}
691

    
692
/*------------------------------------------------------------*/
693

    
694
static void
695
prvHandleClassInterfaceRequest (xUSB_REQUEST * pxRequest)
696
{
697
  switch (pxRequest->ucRequest)
698
    {
699
    case usbSEND_ENCAPSULATED_COMMAND:
700
      prvSendStall ();
701
      break;
702

    
703
    case usbGET_ENCAPSULATED_RESPONSE:
704
      prvSendStall ();
705
      break;
706

    
707
    case usbSET_LINE_CODING:
708
      /* Set line coding - baud rate, data bits, parity, stop bits */
709
      prvSendZLP ();
710
      memcpy ((void *) pxLineCoding, pxControlRx.ucBuffer,
711
	      sizeof (pxLineCoding));
712
      break;
713

    
714
    case usbGET_LINE_CODING:
715
      /* Get line coding */
716
      prvSendControlData ((unsigned portCHAR *) &pxLineCoding,
717
			  pxRequest->usLength, sizeof (pxLineCoding),
718
			  pdFALSE);
719
      break;
720

    
721
    case usbSET_CONTROL_LINE_STATE:
722
      /* D0: 1=DTR, 0=No DTR,  D1: 1=Activate Carrier, 0=Deactivate carrier (RTS, half-duplex) */
723
      prvSendZLP ();
724
      ucControlState = pxRequest->usValue;
725
      break;
726

    
727
    default:
728
      prvSendStall ();
729
      break;
730
    }
731
}
732

    
733
/*------------------------------------------------------------*/
734

    
735
static void
736
prvGetStandardInterfaceDescriptor (xUSB_REQUEST * pxRequest)
737
{
738
  switch ((pxRequest->usValue & (unsigned portSHORT) 0xff00) >> 8)
739
    {
740
    default:
741
      prvSendStall ();
742
      break;
743
    }
744
}
745

    
746
/*-----------------------------------------------------------*/
747

    
748
static void
749
prvHandleStandardInterfaceRequest (xUSB_REQUEST * pxRequest)
750
{
751
  unsigned portSHORT usStatus = 0;
752

    
753
  switch (pxRequest->ucRequest)
754
    {
755
    case usbGET_STATUS_REQUEST:
756
      /* Send dummy 2 bytes. */
757
      prvSendControlData ((unsigned portCHAR *) &usStatus, sizeof (usStatus),
758
			  sizeof (usStatus), pdFALSE);
759
      break;
760

    
761
    case usbGET_DESCRIPTOR_REQUEST:
762
      prvGetStandardInterfaceDescriptor (pxRequest);
763
      break;
764

    
765
      /* This minimal implementation does not respond to these. */
766
    case usbGET_INTERFACE_REQUEST:
767
    case usbSET_FEATURE_REQUEST:
768
    case usbSET_INTERFACE_REQUEST:
769

    
770
    default:
771
      prvSendStall ();
772
      break;
773
    }
774
}
775

    
776
/*-----------------------------------------------------------*/
777

    
778
static void
779
prvHandleStandardEndPointRequest (xUSB_REQUEST * pxRequest)
780
{
781
  switch (pxRequest->ucRequest)
782
    {
783
      /* This minimal implementation does not expect to respond to these. */
784
    case usbGET_STATUS_REQUEST:
785
    case usbCLEAR_FEATURE_REQUEST:
786
    case usbSET_FEATURE_REQUEST:
787

    
788
    default:
789
      prvSendStall ();
790
      break;
791
    }
792
}
793

    
794
/*-----------------------------------------------------------*/
795

    
796
static void
797
vDetachUSBInterface (void)
798
{
799
  /* Setup the PIO for the USB pull up resistor. */
800
  AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
801
  AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
802

    
803

    
804
  /* Disable pull up */
805
  AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
806
}
807

    
808
/*-----------------------------------------------------------*/
809

    
810
static void
811
vInitUSBInterface (void)
812
{
813
  extern void (vUSB_ISR) (void);
814

    
815
  /* Create the queue used to communicate between the USB ISR and task. */
816
  xUSBInterruptQueue =
817
    xQueueCreate (usbQUEUE_LENGTH + 1, sizeof (xISRStatus *));
818

    
819
  /* Create the queues used to hold Rx and Tx characters. */
820
  xRxCDC =
821
    xQueueCreate (USB_CDC_QUEUE_SIZE,
822
		  (unsigned portCHAR) sizeof (signed portCHAR));
823
  xTxCDC =
824
    xQueueCreate ( (USB_CDC_QUEUE_SIZE/CHUNK_SIZE) + 1,
825
		  (unsigned portCHAR) CHUNK_SIZE * sizeof (signed portCHAR));
826

    
827
  if ((!xUSBInterruptQueue) || (!xRxCDC) || (!xTxCDC))
828
    {
829
      /* Not enough RAM to create queues!. */
830
      return;
831
    }
832

    
833
  /* Initialise a few state variables. */
834
  pxControlTx.ulNextCharIndex = (unsigned portLONG) 0;
835
  pxControlRx.ulNextCharIndex = (unsigned portLONG) 0;
836
  ucUSBConfig = (unsigned portCHAR) 0;
837
  eDriverState = eNOTHING;
838
  ucControlState = 0;
839
  uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
840

    
841

    
842
  /* HARDWARE SETUP */
843

    
844
  /* Set the PLL USB Divider */
845
  AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
846

    
847
  /* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
848
  AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
849
  AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
850

    
851
  /* Setup the PIO for the USB pull up resistor. */
852
  AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
853
  AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
854

    
855

    
856
  /* Start without the pullup - this will get set at the end of this 
857
     function. */
858
  AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
859

    
860

    
861
  /* When using the USB debugger the peripheral registers do not always get
862
     set to the correct default values.  To make sure set the relevant registers
863
     manually here. */
864
  AT91C_BASE_UDP->UDP_IDR = (unsigned portLONG) 0xffffffff;
865
  AT91C_BASE_UDP->UDP_ICR = (unsigned portLONG) 0xffffffff;
866
  AT91C_BASE_UDP->UDP_CSR[0] = (unsigned portLONG) 0x00;
867
  AT91C_BASE_UDP->UDP_CSR[1] = (unsigned portLONG) 0x00;
868
  AT91C_BASE_UDP->UDP_CSR[2] = (unsigned portLONG) 0x00;
869
  AT91C_BASE_UDP->UDP_CSR[3] = (unsigned portLONG) 0x00;
870
  AT91C_BASE_UDP->UDP_GLBSTATE = 0;
871
  AT91C_BASE_UDP->UDP_FADDR = 0;
872

    
873
  /* Enable the transceiver. */
874
  AT91C_UDP_TRANSCEIVER_ENABLE = 0;
875

    
876
  /* Enable the USB interrupts - other interrupts get enabled as the 
877
     enumeration process progresses. */
878
  AT91F_AIC_ConfigureIt (AT91C_ID_UDP, usbINTERRUPT_PRIORITY,
879
			 AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
880
			 (void (*)(void)) vUSB_ISR);
881
  AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;
882

    
883

    
884
  /* Wait a short while before making our presence known. */
885
  vTaskDelay (usbINIT_DELAY);
886
  AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
887
}
888

    
889
/*-----------------------------------------------------------*/
890

    
891
static void
892
prvSendControlData (unsigned portCHAR * pucData,
893
		    unsigned portSHORT usRequestedLength,
894
		    unsigned portLONG ulLengthToSend,
895
		    portLONG lSendingDescriptor)
896
{
897
  if (((unsigned portLONG) usRequestedLength < ulLengthToSend))
898
    {
899
      /* Cap the data length to that requested. */
900
      ulLengthToSend = (unsigned portSHORT) usRequestedLength;
901
    }
902
  else if ((ulLengthToSend < (unsigned portLONG) usRequestedLength)
903
	   && lSendingDescriptor)
904
    {
905
      /* We are sending a descriptor.  If the descriptor is an exact 
906
         multiple of the FIFO length then it will have to be terminated
907
         with a NULL packet.  Set the state to indicate this if
908
         necessary. */
909
      if ((ulLengthToSend % usbFIFO_LENGTH) == 0)
910
	{
911
	  eDriverState = eSENDING_EVEN_DESCRIPTOR;
912
	}
913
    }
914

    
915
  /* Here we assume that the previous message has been sent.  THERE IS NO
916
     BUFFER OVERFLOW PROTECTION HERE.
917

    
918
     Copy the data to send into the buffer as we cannot send it all at once
919
     (if it is greater than 8 bytes in length). */
920
  memcpy (pxControlTx.ucBuffer, pucData, ulLengthToSend);
921

    
922
  /* Reinitialise the buffer index so we start sending from the start of 
923
     the data. */
924
  pxControlTx.ulTotalDataLength = ulLengthToSend;
925
  pxControlTx.ulNextCharIndex = (unsigned portLONG) 0;
926

    
927
  /* Send the first 8 bytes now.  The rest will get sent in response to 
928
     TXCOMP interrupts. */
929
  prvSendNextSegment ();
930
}
931

    
932
/*-----------------------------------------------------------*/
933

    
934
static void
935
prvSendNextSegment (void)
936
{
937
  volatile unsigned portLONG ulNextLength, ulStatus, ulLengthLeftToSend;
938

    
939
  /* Is there any data to send? */
940
  if (pxControlTx.ulTotalDataLength > pxControlTx.ulNextCharIndex)
941
    {
942
      ulLengthLeftToSend =
943
	pxControlTx.ulTotalDataLength - pxControlTx.ulNextCharIndex;
944

    
945
      /* We can only send 8 bytes to the fifo at a time. */
946
      if (ulLengthLeftToSend > usbFIFO_LENGTH)
947
	{
948
	  ulNextLength = usbFIFO_LENGTH;
949
	}
950
      else
951
	{
952
	  ulNextLength = ulLengthLeftToSend;
953
	}
954

    
955
      /* Wait until we can place data in the fifo.  THERE IS NO TIMEOUT
956
         HERE! */
957
      while (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_TXPKTRDY)
958
	{
959
	  vTaskDelay (usbSHORTEST_DELAY);
960
	}
961

    
962
      /* Write the data to the FIFO. */
963
      while (ulNextLength > (unsigned portLONG) 0)
964
	{
965
	  AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_0] =
966
	    pxControlTx.ucBuffer[pxControlTx.ulNextCharIndex];
967

    
968
	  ulNextLength--;
969
	  pxControlTx.ulNextCharIndex++;
970
	}
971

    
972
      /* Start the transmission. */
973
      portENTER_CRITICAL ();
974
      {
975
	ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
976
	usbCSR_SET_BIT (&ulStatus, ((unsigned portLONG) 0x10));
977
	AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulStatus;
978
      }
979
      portEXIT_CRITICAL ();
980
    }
981
  else
982
    {
983
      /* There is no data to send.  If we were sending a descriptor and the 
984
         descriptor was an exact multiple of the max packet size then we need
985
         to send a null to terminate the transmission. */
986
      if (eDriverState == eSENDING_EVEN_DESCRIPTOR)
987
	{
988
	  prvSendZLP ();
989
	  eDriverState = eNOTHING;
990
	}
991
    }
992
}
(1-1/5)
Add picture from clipboard (Maximum size: 48.8 MB)