]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - common/usb.c
Apply copyright patch from Michael Gernoth
[proxmark3-svn] / common / usb.c
index 2e8365e45904e257434e2e605c093152d78dab4a..3de7d369f28087cfb3c026e40d405d9097e25af1 100644 (file)
-//-----------------------------------------------------------------------------\r
-// My USB driver. This has to be common, because it exists in both the\r
-// bootrom and the application.\r
-// Jonathan Westhues, split Aug 14 2005\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-\r
-#define min(a, b) (((a) > (b)) ? (b) : (a))\r
-\r
-#define USB_REPORT_PACKET_SIZE 64\r
-\r
-typedef struct PACKED {\r
-       BYTE    bmRequestType;\r
-       BYTE    bRequest;\r
-       WORD    wValue;\r
-       WORD    wIndex;\r
-       WORD    wLength;\r
-} UsbSetupData;\r
-\r
-#define USB_REQUEST_GET_STATUS                                 0\r
-#define USB_REQUEST_CLEAR_FEATURE                              1\r
-#define USB_REQUEST_SET_FEATURE                                        3\r
-#define USB_REQUEST_SET_ADDRESS                                        5\r
-#define USB_REQUEST_GET_DESCRIPTOR                             6\r
-#define USB_REQUEST_SET_DESCRIPTOR                             7\r
-#define USB_REQUEST_GET_CONFIGURATION                  8\r
-#define USB_REQUEST_SET_CONFIGURATION                  9\r
-#define USB_REQUEST_GET_INTERFACE                              10\r
-#define USB_REQUEST_SET_INTERFACE                              11\r
-#define USB_REQUEST_SYNC_FRAME                                 12\r
-\r
-#define USB_DESCRIPTOR_TYPE_DEVICE                             1\r
-#define USB_DESCRIPTOR_TYPE_CONFIGURATION              2\r
-#define USB_DESCRIPTOR_TYPE_STRING                             3\r
-#define USB_DESCRIPTOR_TYPE_INTERFACE                  4\r
-#define USB_DESCRIPTOR_TYPE_ENDPOINT                   5\r
-#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER   6\r
-#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONF   7\r
-#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER            8\r
-#define USB_DESCRIPTOR_TYPE_HID                                        0x21\r
-#define USB_DESCRIPTOR_TYPE_HID_REPORT                 0x22\r
-\r
-#define USB_DEVICE_CLASS_HID                                   0x03\r
-\r
-static const BYTE HidReportDescriptor[] = {\r
-       0x06,0xA0,0xFF, // Usage Page (vendor defined) FFA0\r
-       0x09,0x01,              // Usage (vendor defined)\r
-       0xA1,0x01,              // Collection (Application)\r
-       0x09,0x02,      // Usage (vendor defined)\r
-       0xA1,0x00,      // Collection (Physical)\r
-       0x06,0xA1,0xFF, // Usage Page (vendor defined)\r
-\r
-       //The,input report\r
-       0x09,0x03,      // usage - vendor defined\r
-       0x09,0x04,      // usage - vendor defined\r
-       0x15,0x80,      // Logical Minimum (-128)\r
-       0x25,0x7F,      // Logical Maximum (127)\r
-       0x35,0x00,      // Physical Minimum (0)\r
-       0x45,0xFF,      // Physical Maximum (255)\r
-       0x75,0x08,      // Report Size (8)  (bits)\r
-       0x95,0x40,      // Report Count (64)  (fields)\r
-       0x81,0x02,      // Input (Data,Variable,Absolute)\r
-\r
-       //The,output report\r
-       0x09,0x05,      // usage - vendor defined\r
-       0x09,0x06,      // usage - vendor defined\r
-       0x15,0x80,      // Logical Minimum (-128)\r
-       0x25,0x7F,      // Logical Maximum (127)\r
-       0x35,0x00,      // Physical Minimum (0)\r
-       0x45,0xFF,      // Physical Maximum (255)\r
-       0x75,0x08,      // Report Size (8)  (bits)\r
-       0x95,0x40,      // Report Count (64)  (fields)\r
-       0x91,0x02,      // Output (Data,Variable,Absolute)\r
-\r
-       0xC0,                   // End Collection\r
-\r
-       0xC0,                   // End Collection\r
-};\r
-\r
-static const BYTE DeviceDescriptor[] = {\r
-       0x12,                   // Descriptor length (18 bytes)\r
-       0x01,                   // Descriptor type (Device)\r
-       0x10,0x01,              // Complies with USB Spec. Release (0110h = release 1.10)\r
-       0x00,                   // Class code (0)\r
-       0x00,                   // Subclass code (0)\r
-       0x00,                   // Protocol (No specific protocol)\r
-       0x08,                   // Maximum packet size for Endpoint 0 (8 bytes)\r
-       0xc4,0x9a,              // Vendor ID (random numbers)\r
-       0x8f,0x4b,              // Product ID (random numbers)\r
-       0x01,0x00,              // Device release number (0001)\r
-       0x01,                   // Manufacturer string descriptor index\r
-       0x02,                   // Product string descriptor index\r
-       0x00,                   // Serial Number string descriptor index (None)\r
-       0x01,                   // Number of possible configurations (1)\r
-};\r
-\r
-static const BYTE ConfigurationDescriptor[] = {\r
-       0x09,                   // Descriptor length (9 bytes)\r
-       0x02,                   // Descriptor type (Configuration)\r
-       0x29,0x00,              // Total data length (41 bytes)\r
-       0x01,                   // Interface supported (1)\r
-       0x01,                   // Configuration value (1)\r
-       0x00,                   // Index of string descriptor (None)\r
-       0x80,                   // Configuration (Bus powered)\r
-       250,                    // Maximum power consumption (500mA)\r
-\r
-       //interface\r
-       0x09,                   // Descriptor length (9 bytes)\r
-       0x04,                   // Descriptor type (Interface)\r
-       0x00,                   // Number of interface (0)\r
-       0x00,                   // Alternate setting (0)\r
-       0x02,                   // Number of interface endpoint (2)\r
-       0x03,                   // Class code (HID)\r
-       0x00,                   // Subclass code ()\r
-       0x00,                   // Protocol code ()\r
-       0x00,                   // Index of string()\r
-\r
-       // class\r
-       0x09,                   // Descriptor length (9 bytes)\r
-       0x21,                   // Descriptor type (HID)\r
-       0x00,0x01,              // HID class release number (1.00)\r
-       0x00,                   // Localized country code (None)\r
-       0x01,                   // # of HID class dscrptr to follow (1)\r
-       0x22,                   // Report descriptor type (HID)\r
-       // Total length of report descriptor\r
-       sizeof(HidReportDescriptor),0x00,\r
-\r
-       // endpoint 1\r
-       0x07,                   // Descriptor length (7 bytes)\r
-       0x05,                   // Descriptor type (Endpoint)\r
-       0x01,                   // Encoded address (Respond to OUT)\r
-       0x03,                   // Endpoint attribute (Interrupt transfer)\r
-       0x08,0x00,              // Maximum packet size (8 bytes)\r
-       0x01,                   // Polling interval (1 ms)\r
-\r
-       // endpoint 2\r
-       0x07,                   // Descriptor length (7 bytes)\r
-       0x05,                   // Descriptor type (Endpoint)\r
-       0x82,                   // Encoded address (Respond to IN)\r
-       0x03,                   // Endpoint attribute (Interrupt transfer)\r
-       0x08,0x00,              // Maximum packet size (8 bytes)\r
-       0x01,                   // Polling interval (1 ms)\r
-};\r
-\r
-static const BYTE StringDescriptor0[] = {\r
-       0x04,                   // Length\r
-       0x03,                   // Type is string\r
-       0x09,                   // English\r
-       0x04,                   //  US\r
-};\r
-\r
-static const BYTE StringDescriptor1[] = {\r
-       24,                             // Length\r
-       0x03,                   // Type is string\r
-       'J', 0x00,\r
-       '.', 0x00,\r
-       ' ', 0x00,\r
-       'W', 0x00,\r
-       'e', 0x00,\r
-       's', 0x00,\r
-       't', 0x00,\r
-       'h', 0x00,\r
-       'u', 0x00,\r
-       'e', 0x00,\r
-       's', 0x00,\r
-};\r
-\r
-static const BYTE StringDescriptor2[] = {\r
-       54,                             // Length\r
-       0x03,                   // Type is string\r
-       'P', 0x00,\r
-       'r', 0x00,\r
-       'o', 0x00,\r
-       'x', 0x00,\r
-       'M', 0x00,\r
-       'a', 0x00,\r
-       'r', 0x00,\r
-       'k', 0x00,\r
-       '-', 0x00,\r
-       '3', 0x00,\r
-       ' ', 0x00,\r
-       'R', 0x00,\r
-       'F', 0x00,\r
-       'I', 0x00,\r
-       'D', 0x00,\r
-       ' ', 0x00,\r
-       'I', 0x00,\r
-       'n', 0x00,\r
-       's', 0x00,\r
-       't', 0x00,\r
-       'r', 0x00,\r
-       'u', 0x00,\r
-       'm', 0x00,\r
-       'e', 0x00,\r
-       'n', 0x00,\r
-       't', 0x00,\r
-};\r
-\r
-static const BYTE * const StringDescriptors[] = {\r
-       StringDescriptor0,\r
-       StringDescriptor1,\r
-       StringDescriptor2,\r
-};\r
-\r
-\r
-static BYTE UsbBuffer[64];\r
-static int  UsbSoFarCount;\r
-\r
-static BYTE CurrentConfiguration;\r
-\r
-static void UsbSendEp0(const BYTE *data, int len)\r
-{\r
-       int thisTime, i;\r
-\r
-       do {\r
-               thisTime = min(len, 8);\r
-               len -= thisTime;\r
-\r
-               for(i = 0; i < thisTime; i++) {\r
-                       AT91C_BASE_UDP->UDP_FDR[0] = *data;\r
-                       data++;\r
-               }\r
-\r
-               if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
-                       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;\r
-                       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)\r
-                               ;\r
-               }\r
-\r
-               AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
-\r
-               do {\r
-                       if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) {\r
-                               // This means that the host is trying to write to us, so\r
-                               // abandon our write to them.\r
-                               AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;\r
-                               return;\r
-                       }\r
-               } while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP));\r
-       } while(len > 0);\r
-\r
-       if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
-               AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;\r
-               while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)\r
-                       ;\r
-       }\r
-}\r
-\r
-static void UsbSendZeroLength(void)\r
-{\r
-       AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
-\r
-       while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP))\r
-               ;\r
-\r
-       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;\r
-\r
-       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)\r
-               ;\r
-}\r
-\r
-static void UsbSendStall(void)\r
-{\r
-       AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;\r
-\r
-       while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT))\r
-               ;\r
-\r
-       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_STALLSENT;\r
-\r
-       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT)\r
-               ;\r
-}\r
-\r
-static void HandleRxdSetupData(void)\r
-{\r
-       int i;\r
-       UsbSetupData usd;\r
-\r
-       for(i = 0; i < sizeof(usd); i++) {\r
-               ((BYTE *)&usd)[i] = AT91C_BASE_UDP->UDP_FDR[0];\r
-       }\r
-\r
-       if(usd.bmRequestType & 0x80) {\r
-               AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR;\r
-               while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_DIR))\r
-                       ;\r
-       }\r
-\r
-       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;\r
-       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)\r
-               ;\r
-\r
-       switch(usd.bRequest) {\r
-               case USB_REQUEST_GET_DESCRIPTOR:\r
-                       if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) {\r
-                               UsbSendEp0((BYTE *)&DeviceDescriptor,\r
-                                       min(sizeof(DeviceDescriptor), usd.wLength));\r
-                       } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) {\r
-                               UsbSendEp0((BYTE *)&ConfigurationDescriptor,\r
-                                       min(sizeof(ConfigurationDescriptor), usd.wLength));\r
-                       } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) {\r
-                               const BYTE *s = StringDescriptors[usd.wValue & 0xff];\r
-                               UsbSendEp0(s, min(s[0], usd.wLength));\r
-                       } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) {\r
-                               UsbSendEp0((BYTE *)&HidReportDescriptor,\r
-                                       min(sizeof(HidReportDescriptor), usd.wLength));\r
-                       } else {\r
-                               *((DWORD *)0x00200000) = usd.wValue;\r
-                       }\r
-                       break;\r
-\r
-               case USB_REQUEST_SET_ADDRESS:\r
-                       UsbSendZeroLength();\r
-                       AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | usd.wValue ;\r
-                       if(usd.wValue != 0) {\r
-                               AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;\r
-                       } else {\r
-                               AT91C_BASE_UDP->UDP_GLBSTATE = 0;\r
-                       }\r
-                       break;\r
-\r
-               case USB_REQUEST_GET_CONFIGURATION:\r
-                       UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration));\r
-                       break;\r
-\r
-               case USB_REQUEST_GET_STATUS: {\r
-                       if(usd.bmRequestType & 0x80) {\r
-                               WORD w = 0;\r
-                               UsbSendEp0((BYTE *)&w, sizeof(w));\r
-                       }\r
-                       break;\r
-               }\r
-               case USB_REQUEST_SET_CONFIGURATION:\r
-                       CurrentConfiguration = usd.wValue;\r
-                       if(CurrentConfiguration) {\r
-                               AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;\r
-                               AT91C_BASE_UDP->UDP_CSR[1] = AT91C_UDP_EPEDS |\r
-                                       AT91C_UDP_EPTYPE_INT_OUT;\r
-                               AT91C_BASE_UDP->UDP_CSR[2] = AT91C_UDP_EPEDS |\r
-                                       AT91C_UDP_EPTYPE_INT_IN;\r
-                       } else {\r
-                               AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;\r
-                               AT91C_BASE_UDP->UDP_CSR[1] = 0;\r
-                               AT91C_BASE_UDP->UDP_CSR[2] = 0;\r
-                       }\r
-                       UsbSendZeroLength();\r
-                       break;\r
-\r
-               case USB_REQUEST_GET_INTERFACE: {\r
-                       BYTE b = 0;\r
-                       UsbSendEp0(&b, sizeof(b));\r
-                       break;\r
-               }\r
-\r
-               case USB_REQUEST_SET_INTERFACE:\r
-                       UsbSendZeroLength();\r
-                       break;\r
-\r
-               case USB_REQUEST_CLEAR_FEATURE:\r
-               case USB_REQUEST_SET_FEATURE:\r
-                       UsbSendStall();\r
-                       break;\r
-               case USB_REQUEST_SET_DESCRIPTOR:\r
-               case USB_REQUEST_SYNC_FRAME:\r
-               default:\r
-                       break;\r
-       }\r
-}\r
-\r
-void UsbSendPacket(BYTE *packet, int len)\r
-{\r
-       int i, thisTime;\r
-\r
-       while(len > 0) {\r
-               thisTime = min(len, 8);\r
-\r
-               for(i = 0; i < thisTime; i++) {\r
-                       AT91C_BASE_UDP->UDP_FDR[2] = packet[i];\r
-               }\r
-               AT91C_BASE_UDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;\r
-\r
-               while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP))\r
-                       ;\r
-               AT91C_BASE_UDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP;\r
-\r
-               while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)\r
-                       ;\r
-\r
-               len -= thisTime;\r
-               packet += thisTime;\r
-       }\r
-}\r
-\r
-static void HandleRxdData(void)\r
-{\r
-       int i, len;\r
-\r
-       if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) {\r
-               len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]);\r
-\r
-               for(i = 0; i < len; i++) {\r
-                       UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1];\r
-                       UsbSoFarCount++;\r
-               }\r
-\r
-               AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK0;\r
-               while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0)\r
-                       ;\r
-\r
-               if(UsbSoFarCount >= 64) {\r
-                       UsbPacketReceived(UsbBuffer, UsbSoFarCount);\r
-                       UsbSoFarCount = 0;\r
-               }\r
-       }\r
-\r
-       if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) {\r
-               len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]);\r
-\r
-               for(i = 0; i < len; i++) {\r
-                       UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1];\r
-                       UsbSoFarCount++;\r
-               }\r
-\r
-               AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK1;\r
-               while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1)\r
-                       ;\r
-\r
-               if(UsbSoFarCount >= 64) {\r
-                       UsbPacketReceived(UsbBuffer, UsbSoFarCount);\r
-                       UsbSoFarCount = 0;\r
-               }\r
-       }\r
-}\r
-\r
-void UsbStart(void)\r
-{\r
-       volatile int i;\r
-\r
-       UsbSoFarCount = 0;\r
-\r
-       USB_D_PLUS_PULLUP_OFF();\r
-\r
-       for(i = 0; i < 1000000; i++)\r
-               ;\r
-\r
-       USB_D_PLUS_PULLUP_ON();\r
-\r
-       if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
-               AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
-       }\r
-}\r
-\r
-BOOL UsbConnected()\r
-{\r
-       if (AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG)\r
-               return TRUE;\r
-       else\r
-               return FALSE;\r
-}\r
-\r
-BOOL UsbPoll(BOOL blinkLeds)\r
-{\r
-       BOOL ret = FALSE;\r
-\r
-       if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
-               AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
-\r
-               // following a reset we should be ready to receive a setup packet\r
-               AT91C_BASE_UDP->UDP_RSTEP = 0xf;\r
-               AT91C_BASE_UDP->UDP_RSTEP = 0;\r
-\r
-               AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;\r
-\r
-               AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS;\r
-\r
-               CurrentConfiguration = 0;\r
-\r
-               ret = TRUE;\r
-       }\r
-\r
-       if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(0)) {\r
-               if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) {\r
-                       HandleRxdSetupData();\r
-                       ret = TRUE;\r
-               }\r
-       }\r
-\r
-       if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(1)) {\r
-               HandleRxdData();\r
-               ret = TRUE;\r
-       }\r
-\r
-       return ret;\r
-}\r
+//-----------------------------------------------------------------------------
+// Jonathan Westhues, split Aug 14 2005
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// The common USB driver used for both the bootloader and the application.
+//-----------------------------------------------------------------------------
+
+#include "proxmark3.h"
+
+#define min(a, b) (((a) > (b)) ? (b) : (a))
+
+#define USB_REPORT_PACKET_SIZE 64
+
+typedef struct PACKED {
+       uint8_t         bmRequestType;
+       uint8_t         bRequest;
+       uint16_t        wValue;
+       uint16_t        wIndex;
+       uint16_t        wLength;
+} UsbSetupData;
+
+#define USB_REQUEST_GET_STATUS                                 0
+#define USB_REQUEST_CLEAR_FEATURE                              1
+#define USB_REQUEST_SET_FEATURE                                        3
+#define USB_REQUEST_SET_ADDRESS                                        5
+#define USB_REQUEST_GET_DESCRIPTOR                             6
+#define USB_REQUEST_SET_DESCRIPTOR                             7
+#define USB_REQUEST_GET_CONFIGURATION                  8
+#define USB_REQUEST_SET_CONFIGURATION                  9
+#define USB_REQUEST_GET_INTERFACE                              10
+#define USB_REQUEST_SET_INTERFACE                              11
+#define USB_REQUEST_SYNC_FRAME                                 12
+
+#define USB_DESCRIPTOR_TYPE_DEVICE                             1
+#define USB_DESCRIPTOR_TYPE_CONFIGURATION              2
+#define USB_DESCRIPTOR_TYPE_STRING                             3
+#define USB_DESCRIPTOR_TYPE_INTERFACE                  4
+#define USB_DESCRIPTOR_TYPE_ENDPOINT                   5
+#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER   6
+#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONF   7
+#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER            8
+#define USB_DESCRIPTOR_TYPE_HID                                        0x21
+#define USB_DESCRIPTOR_TYPE_HID_REPORT                 0x22
+
+#define USB_DEVICE_CLASS_HID                                   0x03
+
+static const uint8_t HidReportDescriptor[] = {
+       0x06,0xA0,0xFF, // Usage Page (vendor defined) FFA0
+       0x09,0x01,              // Usage (vendor defined)
+       0xA1,0x01,              // Collection (Application)
+       0x09,0x02,      // Usage (vendor defined)
+       0xA1,0x00,      // Collection (Physical)
+       0x06,0xA1,0xFF, // Usage Page (vendor defined)
+
+       //The,input report
+       0x09,0x03,      // usage - vendor defined
+       0x09,0x04,      // usage - vendor defined
+       0x15,0x80,      // Logical Minimum (-128)
+       0x25,0x7F,      // Logical Maximum (127)
+       0x35,0x00,      // Physical Minimum (0)
+       0x45,0xFF,      // Physical Maximum (255)
+       0x75,0x08,      // Report Size (8)  (bits)
+       0x95,0x40,      // Report Count (64)  (fields)
+       0x81,0x02,      // Input (Data,Variable,Absolute)
+
+       //The,output report
+       0x09,0x05,      // usage - vendor defined
+       0x09,0x06,      // usage - vendor defined
+       0x15,0x80,      // Logical Minimum (-128)
+       0x25,0x7F,      // Logical Maximum (127)
+       0x35,0x00,      // Physical Minimum (0)
+       0x45,0xFF,      // Physical Maximum (255)
+       0x75,0x08,      // Report Size (8)  (bits)
+       0x95,0x40,      // Report Count (64)  (fields)
+       0x91,0x02,      // Output (Data,Variable,Absolute)
+
+       0xC0,                   // End Collection
+
+       0xC0,                   // End Collection
+};
+
+static const uint8_t DeviceDescriptor[] = {
+       0x12,                   // Descriptor length (18 bytes)
+       0x01,                   // Descriptor type (Device)
+       0x10,0x01,              // Complies with USB Spec. Release (0110h = release 1.10)
+       0x00,                   // Class code (0)
+       0x00,                   // Subclass code (0)
+       0x00,                   // Protocol (No specific protocol)
+       0x08,                   // Maximum packet size for Endpoint 0 (8 bytes)
+       0xc4,0x9a,              // Vendor ID (random numbers)
+       0x8f,0x4b,              // Product ID (random numbers)
+       0x01,0x00,              // Device release number (0001)
+       0x01,                   // Manufacturer string descriptor index
+       0x02,                   // Product string descriptor index
+       0x00,                   // Serial Number string descriptor index (None)
+       0x01,                   // Number of possible configurations (1)
+};
+
+static const uint8_t ConfigurationDescriptor[] = {
+       0x09,                   // Descriptor length (9 bytes)
+       0x02,                   // Descriptor type (Configuration)
+       0x29,0x00,              // Total data length (41 bytes)
+       0x01,                   // Interface supported (1)
+       0x01,                   // Configuration value (1)
+       0x00,                   // Index of string descriptor (None)
+       0x80,                   // Configuration (Bus powered)
+       250,                    // Maximum power consumption (500mA)
+
+       //interface
+       0x09,                   // Descriptor length (9 bytes)
+       0x04,                   // Descriptor type (Interface)
+       0x00,                   // Number of interface (0)
+       0x00,                   // Alternate setting (0)
+       0x02,                   // Number of interface endpoint (2)
+       0x03,                   // Class code (HID)
+       0x00,                   // Subclass code ()
+       0x00,                   // Protocol code ()
+       0x00,                   // Index of string()
+
+       // class
+       0x09,                   // Descriptor length (9 bytes)
+       0x21,                   // Descriptor type (HID)
+       0x00,0x01,              // HID class release number (1.00)
+       0x00,                   // Localized country code (None)
+       0x01,                   // # of HID class dscrptr to follow (1)
+       0x22,                   // Report descriptor type (HID)
+       // Total length of report descriptor
+       sizeof(HidReportDescriptor),0x00,
+
+       // endpoint 1
+       0x07,                   // Descriptor length (7 bytes)
+       0x05,                   // Descriptor type (Endpoint)
+       0x01,                   // Encoded address (Respond to OUT)
+       0x03,                   // Endpoint attribute (Interrupt transfer)
+       0x08,0x00,              // Maximum packet size (8 bytes)
+       0x01,                   // Polling interval (1 ms)
+
+       // endpoint 2
+       0x07,                   // Descriptor length (7 bytes)
+       0x05,                   // Descriptor type (Endpoint)
+       0x82,                   // Encoded address (Respond to IN)
+       0x03,                   // Endpoint attribute (Interrupt transfer)
+       0x08,0x00,              // Maximum packet size (8 bytes)
+       0x01,                   // Polling interval (1 ms)
+};
+
+static const uint8_t StringDescriptor0[] = {
+       0x04,                   // Length
+       0x03,                   // Type is string
+       0x09,                   // English
+       0x04,                   //  US
+};
+
+static const uint8_t StringDescriptor1[] = {
+       24,                             // Length
+       0x03,                   // Type is string
+       'J', 0x00,
+       '.', 0x00,
+       ' ', 0x00,
+       'W', 0x00,
+       'e', 0x00,
+       's', 0x00,
+       't', 0x00,
+       'h', 0x00,
+       'u', 0x00,
+       'e', 0x00,
+       's', 0x00,
+};
+
+static const uint8_t StringDescriptor2[] = {
+       54,                             // Length
+       0x03,                   // Type is string
+       'P', 0x00,
+       'r', 0x00,
+       'o', 0x00,
+       'x', 0x00,
+       'M', 0x00,
+       'a', 0x00,
+       'r', 0x00,
+       'k', 0x00,
+       '-', 0x00,
+       '3', 0x00,
+       ' ', 0x00,
+       'R', 0x00,
+       'F', 0x00,
+       'I', 0x00,
+       'D', 0x00,
+       ' ', 0x00,
+       'I', 0x00,
+       'n', 0x00,
+       's', 0x00,
+       't', 0x00,
+       'r', 0x00,
+       'u', 0x00,
+       'm', 0x00,
+       'e', 0x00,
+       'n', 0x00,
+       't', 0x00,
+};
+
+static const uint8_t * const StringDescriptors[] = {
+       StringDescriptor0,
+       StringDescriptor1,
+       StringDescriptor2,
+};
+
+
+static uint8_t UsbBuffer[64];
+static int  UsbSoFarCount;
+
+static uint8_t CurrentConfiguration;
+
+static void UsbSendEp0(const uint8_t *data, int len)
+{
+       int thisTime, i;
+
+       do {
+               thisTime = min(len, 8);
+               len -= thisTime;
+
+               for(i = 0; i < thisTime; i++) {
+                       AT91C_BASE_UDP->UDP_FDR[0] = *data;
+                       data++;
+               }
+
+               if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
+                       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;
+                       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)
+                               ;
+               }
+
+               AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
+
+               do {
+                       if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) {
+                               // This means that the host is trying to write to us, so
+                               // abandon our write to them.
+                               AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RX_DATA_BK0;
+                               return;
+                       }
+               } while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP));
+       } while(len > 0);
+
+       if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
+               AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;
+               while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)
+                       ;
+       }
+}
+
+static void UsbSendZeroLength(void)
+{
+       AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
+
+       while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP))
+               ;
+
+       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_TXCOMP;
+
+       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_TXCOMP)
+               ;
+}
+
+static void UsbSendStall(void)
+{
+       AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;
+
+       while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT))
+               ;
+
+       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_STALLSENT;
+
+       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_STALLSENT)
+               ;
+}
+
+static void HandleRxdSetupData(void)
+{
+       int i;
+       UsbSetupData usd;
+
+       for(i = 0; i < sizeof(usd); i++) {
+               ((uint8_t *)&usd)[i] = AT91C_BASE_UDP->UDP_FDR[0];
+       }
+
+       if(usd.bmRequestType & 0x80) {
+               AT91C_BASE_UDP->UDP_CSR[0] |= AT91C_UDP_DIR;
+               while(!(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_DIR))
+                       ;
+       }
+
+       AT91C_BASE_UDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
+       while(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP)
+               ;
+
+       switch(usd.bRequest) {
+               case USB_REQUEST_GET_DESCRIPTOR:
+                       if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) {
+                               UsbSendEp0((uint8_t *)&DeviceDescriptor,
+                                       min(sizeof(DeviceDescriptor), usd.wLength));
+                       } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
+                               UsbSendEp0((uint8_t *)&ConfigurationDescriptor,
+                                       min(sizeof(ConfigurationDescriptor), usd.wLength));
+                       } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) {
+                               const uint8_t *s = StringDescriptors[usd.wValue & 0xff];
+                               UsbSendEp0(s, min(s[0], usd.wLength));
+                       } else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) {
+                               UsbSendEp0((uint8_t *)&HidReportDescriptor,
+                                       min(sizeof(HidReportDescriptor), usd.wLength));
+                       } else {
+                               *((uint32_t *)0x00200000) = usd.wValue;
+                       }
+                       break;
+
+               case USB_REQUEST_SET_ADDRESS:
+                       UsbSendZeroLength();
+                       AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN | usd.wValue ;
+                       if(usd.wValue != 0) {
+                               AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+                       } else {
+                               AT91C_BASE_UDP->UDP_GLBSTATE = 0;
+                       }
+                       break;
+
+               case USB_REQUEST_GET_CONFIGURATION:
+                       UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration));
+                       break;
+
+               case USB_REQUEST_GET_STATUS: {
+                       if(usd.bmRequestType & 0x80) {
+                               uint16_t w = 0;
+                               UsbSendEp0((uint8_t *)&w, sizeof(w));
+                       }
+                       break;
+               }
+               case USB_REQUEST_SET_CONFIGURATION:
+                       CurrentConfiguration = usd.wValue;
+                       if(CurrentConfiguration) {
+                               AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
+                               AT91C_BASE_UDP->UDP_CSR[1] = AT91C_UDP_EPEDS |
+                                       AT91C_UDP_EPTYPE_INT_OUT;
+                               AT91C_BASE_UDP->UDP_CSR[2] = AT91C_UDP_EPEDS |
+                                       AT91C_UDP_EPTYPE_INT_IN;
+                       } else {
+                               AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
+                               AT91C_BASE_UDP->UDP_CSR[1] = 0;
+                               AT91C_BASE_UDP->UDP_CSR[2] = 0;
+                       }
+                       UsbSendZeroLength();
+                       break;
+
+               case USB_REQUEST_GET_INTERFACE: {
+                       uint8_t b = 0;
+                       UsbSendEp0(&b, sizeof(b));
+                       break;
+               }
+
+               case USB_REQUEST_SET_INTERFACE:
+                       UsbSendZeroLength();
+                       break;
+
+               case USB_REQUEST_CLEAR_FEATURE:
+               case USB_REQUEST_SET_FEATURE:
+                       UsbSendStall();
+                       break;
+               case USB_REQUEST_SET_DESCRIPTOR:
+               case USB_REQUEST_SYNC_FRAME:
+               default:
+                       break;
+       }
+}
+
+void UsbSendPacket(uint8_t *packet, int len)
+{
+       int i, thisTime;
+
+       while(len > 0) {
+               thisTime = min(len, 8);
+
+               for(i = 0; i < thisTime; i++) {
+                       AT91C_BASE_UDP->UDP_FDR[2] = packet[i];
+               }
+               AT91C_BASE_UDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
+
+               while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP))
+                       ;
+               AT91C_BASE_UDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP;
+
+               while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)
+                       ;
+
+               len -= thisTime;
+               packet += thisTime;
+       }
+}
+
+static void HandleRxdData(void)
+{
+       int i, len;
+
+       if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) {
+               len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]);
+
+               for(i = 0; i < len; i++) {
+                       UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1];
+                       UsbSoFarCount++;
+               }
+
+               AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK0;
+               while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0)
+                       ;
+
+               if(UsbSoFarCount >= 64) {
+                       UsbPacketReceived(UsbBuffer, UsbSoFarCount);
+                       UsbSoFarCount = 0;
+               }
+       }
+
+       if(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) {
+               len = UDP_CSR_BYTES_RECEIVED(AT91C_BASE_UDP->UDP_CSR[1]);
+
+               for(i = 0; i < len; i++) {
+                       UsbBuffer[UsbSoFarCount] = AT91C_BASE_UDP->UDP_FDR[1];
+                       UsbSoFarCount++;
+               }
+
+               AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK1;
+               while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1)
+                       ;
+
+               if(UsbSoFarCount >= 64) {
+                       UsbPacketReceived(UsbBuffer, UsbSoFarCount);
+                       UsbSoFarCount = 0;
+               }
+       }
+}
+
+void UsbStart(void)
+{
+       volatile int i;
+
+       UsbSoFarCount = 0;
+
+       USB_D_PLUS_PULLUP_OFF();
+
+       for(i = 0; i < 1000000; i++)
+               ;
+
+       USB_D_PLUS_PULLUP_ON();
+
+       if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
+               AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
+       }
+}
+
+int UsbConnected()
+{
+       if (AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+int UsbPoll(int blinkLeds)
+{
+       int ret = FALSE;
+
+       if(AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
+               AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
+
+               // following a reset we should be ready to receive a setup packet
+               AT91C_BASE_UDP->UDP_RSTEP = 0xf;
+               AT91C_BASE_UDP->UDP_RSTEP = 0;
+
+               AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
+
+               AT91C_BASE_UDP->UDP_CSR[0] = AT91C_UDP_EPTYPE_CTRL | AT91C_UDP_EPEDS;
+
+               CurrentConfiguration = 0;
+
+               ret = TRUE;
+       }
+
+       if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(0)) {
+               if(AT91C_BASE_UDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) {
+                       HandleRxdSetupData();
+                       ret = TRUE;
+               }
+       }
+
+       if(AT91C_BASE_UDP->UDP_ISR & UDP_INTERRUPT_ENDPOINT(1)) {
+               HandleRxdData();
+               ret = TRUE;
+       }
+
+       return ret;
+}
Impressum, Datenschutz