Project

General

Profile

Download (28.1 KB) Statistics
| Branch: | Tag: | Revision:
1 633c646a henryk
/*
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 3ee3c4a6 henryk
#define CHUNK_SIZE 9
127 3639a49e henryk
128 633c646a henryk
/* 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 3639a49e henryk
  unsigned char chunk[CHUNK_SIZE]; 
148
  portBASE_TYPE i;
149 633c646a henryk
  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 3639a49e henryk
	      for (xByte = 0; xByte < 64-CHUNK_SIZE+1; xByte++)
193 633c646a henryk
		{
194 3639a49e henryk
		  if (!xQueueReceive (xTxCDC, &chunk, 0))
195 633c646a henryk
		    {
196
		      /* No data buffered to transmit. */
197
		      break;
198
		    }
199
200 3639a49e henryk
		  /* 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 633c646a henryk
		}
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 ad5b96d5 henryk
{
265
	vUSBSendByte_blocking(cByte, usbNO_BLOCK);
266
}
267
268
void
269
vUSBSendByte_blocking (portCHAR cByte, portTickType xTicksToWait)
270 633c646a henryk
{
271 3639a49e henryk
	char chunk[CHUNK_SIZE];
272
	chunk[0] = 1;
273
	chunk[1] = cByte;
274 633c646a henryk
  /* Queue the byte to be sent.  The USB task will send it. */
275 ad5b96d5 henryk
  xQueueSend (xTxCDC, &chunk, xTicksToWait);
276 3639a49e henryk
}
277
278
#define MIN(a,b) ((a)>(b)?(b):(a))
279
void
280 3ee3c4a6 henryk
vUSBSendBuffer_blocking (unsigned char *buffer, portBASE_TYPE offset, portBASE_TYPE length, portTickType xTicksToWait)
281 3639a49e henryk
{
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 3ee3c4a6 henryk
		xQueueSend (xTxCDC, &chunk, xTicksToWait);
289 3639a49e henryk
		length -= next_size;
290
		offset += next_size;
291
	}
292 633c646a henryk
}
293
294 3ee3c4a6 henryk
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 633c646a henryk
/*------------------------------------------------------------*/
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 3639a49e henryk
    xQueueCreate ( (USB_CDC_QUEUE_SIZE/CHUNK_SIZE) + 1,
825
		  (unsigned portCHAR) CHUNK_SIZE * sizeof (signed portCHAR));
826 633c646a henryk
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
}
Add picture from clipboard (Maximum size: 48.8 MB)