--- /dev/null
+//-----------------------------------------------------------------------------\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
+ UDP_ENDPOINT_FIFO(0) = *data;\r
+ data++;\r
+ }\r
+\r
+ if(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED) {\r
+ UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;\r
+ while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)\r
+ ;\r
+ }\r
+\r
+ UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;\r
+\r
+ do {\r
+ if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {\r
+ // This means that the host is trying to write to us, so\r
+ // abandon our write to them.\r
+ UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;\r
+ return;\r
+ }\r
+ } while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED));\r
+ } while(len > 0);\r
+\r
+ if(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED) {\r
+ UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;\r
+ while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)\r
+ ;\r
+ }\r
+}\r
+\r
+static void UsbSendZeroLength(void)\r
+{\r
+ UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;\r
+\r
+ while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED))\r
+ ;\r
+\r
+ UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;\r
+\r
+ while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)\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] = UDP_ENDPOINT_FIFO(0);\r
+ }\r
+\r
+ if(usd.bmRequestType & 0x80) {\r
+ UDP_ENDPOINT_CSR(0) |= UDP_CSR_CONTROL_DATA_DIR;\r
+ while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_CONTROL_DATA_DIR))\r
+ ;\r
+ }\r
+\r
+ UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_HAVE_READ_SETUP_DATA;\r
+ while(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA)\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
+ UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED | usd.wValue ;\r
+ if(usd.wValue != 0) {\r
+ UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;\r
+ } else {\r
+ UDP_GLOBAL_STATE = 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
+ UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_CONFIGURED;\r
+ UDP_ENDPOINT_CSR(1) = UDP_CSR_ENABLE_EP |\r
+ UDP_CSR_EPTYPE_INTERRUPT_OUT;\r
+ UDP_ENDPOINT_CSR(2) = UDP_CSR_ENABLE_EP |\r
+ UDP_CSR_EPTYPE_INTERRUPT_IN;\r
+ } else {\r
+ UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;\r
+ UDP_ENDPOINT_CSR(1) = 0;\r
+ UDP_ENDPOINT_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
+ 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
+ UDP_ENDPOINT_FIFO(2) = packet[i];\r
+ }\r
+ UDP_ENDPOINT_CSR(2) |= UDP_CSR_TX_PACKET;\r
+\r
+ while(!(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED))\r
+ ;\r
+ UDP_ENDPOINT_CSR(2) &= ~UDP_CSR_TX_PACKET_ACKED;\r
+\r
+ while(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED)\r
+ ;\r
+\r
+ len -= thisTime;\r
+ packet += thisTime;\r
+ }\r
+}\r
+\r
+static void HandleRxdData(void)\r
+{\r
+ int i, len;\r
+\r
+ if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {\r
+ len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));\r
+\r
+ for(i = 0; i < len; i++) {\r
+ UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);\r
+ UsbSoFarCount++;\r
+ }\r
+\r
+ UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;\r
+ while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0)\r
+ ;\r
+\r
+ if(UsbSoFarCount >= 64) {\r
+ UsbPacketReceived(UsbBuffer, UsbSoFarCount);\r
+ UsbSoFarCount = 0;\r
+ }\r
+ }\r
+\r
+ if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1) {\r
+ len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));\r
+\r
+ for(i = 0; i < len; i++) {\r
+ UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);\r
+ UsbSoFarCount++;\r
+ }\r
+\r
+ UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_1;\r
+ while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1)\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(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {\r
+ UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;\r
+ }\r
+}\r
+\r
+BOOL UsbPoll(BOOL blinkLeds)\r
+{\r
+ BOOL ret = FALSE;\r
+\r
+ if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {\r
+ UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;\r
+\r
+ // following a reset we should be ready to receive a setup packet\r
+ UDP_RESET_ENDPOINT = 0xf;\r
+ UDP_RESET_ENDPOINT = 0;\r
+\r
+ UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED;\r
+\r
+ UDP_ENDPOINT_CSR(0) = UDP_CSR_EPTYPE_CONTROL | UDP_CSR_ENABLE_EP;\r
+\r
+ CurrentConfiguration = 0;\r
+\r
+ ret = TRUE;\r
+ }\r
+\r
+ if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(0)) {\r
+ if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA) {\r
+ HandleRxdSetupData();\r
+ ret = TRUE;\r
+ }\r
+ }\r
+\r
+ if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(1)) {\r
+ HandleRxdData();\r
+ ret = TRUE;\r
+ }\r
+\r
+ return ret;\r
+}\r