summaryrefslogtreecommitdiff
path: root/openpicc/os/usb
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/os/usb')
-rw-r--r--openpicc/os/usb/USB-CDC.c953
-rw-r--r--openpicc/os/usb/USB-CDC.h87
-rw-r--r--openpicc/os/usb/USBIsr.c169
-rw-r--r--openpicc/os/usb/descriptors.h190
-rw-r--r--openpicc/os/usb/usb.h146
5 files changed, 1545 insertions, 0 deletions
diff --git a/openpicc/os/usb/USB-CDC.c b/openpicc/os/usb/USB-CDC.c
new file mode 100644
index 0000000..4496c55
--- /dev/null
+++ b/openpicc/os/usb/USB-CDC.c
@@ -0,0 +1,953 @@
+/*
+ FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ See http://www.FreeRTOS.org for documentation, latest information, license
+ and contact details. Please ensure to read the configuration and relevant
+ port sections of the online documentation.
+
+ Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
+ with commercial development and support options.
+ ***************************************************************************
+*/
+
+/*
+ USB Communications Device Class driver.
+ Implements task vUSBCDCTask and provides an Abstract Control Model serial
+ interface. Control is through endpoint 0, device-to-host notification is
+ provided by interrupt-in endpoint 3, and raw data is transferred through
+ bulk endpoints 1 and 2.
+
+ - developed from original FreeRTOS HID example by Scott Miller
+ - modified to support 3.2 GCC by najay
+*/
+
+/* Standard includes. */
+#include <string.h>
+#include <stdio.h>
+
+/* Demo board includes. */
+#include <board.h>
+
+/* Scheduler includes. */
+#include <FreeRTOS.h>
+#include <task.h>
+#include <queue.h>
+
+/* Demo app includes. */
+#include <USB-CDC.h>
+#include <descriptors.h>
+
+#define usbNO_BLOCK ( ( portTickType ) 0 )
+
+/* Reset all endpoints */
+static void prvResetEndPoints (void);
+
+/* Clear pull up resistor to detach device from host */
+static void vDetachUSBInterface (void);
+
+/* Set up interface and initialize variables */
+static void vInitUSBInterface (void);
+
+/* Handle control endpoint events. */
+static void prvProcessEndPoint0Interrupt (xISRStatus * pxMessage);
+
+/* Handle standard device requests. */
+static void prvHandleStandardDeviceRequest (xUSB_REQUEST * pxRequest);
+
+/* Handle standard interface requests. */
+static void prvHandleStandardInterfaceRequest (xUSB_REQUEST * pxRequest);
+
+/* Handle endpoint requests. */
+static void prvHandleStandardEndPointRequest (xUSB_REQUEST * pxRequest);
+
+/* Handle class interface requests. */
+static void prvHandleClassInterfaceRequest (xUSB_REQUEST * pxRequest);
+
+/* Prepare control data transfer. prvSendNextSegment starts transfer. */
+static void prvSendControlData (unsigned portCHAR * pucData,
+ unsigned portSHORT usRequestedLength,
+ unsigned portLONG ulLengthLeftToSend,
+ portLONG lSendingDescriptor);
+
+/* Send next segment of data for the control transfer */
+static void prvSendNextSegment (void);
+
+/* Send stall - used to respond to unsupported requests */
+static void prvSendStall (void);
+
+/* Send a zero-length (null) packet */
+static void prvSendZLP (void);
+
+/* Handle requests for standard interface descriptors */
+static void prvGetStandardInterfaceDescriptor (xUSB_REQUEST * pxRequest);
+
+/*------------------------------------------------------------*/
+
+/* File scope static variables */
+static unsigned portCHAR ucUSBConfig = (unsigned portCHAR) 0;
+static unsigned portLONG ulReceivedAddress = (unsigned portLONG) 0;
+static eDRIVER_STATE eDriverState = eNOTHING;
+
+/* Incoming and outgoing control data structures */
+static xCONTROL_MESSAGE pxControlTx;
+static xCONTROL_MESSAGE pxControlRx;
+
+/* Queue holding pointers to pending messages */
+xQueueHandle xUSBInterruptQueue;
+
+/* Queues used to hold received characters, and characters waiting to be
+transmitted. Rx queue must be larger than FIFO size. */
+static xQueueHandle xRxCDC;
+static xQueueHandle xTxCDC;
+
+/* Line coding - 115,200 baud, N-8-1 */
+static const unsigned portCHAR pxLineCoding[] =
+ { 0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08 };
+
+/* Status variables. */
+static unsigned portCHAR ucControlState;
+static unsigned int uiCurrentBank;
+
+
+/*------------------------------------------------------------*/
+
+
+void
+vUSBCDCTask (void *pvParameters)
+{
+ xISRStatus *pxMessage;
+ unsigned portLONG ulStatus;
+ unsigned portLONG ulRxBytes;
+ unsigned portCHAR ucByte;
+ portBASE_TYPE xByte;
+
+ (void) pvParameters;
+
+ /* Disconnect USB device from hub. For debugging - causes host to register reset */
+ portENTER_CRITICAL ();
+ vDetachUSBInterface ();
+ portEXIT_CRITICAL ();
+
+ vTaskDelay (portTICK_RATE_MS * 60);
+
+ /* Init USB interface */
+ portENTER_CRITICAL ();
+ vInitUSBInterface ();
+ portEXIT_CRITICAL ();
+
+ /* Main task loop. Process incoming endpoint 0 interrupts, handle data transfers. */
+
+ for (;;)
+ {
+ /* Look for data coming from the ISR. */
+ if (xQueueReceive (xUSBInterruptQueue, &pxMessage, usbSHORTEST_DELAY))
+ {
+ if (pxMessage->ulISR & AT91C_UDP_EPINT0)
+ {
+ /* All endpoint 0 interrupts are handled here. */
+ prvProcessEndPoint0Interrupt (pxMessage);
+ }
+
+ if (pxMessage->ulISR & AT91C_UDP_ENDBUSRES)
+ {
+ /* End of bus reset - reset the endpoints and de-configure. */
+ prvResetEndPoints ();
+ }
+ }
+
+ /* See if we're ready to send and receive data. */
+ if (eDriverState == eREADY_TO_SEND && ucControlState)
+ {
+ if ((!
+ (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] & AT91C_UDP_TXPKTRDY))
+ && uxQueueMessagesWaiting (xTxCDC))
+ {
+ for (xByte = 0; xByte < 64; xByte++)
+ {
+ if (!xQueueReceive (xTxCDC, &ucByte, 0))
+ {
+ /* No data buffered to transmit. */
+ break;
+ }
+
+ /* Got a byte to transmit. */
+ AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_2] = ucByte;
+ }
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] |= AT91C_UDP_TXPKTRDY;
+ }
+
+ /* Check for incoming data (host-to-device) on endpoint 1. */
+ while (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_1] & (AT91C_UDP_RX_DATA_BK0 |
+ AT91C_UDP_RX_DATA_BK1))
+ {
+ ulRxBytes =
+ (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_1] >> 16) & usbRX_COUNT_MASK;
+
+ /* Only process FIFO if there's room to store it in the queue */
+ if (ulRxBytes <
+ (USB_CDC_QUEUE_SIZE - uxQueueMessagesWaiting (xRxCDC)))
+ {
+ while (ulRxBytes--)
+ {
+ ucByte = AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_1];
+ xQueueSend (xRxCDC, &ucByte, 0);
+ }
+
+ /* Release the FIFO */
+ portENTER_CRITICAL ();
+ {
+ ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1];
+ usbCSR_CLEAR_BIT (&ulStatus, uiCurrentBank);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1] = ulStatus;
+ }
+ portEXIT_CRITICAL ();
+
+ /* Re-enable endpoint 1's interrupts */
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
+
+ /* Update the current bank in use */
+ if (uiCurrentBank == AT91C_UDP_RX_DATA_BK0)
+ {
+ uiCurrentBank = AT91C_UDP_RX_DATA_BK1;
+ }
+ else
+ {
+ uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
+ }
+
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------*/
+
+void
+vUSBSendByte (portCHAR cByte)
+{
+ /* Queue the byte to be sent. The USB task will send it. */
+ xQueueSend (xTxCDC, &cByte, usbNO_BLOCK);
+}
+
+/*------------------------------------------------------------*/
+
+portLONG
+vUSBRecvByte (portCHAR *cByte, portLONG size, portTickType xTicksToWait)
+{
+ portLONG res;
+ if(size<=0 || !cByte || !xRxCDC)
+ return 0;
+
+ res=0;
+ while(size-- && xQueueReceive(xRxCDC, cByte++, xTicksToWait))
+ res++;
+
+ return res;
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvSendZLP (void)
+{
+ unsigned portLONG ulStatus;
+
+ /* Wait until the FIFO is free - even though we are not going to use it.
+ THERE IS NO TIMEOUT HERE! */
+ while (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_TXPKTRDY)
+ {
+ vTaskDelay (usbSHORTEST_DELAY);
+ }
+
+ portENTER_CRITICAL ();
+ {
+ /* Cancel any further pending data */
+ pxControlTx.ulTotalDataLength = pxControlTx.ulNextCharIndex;
+
+ /* Set the TXPKTRDY bit to cause a transmission with no data. */
+ ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
+ usbCSR_SET_BIT (&ulStatus, AT91C_UDP_TXPKTRDY);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulStatus;
+ }
+ portEXIT_CRITICAL ();
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvSendStall (void)
+{
+ unsigned portLONG ulStatus;
+
+ portENTER_CRITICAL ();
+ {
+ /* Force a stall by simply setting the FORCESTALL bit in the CSR. */
+ ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
+ usbCSR_SET_BIT (&ulStatus, AT91C_UDP_FORCESTALL);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulStatus;
+ }
+ portEXIT_CRITICAL ();
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvResetEndPoints (void)
+{
+ unsigned portLONG ulTemp;
+
+ eDriverState = eJUST_RESET;
+ ucControlState = 0;
+
+ /* Reset all the end points. */
+ AT91C_BASE_UDP->UDP_RSTEP = usbEND_POINT_RESET_MASK;
+ AT91C_BASE_UDP->UDP_RSTEP = (unsigned portLONG) 0x00;
+
+ /* Enable data to be sent and received. */
+ AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
+
+ /* Repair the configuration end point. */
+ portENTER_CRITICAL ();
+ {
+ ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
+ usbCSR_SET_BIT (&ulTemp,
+ ((unsigned portLONG) (AT91C_UDP_EPEDS |
+ AT91C_UDP_EPTYPE_CTRL)));
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulTemp;
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
+ }
+ portEXIT_CRITICAL ();
+ uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvProcessEndPoint0Interrupt (xISRStatus * pxMessage)
+{
+ static xUSB_REQUEST xRequest;
+ unsigned portLONG ulRxBytes;
+
+ /* Get number of bytes received, if any */
+ ulRxBytes = pxMessage->ulCSR0 >> 16;
+ ulRxBytes &= usbRX_COUNT_MASK;
+
+ if (pxMessage->ulCSR0 & AT91C_UDP_TXCOMP)
+ {
+ /* We received a TX complete interrupt. What we do depends on
+ what we sent to get this interrupt. */
+
+ if (eDriverState == eJUST_GOT_CONFIG)
+ {
+ /* We sent an acknowledgement of a SET_CONFIG request. We
+ are now at the end of the enumeration.
+
+ TODO: Config 0 sets unconfigured state, should enter Address state.
+ Request for unsupported config should stall. */
+ AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
+
+ /* Set up endpoints */
+ portENTER_CRITICAL ();
+ {
+ unsigned portLONG ulTemp;
+
+ /* Set endpoint 1 to bulk-out */
+ ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1];
+ usbCSR_SET_BIT (&ulTemp,
+ AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1] = ulTemp;
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
+ /* Set endpoint 2 to bulk-in */
+ ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2];
+ usbCSR_SET_BIT (&ulTemp,
+ AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] = ulTemp;
+ AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT2;
+ /* Set endpoint 3 to interrupt-in, enable it, and enable interrupts */
+ ulTemp = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_3];
+ usbCSR_SET_BIT (&ulTemp,
+ AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_3] = ulTemp;
+ /*AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT3 ); */
+ }
+ portEXIT_CRITICAL ();
+
+ eDriverState = eREADY_TO_SEND;
+ }
+ else if (eDriverState == eJUST_GOT_ADDRESS)
+ {
+ /* We sent an acknowledgement of a SET_ADDRESS request. Move
+ to the addressed state. */
+ if (ulReceivedAddress != (unsigned portLONG) 0)
+ {
+ AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+ }
+ else
+ {
+ AT91C_BASE_UDP->UDP_GLBSTATE = 0;
+ }
+
+ AT91C_BASE_UDP->UDP_FADDR = (AT91C_UDP_FEN | ulReceivedAddress);
+ eDriverState = eNOTHING;
+ }
+ else
+ {
+ /* The TXCOMP was not for any special type of transmission. See
+ if there is any more data to send. */
+ prvSendNextSegment ();
+ }
+ }
+
+ if (pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0)
+ {
+ /* Received a control data packet. May be a 0-length ACK or a data stage. */
+ unsigned portCHAR ucBytesToGet;
+
+ /* Got data. Cancel any outgoing data. */
+ pxControlTx.ulNextCharIndex = pxControlTx.ulTotalDataLength;
+
+ /* Determine how many bytes we need to receive. */
+ ucBytesToGet =
+ pxControlRx.ulTotalDataLength - pxControlRx.ulNextCharIndex;
+ if (ucBytesToGet > ulRxBytes)
+ {
+ ucBytesToGet = ulRxBytes;
+ }
+
+ /* If we're not expecting any data, it's an ack - just quit now. */
+ if (!ucBytesToGet)
+ {
+ return;
+ }
+
+ /* Get the required data and update the index. */
+ memcpy (pxControlRx.ucBuffer, pxMessage->ucFifoData, ucBytesToGet);
+ pxControlRx.ulNextCharIndex += ucBytesToGet;
+ }
+
+ if (pxMessage->ulCSR0 & AT91C_UDP_RXSETUP)
+ {
+ /* Received a SETUP packet. May be followed by data packets. */
+
+ if (ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES)
+ {
+ /* Create an xUSB_REQUEST variable from the raw bytes array. */
+
+ xRequest.ucReqType = pxMessage->ucFifoData[usbREQUEST_TYPE_INDEX];
+ xRequest.ucRequest = pxMessage->ucFifoData[usbREQUEST_INDEX];
+
+ xRequest.usValue = pxMessage->ucFifoData[usbVALUE_HIGH_BYTE];
+ xRequest.usValue <<= 8;
+ xRequest.usValue |= pxMessage->ucFifoData[usbVALUE_LOW_BYTE];
+
+ xRequest.usIndex = pxMessage->ucFifoData[usbINDEX_HIGH_BYTE];
+ xRequest.usIndex <<= 8;
+ xRequest.usIndex |= pxMessage->ucFifoData[usbINDEX_LOW_BYTE];
+
+ xRequest.usLength = pxMessage->ucFifoData[usbLENGTH_HIGH_BYTE];
+ xRequest.usLength <<= 8;
+ xRequest.usLength |= pxMessage->ucFifoData[usbLENGTH_LOW_BYTE];
+
+ pxControlRx.ulNextCharIndex = 0;
+ if (!(xRequest.ucReqType & 0x80)) /* Host-to-Device transfer, may need to get data first */
+ {
+ if (xRequest.usLength > usbMAX_CONTROL_MESSAGE_SIZE)
+ {
+ /* Too big! No space for control data, stall and abort. */
+ prvSendStall ();
+ return;
+ }
+
+ pxControlRx.ulTotalDataLength = xRequest.usLength;
+ }
+ else
+ {
+ /* We're sending the data, don't wait for any. */
+ pxControlRx.ulTotalDataLength = 0;
+ }
+ }
+ }
+
+ /* See if we've got a pending request and all its associated data ready */
+ if ((pxMessage->ulCSR0 & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP))
+ && (pxControlRx.ulNextCharIndex >= pxControlRx.ulTotalDataLength))
+ {
+ unsigned portCHAR ucRequest;
+
+ /* Manipulate the ucRequestType and the ucRequest parameters to
+ generate a zero based request selection. This is just done to
+ break up the requests into subsections for clarity. The
+ alternative would be to have more huge switch statement that would
+ be difficult to optimise. */
+ ucRequest = ((xRequest.ucReqType & 0x60) >> 3);
+ ucRequest |= (xRequest.ucReqType & 0x03);
+
+ switch (ucRequest)
+ {
+ case usbSTANDARD_DEVICE_REQUEST:
+ /* Standard Device request */
+ prvHandleStandardDeviceRequest (&xRequest);
+ break;
+
+ case usbSTANDARD_INTERFACE_REQUEST:
+ /* Standard Interface request */
+ prvHandleStandardInterfaceRequest (&xRequest);
+ break;
+
+ case usbSTANDARD_END_POINT_REQUEST:
+ /* Standard Endpoint request */
+ prvHandleStandardEndPointRequest (&xRequest);
+ break;
+
+ case usbCLASS_INTERFACE_REQUEST:
+ /* Class Interface request */
+ prvHandleClassInterfaceRequest (&xRequest);
+ break;
+
+ default: /* This is not something we want to respond to. */
+ prvSendStall ();
+ }
+ }
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvGetStandardDeviceDescriptor (xUSB_REQUEST * pxRequest)
+{
+ /* The type is in the high byte. Return whatever has been requested. */
+ switch ((pxRequest->usValue & 0xff00) >> 8)
+ {
+ case usbDESCRIPTOR_TYPE_DEVICE:
+ prvSendControlData ((unsigned portCHAR *) &pxDeviceDescriptor,
+ pxRequest->usLength, sizeof (pxDeviceDescriptor),
+ pdTRUE);
+ break;
+
+ case usbDESCRIPTOR_TYPE_CONFIGURATION:
+ prvSendControlData ((unsigned portCHAR *) &(pxConfigDescriptor),
+ pxRequest->usLength, sizeof (pxConfigDescriptor),
+ pdTRUE);
+ break;
+
+ case usbDESCRIPTOR_TYPE_STRING:
+
+ /* The index to the string descriptor is the lower byte. */
+ switch (pxRequest->usValue & 0xff)
+ {
+ case usbLANGUAGE_STRING:
+ prvSendControlData ((unsigned portCHAR *)
+ &pxLanguageStringDescriptor,
+ pxRequest->usLength,
+ sizeof (pxLanguageStringDescriptor), pdTRUE);
+ break;
+
+ case usbMANUFACTURER_STRING:
+ prvSendControlData ((unsigned portCHAR *)
+ &pxManufacturerStringDescriptor,
+ pxRequest->usLength,
+ sizeof (pxManufacturerStringDescriptor),
+ pdTRUE);
+ break;
+
+ case usbPRODUCT_STRING:
+ prvSendControlData ((unsigned portCHAR *)
+ &pxProductStringDescriptor, pxRequest->usLength,
+ sizeof (pxProductStringDescriptor), pdTRUE);
+ break;
+
+ default:
+ prvSendStall ();
+ break;
+ }
+ break;
+
+ default:
+ prvSendStall ();
+ break;
+ }
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvHandleStandardDeviceRequest (xUSB_REQUEST * pxRequest)
+{
+ unsigned portSHORT usStatus = 0;
+
+ switch (pxRequest->ucRequest)
+ {
+ case usbGET_STATUS_REQUEST:
+ /* Just send two byte dummy status. */
+ prvSendControlData ((unsigned portCHAR *) &usStatus, sizeof (usStatus),
+ sizeof (usStatus), pdFALSE);
+ break;
+
+ case usbGET_DESCRIPTOR_REQUEST:
+ /* Send device descriptor */
+ prvGetStandardDeviceDescriptor (pxRequest);
+ break;
+
+ case usbGET_CONFIGURATION_REQUEST:
+ /* Send selected device configuration */
+ prvSendControlData ((unsigned portCHAR *) &ucUSBConfig,
+ sizeof (ucUSBConfig), sizeof (ucUSBConfig),
+ pdFALSE);
+ break;
+
+ case usbSET_FEATURE_REQUEST:
+ prvSendZLP ();
+ break;
+
+ case usbSET_ADDRESS_REQUEST:
+ /* Get assigned address and send ack, but don't implement new address until we get a TXCOMP */
+ prvSendZLP ();
+ eDriverState = eJUST_GOT_ADDRESS;
+ ulReceivedAddress = (unsigned portLONG) pxRequest->usValue;
+ break;
+
+ case usbSET_CONFIGURATION_REQUEST:
+ /* Ack SET_CONFIGURATION request, but don't implement until TXCOMP */
+ ucUSBConfig = (unsigned portCHAR) (pxRequest->usValue & 0xff);
+ eDriverState = eJUST_GOT_CONFIG;
+ prvSendZLP ();
+ break;
+
+ default:
+ /* Any unsupported request results in a STALL response. */
+ prvSendStall ();
+ break;
+ }
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvHandleClassInterfaceRequest (xUSB_REQUEST * pxRequest)
+{
+ switch (pxRequest->ucRequest)
+ {
+ case usbSEND_ENCAPSULATED_COMMAND:
+ prvSendStall ();
+ break;
+
+ case usbGET_ENCAPSULATED_RESPONSE:
+ prvSendStall ();
+ break;
+
+ case usbSET_LINE_CODING:
+ /* Set line coding - baud rate, data bits, parity, stop bits */
+ prvSendZLP ();
+ memcpy ((void *) pxLineCoding, pxControlRx.ucBuffer,
+ sizeof (pxLineCoding));
+ break;
+
+ case usbGET_LINE_CODING:
+ /* Get line coding */
+ prvSendControlData ((unsigned portCHAR *) &pxLineCoding,
+ pxRequest->usLength, sizeof (pxLineCoding),
+ pdFALSE);
+ break;
+
+ case usbSET_CONTROL_LINE_STATE:
+ /* D0: 1=DTR, 0=No DTR, D1: 1=Activate Carrier, 0=Deactivate carrier (RTS, half-duplex) */
+ prvSendZLP ();
+ ucControlState = pxRequest->usValue;
+ break;
+
+ default:
+ prvSendStall ();
+ break;
+ }
+}
+
+/*------------------------------------------------------------*/
+
+static void
+prvGetStandardInterfaceDescriptor (xUSB_REQUEST * pxRequest)
+{
+ switch ((pxRequest->usValue & (unsigned portSHORT) 0xff00) >> 8)
+ {
+ default:
+ prvSendStall ();
+ break;
+ }
+}
+
+/*-----------------------------------------------------------*/
+
+static void
+prvHandleStandardInterfaceRequest (xUSB_REQUEST * pxRequest)
+{
+ unsigned portSHORT usStatus = 0;
+
+ switch (pxRequest->ucRequest)
+ {
+ case usbGET_STATUS_REQUEST:
+ /* Send dummy 2 bytes. */
+ prvSendControlData ((unsigned portCHAR *) &usStatus, sizeof (usStatus),
+ sizeof (usStatus), pdFALSE);
+ break;
+
+ case usbGET_DESCRIPTOR_REQUEST:
+ prvGetStandardInterfaceDescriptor (pxRequest);
+ break;
+
+ /* This minimal implementation does not respond to these. */
+ case usbGET_INTERFACE_REQUEST:
+ case usbSET_FEATURE_REQUEST:
+ case usbSET_INTERFACE_REQUEST:
+
+ default:
+ prvSendStall ();
+ break;
+ }
+}
+
+/*-----------------------------------------------------------*/
+
+static void
+prvHandleStandardEndPointRequest (xUSB_REQUEST * pxRequest)
+{
+ switch (pxRequest->ucRequest)
+ {
+ /* This minimal implementation does not expect to respond to these. */
+ case usbGET_STATUS_REQUEST:
+ case usbCLEAR_FEATURE_REQUEST:
+ case usbSET_FEATURE_REQUEST:
+
+ default:
+ prvSendStall ();
+ break;
+ }
+}
+
+/*-----------------------------------------------------------*/
+
+static void
+vDetachUSBInterface (void)
+{
+ /* Setup the PIO for the USB pull up resistor. */
+ AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
+ AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
+
+
+ /* Disable pull up */
+ AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
+}
+
+/*-----------------------------------------------------------*/
+
+static void
+vInitUSBInterface (void)
+{
+ extern void (vUSB_ISR) (void);
+
+ /* Create the queue used to communicate between the USB ISR and task. */
+ xUSBInterruptQueue =
+ xQueueCreate (usbQUEUE_LENGTH + 1, sizeof (xISRStatus *));
+
+ /* Create the queues used to hold Rx and Tx characters. */
+ xRxCDC =
+ xQueueCreate (USB_CDC_QUEUE_SIZE,
+ (unsigned portCHAR) sizeof (signed portCHAR));
+ xTxCDC =
+ xQueueCreate (USB_CDC_QUEUE_SIZE + 1,
+ (unsigned portCHAR) sizeof (signed portCHAR));
+
+ if ((!xUSBInterruptQueue) || (!xRxCDC) || (!xTxCDC))
+ {
+ /* Not enough RAM to create queues!. */
+ return;
+ }
+
+ /* Initialise a few state variables. */
+ pxControlTx.ulNextCharIndex = (unsigned portLONG) 0;
+ pxControlRx.ulNextCharIndex = (unsigned portLONG) 0;
+ ucUSBConfig = (unsigned portCHAR) 0;
+ eDriverState = eNOTHING;
+ ucControlState = 0;
+ uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
+
+
+ /* HARDWARE SETUP */
+
+ /* Set the PLL USB Divider */
+ AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
+
+ /* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
+ AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
+
+ /* Setup the PIO for the USB pull up resistor. */
+ AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
+ AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
+
+
+ /* Start without the pullup - this will get set at the end of this
+ function. */
+ AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
+
+
+ /* When using the USB debugger the peripheral registers do not always get
+ set to the correct default values. To make sure set the relevant registers
+ manually here. */
+ AT91C_BASE_UDP->UDP_IDR = (unsigned portLONG) 0xffffffff;
+ AT91C_BASE_UDP->UDP_ICR = (unsigned portLONG) 0xffffffff;
+ AT91C_BASE_UDP->UDP_CSR[0] = (unsigned portLONG) 0x00;
+ AT91C_BASE_UDP->UDP_CSR[1] = (unsigned portLONG) 0x00;
+ AT91C_BASE_UDP->UDP_CSR[2] = (unsigned portLONG) 0x00;
+ AT91C_BASE_UDP->UDP_CSR[3] = (unsigned portLONG) 0x00;
+ AT91C_BASE_UDP->UDP_GLBSTATE = 0;
+ AT91C_BASE_UDP->UDP_FADDR = 0;
+
+ /* Enable the transceiver. */
+ AT91C_UDP_TRANSCEIVER_ENABLE = 0;
+
+ /* Enable the USB interrupts - other interrupts get enabled as the
+ enumeration process progresses. */
+ AT91F_AIC_ConfigureIt (AT91C_ID_UDP, usbINTERRUPT_PRIORITY,
+ AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
+ (void (*)(void)) vUSB_ISR);
+ AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;
+
+
+ /* Wait a short while before making our presence known. */
+ vTaskDelay (usbINIT_DELAY);
+ AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
+}
+
+/*-----------------------------------------------------------*/
+
+static void
+prvSendControlData (unsigned portCHAR * pucData,
+ unsigned portSHORT usRequestedLength,
+ unsigned portLONG ulLengthToSend,
+ portLONG lSendingDescriptor)
+{
+ if (((unsigned portLONG) usRequestedLength < ulLengthToSend))
+ {
+ /* Cap the data length to that requested. */
+ ulLengthToSend = (unsigned portSHORT) usRequestedLength;
+ }
+ else if ((ulLengthToSend < (unsigned portLONG) usRequestedLength)
+ && lSendingDescriptor)
+ {
+ /* We are sending a descriptor. If the descriptor is an exact
+ multiple of the FIFO length then it will have to be terminated
+ with a NULL packet. Set the state to indicate this if
+ necessary. */
+ if ((ulLengthToSend % usbFIFO_LENGTH) == 0)
+ {
+ eDriverState = eSENDING_EVEN_DESCRIPTOR;
+ }
+ }
+
+ /* Here we assume that the previous message has been sent. THERE IS NO
+ BUFFER OVERFLOW PROTECTION HERE.
+
+ Copy the data to send into the buffer as we cannot send it all at once
+ (if it is greater than 8 bytes in length). */
+ memcpy (pxControlTx.ucBuffer, pucData, ulLengthToSend);
+
+ /* Reinitialise the buffer index so we start sending from the start of
+ the data. */
+ pxControlTx.ulTotalDataLength = ulLengthToSend;
+ pxControlTx.ulNextCharIndex = (unsigned portLONG) 0;
+
+ /* Send the first 8 bytes now. The rest will get sent in response to
+ TXCOMP interrupts. */
+ prvSendNextSegment ();
+}
+
+/*-----------------------------------------------------------*/
+
+static void
+prvSendNextSegment (void)
+{
+ volatile unsigned portLONG ulNextLength, ulStatus, ulLengthLeftToSend;
+
+ /* Is there any data to send? */
+ if (pxControlTx.ulTotalDataLength > pxControlTx.ulNextCharIndex)
+ {
+ ulLengthLeftToSend =
+ pxControlTx.ulTotalDataLength - pxControlTx.ulNextCharIndex;
+
+ /* We can only send 8 bytes to the fifo at a time. */
+ if (ulLengthLeftToSend > usbFIFO_LENGTH)
+ {
+ ulNextLength = usbFIFO_LENGTH;
+ }
+ else
+ {
+ ulNextLength = ulLengthLeftToSend;
+ }
+
+ /* Wait until we can place data in the fifo. THERE IS NO TIMEOUT
+ HERE! */
+ while (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_TXPKTRDY)
+ {
+ vTaskDelay (usbSHORTEST_DELAY);
+ }
+
+ /* Write the data to the FIFO. */
+ while (ulNextLength > (unsigned portLONG) 0)
+ {
+ AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_0] =
+ pxControlTx.ucBuffer[pxControlTx.ulNextCharIndex];
+
+ ulNextLength--;
+ pxControlTx.ulNextCharIndex++;
+ }
+
+ /* Start the transmission. */
+ portENTER_CRITICAL ();
+ {
+ ulStatus = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
+ usbCSR_SET_BIT (&ulStatus, ((unsigned portLONG) 0x10));
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] = ulStatus;
+ }
+ portEXIT_CRITICAL ();
+ }
+ else
+ {
+ /* There is no data to send. If we were sending a descriptor and the
+ descriptor was an exact multiple of the max packet size then we need
+ to send a null to terminate the transmission. */
+ if (eDriverState == eSENDING_EVEN_DESCRIPTOR)
+ {
+ prvSendZLP ();
+ eDriverState = eNOTHING;
+ }
+ }
+}
diff --git a/openpicc/os/usb/USB-CDC.h b/openpicc/os/usb/USB-CDC.h
new file mode 100644
index 0000000..894ebfb
--- /dev/null
+++ b/openpicc/os/usb/USB-CDC.h
@@ -0,0 +1,87 @@
+/*
+ FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ See http://www.FreeRTOS.org for documentation, latest information, license
+ and contact details. Please ensure to read the configuration and relevant
+ port sections of the online documentation.
+
+ Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
+ with commercial development and support options.
+ ***************************************************************************
+*/
+
+#ifndef USB_CDC_H
+#define USB_CDC_H
+
+#include "usb.h"
+
+#define USB_CDC_QUEUE_SIZE 1024
+
+/* Structure used to take a snapshot of the USB status from within the ISR. */
+typedef struct X_ISR_STATUS
+{
+ unsigned portLONG ulISR;
+ unsigned portLONG ulCSR0;
+ unsigned portCHAR ucFifoData[8];
+} xISRStatus;
+
+/* Structure used to hold the received requests. */
+typedef struct
+{
+ unsigned portCHAR ucReqType;
+ unsigned portCHAR ucRequest;
+ unsigned portSHORT usValue;
+ unsigned portSHORT usIndex;
+ unsigned portSHORT usLength;
+} xUSB_REQUEST;
+
+typedef enum
+{
+ eNOTHING,
+ eJUST_RESET,
+ eJUST_GOT_CONFIG,
+ eJUST_GOT_ADDRESS,
+ eSENDING_EVEN_DESCRIPTOR,
+ eREADY_TO_SEND
+} eDRIVER_STATE;
+
+/* Structure used to control the data being sent to the host. */
+typedef struct
+{
+ unsigned portCHAR ucBuffer[usbMAX_CONTROL_MESSAGE_SIZE];
+ unsigned portLONG ulNextCharIndex;
+ unsigned portLONG ulTotalDataLength;
+} xCONTROL_MESSAGE;
+
+/*-----------------------------------------------------------*/
+void vUSBCDCTask (void *pvParameters);
+
+/* Send cByte down the USB port. Characters are simply buffered and not
+sent unless the port is connected. */
+void vUSBSendByte (portCHAR cByte);
+portLONG vUSBRecvByte (portCHAR *cByte,portLONG size, portTickType xTicksToWait);
+
+#endif
diff --git a/openpicc/os/usb/USBIsr.c b/openpicc/os/usb/USBIsr.c
new file mode 100644
index 0000000..cbc5f85
--- /dev/null
+++ b/openpicc/os/usb/USBIsr.c
@@ -0,0 +1,169 @@
+/*
+ FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ See http://www.FreeRTOS.org for documentation, latest information, license
+ and contact details. Please ensure to read the configuration and relevant
+ port sections of the online documentation.
+ ***************************************************************************
+*/
+
+
+/*
+ BASIC INTERRUPT DRIVEN DRIVER FOR USB.
+
+ This file contains all the usb components that must be compiled
+ to ARM mode. The components that can be compiled to either ARM or THUMB
+ mode are contained in USB-CDC.c.
+
+*/
+
+/* Scheduler includes. */
+#include <FreeRTOS.h>
+#include <task.h>
+#include <queue.h>
+
+/* Demo application includes. */
+#include <board.h>
+#include <usb.h>
+#include <USB-CDC.h>
+
+#define usbINT_CLEAR_MASK (AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 )
+/*-----------------------------------------------------------*/
+
+/* Messages and queue used to communicate between the ISR and the USB task. */
+static xISRStatus xISRMessages[usbQUEUE_LENGTH + 1];
+extern xQueueHandle xUSBInterruptQueue;
+/*-----------------------------------------------------------*/
+
+/* The ISR can cause a context switch so is declared naked. */
+void vUSB_ISR (void) __attribute__ ((naked));
+
+/*-----------------------------------------------------------*/
+
+
+void
+vUSB_ISR (void)
+{
+ /* This ISR can cause a context switch. Therefore a call to the
+ portENTER_SWITCHING_ISR() macro is made. This must come BEFORE any
+ stack variable declarations. */
+ portENTER_SWITCHING_ISR ();
+
+ /* Now variables can be declared. */
+ portCHAR cTaskWokenByPost = pdFALSE;
+ static volatile unsigned portLONG ulNextMessage = 0;
+ xISRStatus *pxMessage;
+ unsigned portLONG ulRxBytes;
+ unsigned portCHAR ucFifoIndex;
+
+ /* Use the next message from the array. */
+ pxMessage = &(xISRMessages[(ulNextMessage & usbQUEUE_LENGTH)]);
+ ulNextMessage++;
+
+ /* Save UDP ISR state for task-level processing. */
+ pxMessage->ulISR = AT91C_BASE_UDP->UDP_ISR;
+ pxMessage->ulCSR0 = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
+
+ /* Clear interrupts from ICR. */
+ AT91C_BASE_UDP->UDP_ICR = AT91C_BASE_UDP->UDP_IMR | AT91C_UDP_ENDBUSRES;
+
+
+ /* Process incoming FIFO data. Must set DIR (if needed) and clear RXSETUP
+ before exit. */
+
+ /* Read CSR and get incoming byte count. */
+ ulRxBytes = (pxMessage->ulCSR0 >> 16) & usbRX_COUNT_MASK;
+
+ /* Receive control transfers on endpoint 0. */
+ if (pxMessage->ulCSR0 & (AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0))
+ {
+ /* Save FIFO data buffer for either a SETUP or DATA stage */
+ for (ucFifoIndex = 0; ucFifoIndex < ulRxBytes; ucFifoIndex++)
+ {
+ pxMessage->ucFifoData[ucFifoIndex] =
+ AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_0];
+ }
+
+ /* Set direction for data stage. Must be done before RXSETUP is
+ cleared. */
+ if ((AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_RXSETUP))
+ {
+ if (ulRxBytes
+ && (pxMessage->ucFifoData[usbREQUEST_TYPE_INDEX] & 0x80))
+ {
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] |= AT91C_UDP_DIR;
+
+ /* Might not be wise in an ISR! */
+ while (!
+ (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_0] & AT91C_UDP_DIR));
+ }
+
+ /* Clear RXSETUP */
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] &= ~AT91C_UDP_RXSETUP;
+
+ /* Might not be wise in an ISR! */
+ while (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_RXSETUP);
+ }
+ else
+ {
+ /* Clear RX_DATA_BK0 */
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] &= ~AT91C_UDP_RX_DATA_BK0;
+
+ /* Might not be wise in an ISR! */
+ while (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_0] & AT91C_UDP_RX_DATA_BK0);
+ }
+ }
+
+ /* If we received data on endpoint 1, disable its interrupts until it is
+ processed in the main loop */
+ if (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_1] & (AT91C_UDP_RX_DATA_BK0 |
+ AT91C_UDP_RX_DATA_BK1))
+ {
+ AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_EPINT1;
+ }
+
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] &=
+ ~(AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT);
+
+ /* Clear interrupts for the other endpoints, retain data flags for endpoint
+ 1. */
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1] &=
+ ~(AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] &= ~usbINT_CLEAR_MASK;
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_3] &= ~usbINT_CLEAR_MASK;
+
+ /* Post ISR data to queue for task-level processing */
+ cTaskWokenByPost =
+ xQueueSendFromISR (xUSBInterruptQueue, &pxMessage, cTaskWokenByPost);
+
+ /* Clear AIC to complete ISR processing */
+ AT91C_BASE_AIC->AIC_EOICR = 0;
+
+ /* Do a task switch if needed */
+portEXIT_SWITCHING_ISR (cTaskWokenByPost)}
diff --git a/openpicc/os/usb/descriptors.h b/openpicc/os/usb/descriptors.h
new file mode 100644
index 0000000..230122f
--- /dev/null
+++ b/openpicc/os/usb/descriptors.h
@@ -0,0 +1,190 @@
+/*
+ FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ See http://www.FreeRTOS.org for documentation, latest information, license
+ and contact details. Please ensure to read the configuration and relevant
+ port sections of the online documentation.
+
+ Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
+ with commercial development and support options.
+ ***************************************************************************
+*/
+
+/*
+ - DESCRIPTOR DEFINITIONS -
+*/
+
+/* String descriptors used during the enumeration process.
+These take the form:
+
+{
+ Length of descriptor,
+ Descriptor type,
+ Data
+}
+*/
+
+const portCHAR pxLanguageStringDescriptor[] = {
+ 4,
+ usbDESCRIPTOR_TYPE_STRING,
+ 0x09, 0x04
+};
+
+const portCHAR pxManufacturerStringDescriptor[] = {
+ 28,
+ usbDESCRIPTOR_TYPE_STRING,
+
+ 'b', 0x00, 'i', 0x00, 't', 0x00, 'm', 0x00,
+ 'a', 0x00, 'n', 0x00, 'u', 0x00, 'f', 0x00,
+ 'a', 0x00, 'k', 0x00, 't', 0x00, 'u', 0x00,
+ 'r', 0x00
+};
+
+const portCHAR pxProductStringDescriptor[] = {
+ 44,
+ usbDESCRIPTOR_TYPE_STRING,
+
+ 'O', 0x00, 'p', 0x00, 'e', 0x00, 'n', 0x00,
+ 'B', 0x00, 'e', 0x00, 'a', 0x00, 'c', 0x00,
+ 'o', 0x00, 'n', 0x00, ' ', 0x00, 'U', 0x00,
+ 'S', 0x00, 'B', 0x00, ' ', 0x00, '2', 0x00,
+ '.', 0x00, '4', 0x00, 'G', 0x00, 'H', 0x00,
+ 'z', 0x00
+};
+
+/* Device should properly be 0x134A:0x9001, using 0x05F9:0xFFFF for Linux testing */
+const char pxDeviceDescriptor[] = {
+ /* Device descriptor */
+ 0x12, /* bLength */
+ 0x01, /* bDescriptorType */
+ 0x10, 0x01, /* bcdUSBL */
+ 0x02, /* bDeviceClass: */
+ 0x00, /* bDeviceSubclass: */
+ 0x00, /* bDeviceProtocol: */
+ 0x08, /* bMaxPacketSize0 */
+ 0xC0, 0x16, /* idVendorL */
+ 0xAC, 0x08, /* idProductL */
+ 0x10, 0x01, /* bcdDeviceL */
+ usbMANUFACTURER_STRING, /* iManufacturer */
+ usbPRODUCT_STRING, /* iProduct */
+ 0x00, /* SerialNumber */
+ 0x01 /* bNumConfigs */
+};
+
+const char pxConfigDescriptor[] = {
+
+ /* Configuration 1 descriptor
+ Here we define two interfaces (0 and 1) and a total of 3 endpoints.
+ Interface 0 is a CDC Abstract Control Model interface with one interrupt-in endpoint.
+ Interface 1 is a CDC Data Interface class, with a bulk-in and bulk-out endpoint.
+ Endpoint 0 gets used as the CDC management element.
+ */
+ 0x09, /* CbLength */
+ 0x02, /* CbDescriptorType */
+ 0x43, 0x00, /* CwTotalLength 2 EP + Control ? */
+ 0x02, /* CbNumInterfaces */
+ 0x01, /* CbConfigurationValue */
+ 0x00, /* CiConfiguration */
+ usbBUS_POWERED, /* CbmAttributes Bus powered + Remote Wakeup */
+ 0x32, /* CMaxPower: 100mA */
+
+ /* Communication Class Interface Descriptor Requirement */
+ 0x09, /* bLength */
+ 0x04, /* bDescriptorType */
+ 0x00, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ 0x01, /* bNumEndpoints */
+ 0x02, /* bInterfaceClass: Comm Interface Class */
+ 0x02, /* bInterfaceSubclass: Abstract Control Model */
+ 0x01, /* bInterfaceProtocol */
+ usbINTERFACE_STRING, /* iInterface */
+
+ /* Header Functional Descriptor */
+ 0x05, /* bLength */
+ 0x24, /* bDescriptor type: CS_INTERFACE */
+ 0x00, /* bDescriptor subtype: Header Func Desc */
+ 0x10, 0x01, /* bcdCDC:1.1 */
+
+ /* ACM Functional Descriptor */
+ 0x04, /* bFunctionLength */
+ 0x24, /* bDescriptor type: CS_INTERFACE */
+ 0x02, /* bDescriptor subtype: ACM Func Desc */
+ 0x00, /* bmCapabilities: We don't support squat */
+
+ /* Union Functional Descriptor */
+ 0x05, /* bFunctionLength */
+ 0x24, /* bDescriptor type: CS_INTERFACE */
+ 0x06, /* bDescriptor subtype: Union Func Desc */
+ 0x00, /* bMasterInterface: CDC Interface */
+ 0x01, /* bSlaveInterface0: Data Class Interface */
+
+ /* Call Management Functional Descriptor
+ 0 in D1 and D0 indicates that device does not handle call management */
+ 0x05, /* bFunctionLength */
+ 0x24, /* bDescriptor type: CS_INTERFACE */
+ 0x01, /* bDescriptor subtype: Call Management Func */
+ 0x00, /* bmCapabilities: D1 + D0 */
+ 0x01, /* bDataInterface: Data Class Interface 1 */
+
+ /* CDC Control - Endpoint 3 descriptor
+ This endpoint serves as a notification element. */
+
+ 0x07, /* bLength */
+ 0x05, /* bDescriptorType */
+ 0x83, /* bEndpointAddress, Endpoint 03 - IN */
+ 0x03, /* bmAttributes INT */
+ 0x08, 0x00, /* wMaxPacketSize: 8 bytes */
+ 0xFF, /* bInterval */
+
+ /* Data Class Interface Descriptor Requirement */
+ 0x09, /* bLength */
+ 0x04, /* bDescriptorType */
+ 0x01, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ 0x02, /* bNumEndPoints */
+ 0x0A, /* bInterfaceClass */
+ 0x00, /* bInterfaceSubclass */
+ 0x00, /* bInterfaceProtocol */
+ 0x00, /* iInterface */
+
+ /* CDC Data - Endpoint 1 descriptor */
+ 0x07, /* bLenght */
+ 0x05, /* bDescriptorType */
+ 0x01, /* bEndPointAddress, Endpoint 01 - OUT */
+ 0x02, /* bmAttributes BULK */
+ 64, /* wMaxPacketSize */
+ 0x00,
+ 0x00, /* bInterval */
+
+ /* CDC Data - Endpoint 2 descriptor */
+ 0x07, /* bLength */
+ 0x05, /* bDescriptorType */
+ 0x82, /* bEndPointAddress, Endpoint 02 - IN */
+ 0x02, /* bmAttributes BULK */
+ 64, /* wMaxPacketSize */
+ 0x00,
+ 0x00 /* bInterval */
+};
diff --git a/openpicc/os/usb/usb.h b/openpicc/os/usb/usb.h
new file mode 100644
index 0000000..86d98f9
--- /dev/null
+++ b/openpicc/os/usb/usb.h
@@ -0,0 +1,146 @@
+/*
+ FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ See http://www.FreeRTOS.org for documentation, latest information, license
+ and contact details. Please ensure to read the configuration and relevant
+ port sections of the online documentation.
+
+ Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
+ with commercial development and support options.
+ ***************************************************************************
+*/
+
+/* Descriptor type definitions. */
+#define usbDESCRIPTOR_TYPE_DEVICE ( 0x01 )
+#define usbDESCRIPTOR_TYPE_CONFIGURATION ( 0x02 )
+#define usbDESCRIPTOR_TYPE_STRING ( 0x03 )
+
+/* USB request type definitions. */
+#define usbGET_REPORT_REQUEST ( 0x01 )
+#define usbGET_IDLE_REQUEST ( 0x02 )
+#define usbGET_PROTOCOL_REQUEST ( 0x03 )
+#define usbSET_REPORT_REQUEST ( 0x09 )
+#define usbSET_IDLE_REQUEST ( 0x0A )
+#define usbSET_PROTOCOL_REQUEST ( 0x0B )
+#define usbGET_CONFIGURATION_REQUEST ( 0x08 )
+#define usbGET_STATUS_REQUEST ( 0x00 )
+#define usbCLEAR_FEATURE_REQUEST ( 0x01 )
+#define usbSET_FEATURE_REQUEST ( 0x03 )
+#define usbSET_ADDRESS_REQUEST ( 0x05 )
+#define usbGET_DESCRIPTOR_REQUEST ( 0x06 )
+#define usbSET_CONFIGURATION_REQUEST ( 0x09 )
+#define usbGET_INTERFACE_REQUEST ( 0x0A )
+#define usbSET_INTERFACE_REQUEST ( 0x0B )
+
+/* ACM Requests */
+#define usbSEND_ENCAPSULATED_COMMAND ( 0x00 )
+#define usbGET_ENCAPSULATED_RESPONSE ( 0x01 )
+#define usbSET_LINE_CODING ( 0x20 )
+#define usbGET_LINE_CODING ( 0x21 )
+#define usbSET_CONTROL_LINE_STATE ( 0x22 )
+
+/* Misc USB definitions. */
+#define usbDEVICE_CLASS_VENDOR_SPECIFIC ( 0xFF )
+#define usbBUS_POWERED ( 0x80 )
+#define usbHID_REPORT_DESCRIPTOR ( 0x22 )
+#define AT91C_UDP_TRANSCEIVER_ENABLE ( *( ( unsigned long * ) 0xfffb0074 ) )
+
+/* Index to the various string. */
+#define usbLANGUAGE_STRING ( 0 )
+#define usbMANUFACTURER_STRING ( 1 )
+#define usbPRODUCT_STRING ( 2 )
+#define usbCONFIGURATION_STRING ( 3 )
+#define usbINTERFACE_STRING ( 4 )
+
+/* Defines fields of standard SETUP request. Now in normal order. */
+#define usbREQUEST_TYPE_INDEX ( 0 )
+#define usbREQUEST_INDEX ( 1 )
+#define usbVALUE_HIGH_BYTE ( 3 )
+#define usbVALUE_LOW_BYTE ( 2 )
+#define usbINDEX_HIGH_BYTE ( 5 )
+#define usbINDEX_LOW_BYTE ( 4 )
+#define usbLENGTH_HIGH_BYTE ( 7 )
+#define usbLENGTH_LOW_BYTE ( 6 )
+
+/* Misc application definitions. */
+#define usbINTERRUPT_PRIORITY ( 3 )
+#define usbQUEUE_LENGTH ( 0x3 ) /* Must have all bits set! */
+#define usbFIFO_LENGTH ( ( unsigned portLONG ) 8 )
+#define usbEND_POINT_0 ( 0 )
+#define usbEND_POINT_1 ( 1 )
+#define usbEND_POINT_2 ( 2 )
+#define usbEND_POINT_3 ( 3 )
+#define usbMAX_CONTROL_MESSAGE_SIZE ( 128 )
+#define usbRX_COUNT_MASK ( ( unsigned portLONG ) 0x7ff )
+#define usbSHORTEST_DELAY ( ( portTickType ) 1 )
+#define usbINIT_DELAY ( ( portTickType ) 1000 / portTICK_RATE_MS )
+#define usbSHORT_DELAY ( ( portTickType ) 50 / portTICK_RATE_MS )
+#define usbEND_POINT_RESET_MASK ( ( unsigned portLONG ) 0x0f )
+#define usbDATA_INC ( ( portCHAR ) 5 )
+#define usbEXPECTED_NUMBER_OF_BYTES ( ( unsigned portLONG ) 8 )
+
+/* Control request types. */
+#define usbSTANDARD_DEVICE_REQUEST ( 0 )
+#define usbSTANDARD_INTERFACE_REQUEST ( 1 )
+#define usbSTANDARD_END_POINT_REQUEST ( 2 )
+#define usbCLASS_INTERFACE_REQUEST ( 5 )
+
+
+/* Macros to manipulate the control and status registers. These registers
+cannot be accessed using a direct read modify write operation outside of the
+ISR as some bits are left unchanged by writing with a 0, and some are left
+unchanged by writing with a 1. */
+
+
+#define usbCSR_SET_BIT( pulValueNow, ulBit ) \
+{ \
+ /* Set TXCOMP, RX_DATA_BK0, RXSETUP, */ \
+ /* STALLSENT and RX_DATA_BK1 to 1 so the */ \
+ /* write has no effect. */ \
+ ( * ( ( unsigned portLONG * ) pulValueNow ) ) |= ( unsigned portLONG ) 0x4f; \
+ \
+ /* Clear the FORCE_STALL and TXPKTRDY bits */ \
+ /* so the write has no effect. */ \
+ ( * ( ( unsigned portLONG * ) pulValueNow ) ) &= ( unsigned portLONG ) 0xffffffcf; \
+ \
+ /* Set whichever bit we want set. */ \
+ ( * ( ( unsigned portLONG * ) pulValueNow ) ) |= ( ulBit ); \
+}
+
+#define usbCSR_CLEAR_BIT( pulValueNow, ulBit ) \
+{ \
+ /* Set TXCOMP, RX_DATA_BK0, RXSETUP, */ \
+ /* STALLSENT and RX_DATA_BK1 to 1 so the */ \
+ /* write has no effect. */ \
+ ( * ( ( unsigned portLONG * ) pulValueNow ) ) |= ( unsigned portLONG ) 0x4f; \
+ \
+ /* Clear the FORCE_STALL and TXPKTRDY bits */ \
+ /* so the write has no effect. */ \
+ ( * ( ( unsigned portLONG * ) pulValueNow ) ) &= ( unsigned portLONG ) 0xffffffcf; \
+ \
+ /* Clear whichever bit we want clear. */ \
+ ( * ( ( unsigned portLONG * ) pulValueNow ) ) &= ( ~ulBit ); \
+}
personal git repositories of Harald Welte. Your mileage may vary