USB host library, support isochronous,bulk,interrupt and control.
Dependents: BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example
Import programBaseUsbHost_example
BaseUsbHost example program
BaseUsbHost.h@5:8a2d056e9b38, 2013-02-11 (annotated)
- Committer:
- va009039
- Date:
- Mon Feb 11 12:00:47 2013 +0000
- Revision:
- 5:8a2d056e9b38
- Parent:
- 4:d931d24c2f81
add GetStringDescriptor()
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 5:8a2d056e9b38 | 1 | // BaseUsbHost.h 2013/2/11 |
va009039 | 3:ae77d63a1eda | 2 | #pragma once |
va009039 | 3:ae77d63a1eda | 3 | #include <vector> |
va009039 | 5:8a2d056e9b38 | 4 | #include <string> |
va009039 | 0:b7d6879637a8 | 5 | |
va009039 | 2:fe1e62051d88 | 6 | #define USB_OK 0 |
va009039 | 2:fe1e62051d88 | 7 | #define USB_PROCESSING -1 |
va009039 | 2:fe1e62051d88 | 8 | #define USB_ERROR -2 |
va009039 | 2:fe1e62051d88 | 9 | #define USB_ERROR_MEMORY -3 |
va009039 | 3:ae77d63a1eda | 10 | #define USB_ERROR_STALL -4 |
va009039 | 3:ae77d63a1eda | 11 | #define USB_ERROR_DEVICE_NOT_RESPONDING -5 |
va009039 | 0:b7d6879637a8 | 12 | |
va009039 | 0:b7d6879637a8 | 13 | // USB STANDARD REQUEST DEFINITIONS |
va009039 | 0:b7d6879637a8 | 14 | #define USB_DESCRIPTOR_TYPE_DEVICE 1 |
va009039 | 0:b7d6879637a8 | 15 | #define USB_DESCRIPTOR_TYPE_CONFIGURATION 2 |
va009039 | 0:b7d6879637a8 | 16 | #define USB_DESCRIPTOR_TYPE_STRING 3 |
va009039 | 0:b7d6879637a8 | 17 | #define USB_DESCRIPTOR_TYPE_INTERFACE 4 |
va009039 | 0:b7d6879637a8 | 18 | #define USB_DESCRIPTOR_TYPE_ENDPOINT 5 |
va009039 | 0:b7d6879637a8 | 19 | #define USB_DESCRIPTOR_TYPE_HUB 0x29 |
va009039 | 0:b7d6879637a8 | 20 | // ----------- Control RequestType Fields ----------- |
va009039 | 0:b7d6879637a8 | 21 | #define USB_DEVICE_TO_HOST 0x80 |
va009039 | 0:b7d6879637a8 | 22 | #define USB_HOST_TO_DEVICE 0x00 |
va009039 | 0:b7d6879637a8 | 23 | #define USB_REQUEST_TYPE_CLASS 0x20 |
va009039 | 0:b7d6879637a8 | 24 | #define USB_RECIPIENT_DEVICE 0x00 |
va009039 | 0:b7d6879637a8 | 25 | #define USB_RECIPIENT_INTERFACE 0x01 |
va009039 | 0:b7d6879637a8 | 26 | #define USB_RECIPIENT_OTHER 0x03 |
va009039 | 0:b7d6879637a8 | 27 | // -------------- USB Standard Requests -------------- |
va009039 | 0:b7d6879637a8 | 28 | #define GET_STATUS 0 |
va009039 | 0:b7d6879637a8 | 29 | #define CLEAR_FEATURE 1 |
va009039 | 0:b7d6879637a8 | 30 | #define SET_FEATURE 3 |
va009039 | 0:b7d6879637a8 | 31 | #define SET_ADDRESS 5 |
va009039 | 0:b7d6879637a8 | 32 | #define GET_DESCRIPTOR 6 |
va009039 | 0:b7d6879637a8 | 33 | #define SET_CONFIGURATION 9 |
va009039 | 0:b7d6879637a8 | 34 | #define SET_INTERFACE 11 |
va009039 | 3:ae77d63a1eda | 35 | |
va009039 | 3:ae77d63a1eda | 36 | #pragma pack(push,1) |
va009039 | 4:d931d24c2f81 | 37 | struct StandardDeviceDescriptor {// offset |
va009039 | 3:ae77d63a1eda | 38 | uint8_t bLength; // +0 |
va009039 | 3:ae77d63a1eda | 39 | uint8_t bDescriptorType; // +1 |
va009039 | 3:ae77d63a1eda | 40 | uint16_t bcdUSB; // +2 |
va009039 | 3:ae77d63a1eda | 41 | uint8_t bDeviceClass; // +4 |
va009039 | 3:ae77d63a1eda | 42 | uint8_t bDeviceSubClass; // +5 |
va009039 | 3:ae77d63a1eda | 43 | uint8_t bDeviceProtocol; // +6 |
va009039 | 3:ae77d63a1eda | 44 | uint8_t bMaxPacketSize; // +7 |
va009039 | 3:ae77d63a1eda | 45 | uint16_t idVendor; // +8 |
va009039 | 3:ae77d63a1eda | 46 | uint16_t idProduct; // +10 |
va009039 | 3:ae77d63a1eda | 47 | uint16_t bcdDevice; // +12 |
va009039 | 3:ae77d63a1eda | 48 | uint8_t iManufacturer; // +14 |
va009039 | 3:ae77d63a1eda | 49 | uint8_t iProduct; // +15 |
va009039 | 3:ae77d63a1eda | 50 | uint8_t iSerialNumber; // +16 |
va009039 | 3:ae77d63a1eda | 51 | uint8_t bNumConfigurations; // +17 |
va009039 | 4:d931d24c2f81 | 52 | }; // +18 |
va009039 | 3:ae77d63a1eda | 53 | |
va009039 | 4:d931d24c2f81 | 54 | struct StandardConfigurationDescriptor {// offset |
va009039 | 3:ae77d63a1eda | 55 | uint8_t bLength; // +0 |
va009039 | 3:ae77d63a1eda | 56 | uint8_t bDescriptorType; // +1 |
va009039 | 3:ae77d63a1eda | 57 | uint16_t wTotalLength; // +2 |
va009039 | 3:ae77d63a1eda | 58 | uint8_t bNumInterfaces; // +4 |
va009039 | 3:ae77d63a1eda | 59 | uint8_t bConfigurationValue; // +5 |
va009039 | 3:ae77d63a1eda | 60 | uint8_t iConfiguration; // +6 |
va009039 | 3:ae77d63a1eda | 61 | uint8_t bmAttributes; // +7 |
va009039 | 3:ae77d63a1eda | 62 | uint8_t bMaxPower; // +8 |
va009039 | 4:d931d24c2f81 | 63 | }; // +9 |
va009039 | 3:ae77d63a1eda | 64 | |
va009039 | 4:d931d24c2f81 | 65 | struct StandardInterfaceDescriptor {// offset |
va009039 | 3:ae77d63a1eda | 66 | uint8_t bLength; // +0 |
va009039 | 3:ae77d63a1eda | 67 | uint8_t bDescriptorType; // +1 |
va009039 | 3:ae77d63a1eda | 68 | uint8_t bInterfaceNumber; // +2 |
va009039 | 3:ae77d63a1eda | 69 | uint8_t bAlternateSetting; // +3 |
va009039 | 3:ae77d63a1eda | 70 | uint8_t bNumEndpoints; // +4 |
va009039 | 3:ae77d63a1eda | 71 | uint8_t bInterfaceClass; // +5 |
va009039 | 3:ae77d63a1eda | 72 | uint8_t bInterfaceSubClass;// +6 |
va009039 | 3:ae77d63a1eda | 73 | uint8_t bInterfaceProtocol;// +7 |
va009039 | 3:ae77d63a1eda | 74 | uint8_t iInterface; // +8 |
va009039 | 4:d931d24c2f81 | 75 | }; // +9 |
va009039 | 3:ae77d63a1eda | 76 | |
va009039 | 4:d931d24c2f81 | 77 | struct StandardEndpointDescriptor {// offset |
va009039 | 3:ae77d63a1eda | 78 | uint8_t bLength; // +0 |
va009039 | 3:ae77d63a1eda | 79 | uint8_t bDescriptorType; // +1 |
va009039 | 3:ae77d63a1eda | 80 | uint8_t bEndpointAddress; // +2 |
va009039 | 3:ae77d63a1eda | 81 | uint8_t bmAttributes; // +3 |
va009039 | 3:ae77d63a1eda | 82 | uint16_t wMaxPacketSize; // +4 |
va009039 | 3:ae77d63a1eda | 83 | uint8_t bInterval; // +6 |
va009039 | 4:d931d24c2f81 | 84 | }; // +7 |
va009039 | 3:ae77d63a1eda | 85 | |
va009039 | 5:8a2d056e9b38 | 86 | struct StandardStringDescriptor {// offset |
va009039 | 5:8a2d056e9b38 | 87 | uint8_t bLength; // +0 |
va009039 | 5:8a2d056e9b38 | 88 | uint8_t bDescriptorType; // +1 |
va009039 | 5:8a2d056e9b38 | 89 | char bString[0]; // +2 |
va009039 | 5:8a2d056e9b38 | 90 | }; // +3 |
va009039 | 5:8a2d056e9b38 | 91 | |
va009039 | 4:d931d24c2f81 | 92 | struct HubDescriptor { // offset |
va009039 | 3:ae77d63a1eda | 93 | uint8_t bDescLength; // +0 |
va009039 | 3:ae77d63a1eda | 94 | uint8_t bDescriptorType; // +1 |
va009039 | 3:ae77d63a1eda | 95 | uint8_t bNbrPorts; // +2 |
va009039 | 3:ae77d63a1eda | 96 | uint16_t wHubCharacteristics;// +3 |
va009039 | 3:ae77d63a1eda | 97 | uint8_t bPwrOn2PwrGood; // +5 |
va009039 | 3:ae77d63a1eda | 98 | uint8_t bHubContrCurrent; // +6 |
va009039 | 3:ae77d63a1eda | 99 | uint8_t DeviceRemovable; // +7 |
va009039 | 3:ae77d63a1eda | 100 | uint8_t PortPweCtrlMak; // +8 |
va009039 | 4:d931d24c2f81 | 101 | }; // +9 |
va009039 | 3:ae77d63a1eda | 102 | #pragma pack(pop) |
va009039 | 3:ae77d63a1eda | 103 | |
va009039 | 0:b7d6879637a8 | 104 | // ------------------ HcControl Register --------------------- |
va009039 | 0:b7d6879637a8 | 105 | #define OR_CONTROL_PLE 0x00000004 |
va009039 | 0:b7d6879637a8 | 106 | #define OR_CONTROL_IE 0x00000008 |
va009039 | 0:b7d6879637a8 | 107 | #define OR_CONTROL_CLE 0x00000010 |
va009039 | 0:b7d6879637a8 | 108 | #define OR_CONTROL_BLE 0x00000020 |
va009039 | 0:b7d6879637a8 | 109 | #define OR_CONTROL_HCFS 0x000000C0 |
va009039 | 0:b7d6879637a8 | 110 | #define OR_CONTROL_HC_OPER 0x00000080 |
va009039 | 0:b7d6879637a8 | 111 | // ----------------- HcCommandStatus Register ----------------- |
va009039 | 0:b7d6879637a8 | 112 | #define OR_CMD_STATUS_HCR 0x00000001 |
va009039 | 0:b7d6879637a8 | 113 | #define OR_CMD_STATUS_CLF 0x00000002 |
va009039 | 0:b7d6879637a8 | 114 | #define OR_CMD_STATUS_BLF 0x00000004 |
va009039 | 0:b7d6879637a8 | 115 | // --------------- HcInterruptStatus Register ----------------- |
va009039 | 0:b7d6879637a8 | 116 | #define OR_INTR_STATUS_WDH 0x00000002 |
va009039 | 0:b7d6879637a8 | 117 | #define OR_INTR_STATUS_UE 0x00000010 |
va009039 | 0:b7d6879637a8 | 118 | #define OR_INTR_STATUS_FNO 0x00000020 |
va009039 | 0:b7d6879637a8 | 119 | #define OR_INTR_STATUS_RHSC 0x00000040 |
va009039 | 0:b7d6879637a8 | 120 | // --------------- HcInterruptEnable Register ----------------- |
va009039 | 0:b7d6879637a8 | 121 | #define OR_INTR_ENABLE_WDH 0x00000002 |
va009039 | 0:b7d6879637a8 | 122 | #define OR_INTR_ENABLE_FNO 0x00000020 |
va009039 | 0:b7d6879637a8 | 123 | #define OR_INTR_ENABLE_RHSC 0x00000040 |
va009039 | 0:b7d6879637a8 | 124 | #define OR_INTR_ENABLE_MIE 0x80000000 |
va009039 | 0:b7d6879637a8 | 125 | // ---------------- HcRhDescriptorA Register ------------------ |
va009039 | 0:b7d6879637a8 | 126 | #define OR_RH_STATUS_LPSC 0x00010000 |
va009039 | 0:b7d6879637a8 | 127 | #define OR_RH_STATUS_DRWE 0x00008000 |
va009039 | 0:b7d6879637a8 | 128 | // -------------- HcRhPortStatus[1:NDP] Register -------------- |
va009039 | 0:b7d6879637a8 | 129 | #define OR_RH_PORT_CCS 0x00000001 |
va009039 | 0:b7d6879637a8 | 130 | #define OR_RH_PORT_PRS 0x00000010 |
va009039 | 0:b7d6879637a8 | 131 | #define OR_RH_PORT_CSC 0x00010000 |
va009039 | 0:b7d6879637a8 | 132 | #define OR_RH_PORT_PRSC 0x00100000 |
va009039 | 0:b7d6879637a8 | 133 | |
va009039 | 0:b7d6879637a8 | 134 | // TRANSFER DESCRIPTOR CONTROL FIELDS |
va009039 | 0:b7d6879637a8 | 135 | #define TD_ROUNDING (uint32_t)(0x00040000) /* Buffer Rounding */ |
va009039 | 0:b7d6879637a8 | 136 | #define TD_SETUP (uint32_t)(0x00000000) /* Direction of Setup Packet */ |
va009039 | 0:b7d6879637a8 | 137 | #define TD_IN (uint32_t)(0x00100000) /* Direction In */ |
va009039 | 0:b7d6879637a8 | 138 | #define TD_OUT (uint32_t)(0x00080000) /* Direction Out */ |
va009039 | 0:b7d6879637a8 | 139 | #define TD_DELAY_INT(x) (uint32_t)((x) << 21) /* Delay Interrupt */ |
va009039 | 0:b7d6879637a8 | 140 | #define TD_DI (uint32_t)(7<<21) /* desable interrupt */ |
va009039 | 0:b7d6879637a8 | 141 | #define TD_TOGGLE_0 (uint32_t)(0x02000000) /* Toggle 0 */ |
va009039 | 0:b7d6879637a8 | 142 | #define TD_TOGGLE_1 (uint32_t)(0x03000000) /* Toggle 1 */ |
va009039 | 0:b7d6879637a8 | 143 | #define TD_CC (uint32_t)(0xF0000000) /* Completion Code */ |
va009039 | 0:b7d6879637a8 | 144 | |
va009039 | 4:d931d24c2f81 | 145 | class BaseEp; |
va009039 | 4:d931d24c2f81 | 146 | struct HCTD { // HostController Transfer Descriptor |
va009039 | 4:d931d24c2f81 | 147 | __IO uint32_t Control; // +0 Transfer descriptor control |
va009039 | 4:d931d24c2f81 | 148 | __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer |
va009039 | 4:d931d24c2f81 | 149 | HCTD* Next; // +8 Physical pointer to next Transfer Descriptor |
va009039 | 4:d931d24c2f81 | 150 | uint8_t* BufEnd; // +12 Physical address of end of buffer |
va009039 | 4:d931d24c2f81 | 151 | uint8_t* buf_top; // +16 Buffer start address |
va009039 | 4:d931d24c2f81 | 152 | uint16_t buf_size; // +20 buffer size size |
va009039 | 4:d931d24c2f81 | 153 | uint8_t _dummy[10]; // +22 dummy |
va009039 | 4:d931d24c2f81 | 154 | BaseEp* ep; // +32 endpoint object |
va009039 | 4:d931d24c2f81 | 155 | // +36 |
va009039 | 4:d931d24c2f81 | 156 | HCTD(BaseEp* obj); |
va009039 | 4:d931d24c2f81 | 157 | inline void* operator new(size_t size) { |
va009039 | 4:d931d24c2f81 | 158 | void* p; |
va009039 | 4:d931d24c2f81 | 159 | if (posix_memalign(&p, 16, size) == 0) { |
va009039 | 4:d931d24c2f81 | 160 | return p; |
va009039 | 4:d931d24c2f81 | 161 | } |
va009039 | 4:d931d24c2f81 | 162 | return NULL; |
va009039 | 4:d931d24c2f81 | 163 | } |
va009039 | 0:b7d6879637a8 | 164 | |
va009039 | 4:d931d24c2f81 | 165 | inline void operator delete(void* p) { |
va009039 | 4:d931d24c2f81 | 166 | free(p); |
va009039 | 4:d931d24c2f81 | 167 | } |
va009039 | 4:d931d24c2f81 | 168 | |
va009039 | 4:d931d24c2f81 | 169 | inline void transfer(uint8_t* data, int len) { |
va009039 | 4:d931d24c2f81 | 170 | CurrBufPtr = data; |
va009039 | 4:d931d24c2f81 | 171 | buf_top = data; |
va009039 | 4:d931d24c2f81 | 172 | buf_size = len; |
va009039 | 4:d931d24c2f81 | 173 | BufEnd = const_cast<uint8_t*>(data)+len-1; |
va009039 | 4:d931d24c2f81 | 174 | } |
va009039 | 0:b7d6879637a8 | 175 | |
va009039 | 4:d931d24c2f81 | 176 | inline int status() { |
va009039 | 4:d931d24c2f81 | 177 | if (CurrBufPtr) { |
va009039 | 4:d931d24c2f81 | 178 | return CurrBufPtr - buf_top; |
va009039 | 4:d931d24c2f81 | 179 | } |
va009039 | 4:d931d24c2f81 | 180 | return buf_size; |
va009039 | 4:d931d24c2f81 | 181 | } |
va009039 | 4:d931d24c2f81 | 182 | |
va009039 | 4:d931d24c2f81 | 183 | inline uint8_t ConditionCode() { |
va009039 | 4:d931d24c2f81 | 184 | return Control>>28; |
va009039 | 4:d931d24c2f81 | 185 | } |
va009039 | 4:d931d24c2f81 | 186 | }; |
va009039 | 4:d931d24c2f81 | 187 | |
va009039 | 4:d931d24c2f81 | 188 | struct HCITD { // HostController Isochronous Transfer Descriptor |
va009039 | 0:b7d6879637a8 | 189 | __IO uint32_t Control; // +0 Transfer descriptor control |
va009039 | 0:b7d6879637a8 | 190 | uint8_t* BufferPage0; // +4 Buffer Page 0 |
va009039 | 4:d931d24c2f81 | 191 | HCITD* Next; // +8 Physical pointer to next Isochronous Transfer Descriptor |
va009039 | 0:b7d6879637a8 | 192 | uint8_t* BufferEnd; // +12 buffer End |
va009039 | 0:b7d6879637a8 | 193 | __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW |
va009039 | 4:d931d24c2f81 | 194 | BaseEp* ep; // +32 endpoint object |
va009039 | 0:b7d6879637a8 | 195 | __IO uint8_t buf[0]; // +36 buffer |
va009039 | 4:d931d24c2f81 | 196 | // +36 |
va009039 | 4:d931d24c2f81 | 197 | HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize); |
va009039 | 4:d931d24c2f81 | 198 | inline void* operator new(size_t size, int buf_size) { |
va009039 | 4:d931d24c2f81 | 199 | void* p; |
va009039 | 4:d931d24c2f81 | 200 | if (posix_memalign(&p, 32, size+buf_size) == 0) { |
va009039 | 4:d931d24c2f81 | 201 | return p; |
va009039 | 4:d931d24c2f81 | 202 | } |
va009039 | 4:d931d24c2f81 | 203 | return NULL; |
va009039 | 4:d931d24c2f81 | 204 | } |
va009039 | 4:d931d24c2f81 | 205 | |
va009039 | 4:d931d24c2f81 | 206 | inline void operator delete(void* p) { |
va009039 | 4:d931d24c2f81 | 207 | free(p); |
va009039 | 4:d931d24c2f81 | 208 | } |
va009039 | 0:b7d6879637a8 | 209 | |
va009039 | 4:d931d24c2f81 | 210 | inline uint16_t StartingFrame() { |
va009039 | 4:d931d24c2f81 | 211 | return Control & 0xffff; |
va009039 | 4:d931d24c2f81 | 212 | } |
va009039 | 4:d931d24c2f81 | 213 | |
va009039 | 4:d931d24c2f81 | 214 | inline uint8_t FrameCount() { |
va009039 | 4:d931d24c2f81 | 215 | return ((Control>>24)&7)+1; |
va009039 | 4:d931d24c2f81 | 216 | } |
va009039 | 4:d931d24c2f81 | 217 | |
va009039 | 4:d931d24c2f81 | 218 | inline uint8_t ConditionCode() { |
va009039 | 4:d931d24c2f81 | 219 | return Control>>28; |
va009039 | 4:d931d24c2f81 | 220 | } |
va009039 | 4:d931d24c2f81 | 221 | }; |
va009039 | 4:d931d24c2f81 | 222 | |
va009039 | 4:d931d24c2f81 | 223 | struct HCED { // HostController EndPoint Descriptor |
va009039 | 0:b7d6879637a8 | 224 | __IO uint32_t Control; // +0 Endpoint descriptor control |
va009039 | 0:b7d6879637a8 | 225 | HCTD* TailTd; // +4 Physical address of tail in Transfer descriptor list |
va009039 | 0:b7d6879637a8 | 226 | __IO HCTD* HeadTd; // +8 Physcial address of head in Transfer descriptor list |
va009039 | 4:d931d24c2f81 | 227 | HCED* Next; // +12 Physical address of next Endpoint descriptor |
va009039 | 4:d931d24c2f81 | 228 | // +16 |
va009039 | 4:d931d24c2f81 | 229 | HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed) { |
va009039 | 4:d931d24c2f81 | 230 | Control = addr | /* USB address */ |
va009039 | 4:d931d24c2f81 | 231 | ((ep & 0x7F) << 7) | /* Endpoint address */ |
va009039 | 4:d931d24c2f81 | 232 | (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */ |
va009039 | 4:d931d24c2f81 | 233 | ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */ |
va009039 | 4:d931d24c2f81 | 234 | (size << 16); /* MaxPkt Size */ |
va009039 | 4:d931d24c2f81 | 235 | Next = NULL; |
va009039 | 4:d931d24c2f81 | 236 | } |
va009039 | 4:d931d24c2f81 | 237 | |
va009039 | 4:d931d24c2f81 | 238 | inline void* operator new(size_t size) { |
va009039 | 4:d931d24c2f81 | 239 | void* p; |
va009039 | 4:d931d24c2f81 | 240 | if (posix_memalign(&p, 16, size) == 0) { |
va009039 | 4:d931d24c2f81 | 241 | return p; |
va009039 | 4:d931d24c2f81 | 242 | } |
va009039 | 4:d931d24c2f81 | 243 | return NULL; |
va009039 | 4:d931d24c2f81 | 244 | } |
va009039 | 4:d931d24c2f81 | 245 | |
va009039 | 4:d931d24c2f81 | 246 | inline void operator delete(void* p) { |
va009039 | 4:d931d24c2f81 | 247 | free(p); |
va009039 | 4:d931d24c2f81 | 248 | } |
va009039 | 4:d931d24c2f81 | 249 | |
va009039 | 4:d931d24c2f81 | 250 | inline uint8_t FunctionAddress() { |
va009039 | 4:d931d24c2f81 | 251 | return Control & 0x7f; |
va009039 | 4:d931d24c2f81 | 252 | } |
va009039 | 4:d931d24c2f81 | 253 | |
va009039 | 4:d931d24c2f81 | 254 | inline int Speed() { |
va009039 | 4:d931d24c2f81 | 255 | return (Control>>13)&1; |
va009039 | 4:d931d24c2f81 | 256 | } |
va009039 | 4:d931d24c2f81 | 257 | |
va009039 | 4:d931d24c2f81 | 258 | inline void setFunctionAddress(int addr) { |
va009039 | 4:d931d24c2f81 | 259 | Control &= ~0x7f; |
va009039 | 4:d931d24c2f81 | 260 | Control |= addr; |
va009039 | 4:d931d24c2f81 | 261 | } |
va009039 | 4:d931d24c2f81 | 262 | |
va009039 | 4:d931d24c2f81 | 263 | inline void setMaxPacketSize(uint16_t size) { |
va009039 | 4:d931d24c2f81 | 264 | Control &= ~0xffff0000; |
va009039 | 4:d931d24c2f81 | 265 | Control |= size<<16; |
va009039 | 4:d931d24c2f81 | 266 | } |
va009039 | 4:d931d24c2f81 | 267 | }; |
va009039 | 4:d931d24c2f81 | 268 | |
va009039 | 4:d931d24c2f81 | 269 | struct HCCA { // Host Controller Communication Area |
va009039 | 4:d931d24c2f81 | 270 | HCED* InterruptTable[32]; // +0 Interrupt Table |
va009039 | 4:d931d24c2f81 | 271 | __IO uint16_t FrameNumber;// +128 Frame Number |
va009039 | 4:d931d24c2f81 | 272 | __IO uint16_t Pad1; // +130 |
va009039 | 4:d931d24c2f81 | 273 | __IO HCTD* DoneHead; // +132 Done Head |
va009039 | 4:d931d24c2f81 | 274 | uint8_t Reserved[116]; // +136 Reserved for future use |
va009039 | 4:d931d24c2f81 | 275 | uint8_t Unknown[4]; // +252 Unused |
va009039 | 4:d931d24c2f81 | 276 | // +256 |
va009039 | 4:d931d24c2f81 | 277 | inline void* operator new(size_t size) { |
va009039 | 4:d931d24c2f81 | 278 | void* p; |
va009039 | 4:d931d24c2f81 | 279 | if (posix_memalign(&p, 256, size) == 0) { |
va009039 | 4:d931d24c2f81 | 280 | return p; |
va009039 | 4:d931d24c2f81 | 281 | } |
va009039 | 4:d931d24c2f81 | 282 | return NULL; |
va009039 | 4:d931d24c2f81 | 283 | } |
va009039 | 4:d931d24c2f81 | 284 | |
va009039 | 4:d931d24c2f81 | 285 | inline void operator delete(void* p) { |
va009039 | 4:d931d24c2f81 | 286 | free(p); |
va009039 | 4:d931d24c2f81 | 287 | } |
va009039 | 4:d931d24c2f81 | 288 | }; |
va009039 | 0:b7d6879637a8 | 289 | |
va009039 | 0:b7d6879637a8 | 290 | class BaseUsbHost { |
va009039 | 0:b7d6879637a8 | 291 | public: |
va009039 | 0:b7d6879637a8 | 292 | BaseUsbHost(); |
va009039 | 0:b7d6879637a8 | 293 | void irqHandler(); |
va009039 | 0:b7d6879637a8 | 294 | // report |
va009039 | 0:b7d6879637a8 | 295 | uint32_t m_report_irq; |
va009039 | 0:b7d6879637a8 | 296 | uint32_t m_report_RHSC; |
va009039 | 0:b7d6879637a8 | 297 | uint32_t m_report_FNO; |
va009039 | 0:b7d6879637a8 | 298 | uint32_t m_report_WDH; |
va009039 | 0:b7d6879637a8 | 299 | uint32_t m_report_sp; |
va009039 | 3:ae77d63a1eda | 300 | private: |
va009039 | 3:ae77d63a1eda | 301 | void init_hw_ohci(HCCA* pHcca); |
va009039 | 3:ae77d63a1eda | 302 | void ResetRootHub(); |
va009039 | 3:ae77d63a1eda | 303 | HCCA* m_pHcca; |
va009039 | 0:b7d6879637a8 | 304 | }; |
va009039 | 0:b7d6879637a8 | 305 | |
va009039 | 0:b7d6879637a8 | 306 | #define HCTD_QUEUE_SIZE 3 |
va009039 | 0:b7d6879637a8 | 307 | |
va009039 | 0:b7d6879637a8 | 308 | class BaseEp { // endpoint |
va009039 | 0:b7d6879637a8 | 309 | public: |
va009039 | 0:b7d6879637a8 | 310 | BaseEp(int addr, uint8_t ep = 0, uint16_t size = 8, int lowSpeed = 0); |
va009039 | 0:b7d6879637a8 | 311 | int GetAddr(); |
va009039 | 0:b7d6879637a8 | 312 | int GetLowSpeed(); |
va009039 | 0:b7d6879637a8 | 313 | void update_FunctionAddress(int addr); |
va009039 | 0:b7d6879637a8 | 314 | void update_MaxPacketSize(uint16_t size); |
va009039 | 3:ae77d63a1eda | 315 | int transfer(uint8_t* buf, int len); |
va009039 | 3:ae77d63a1eda | 316 | int status(uint32_t millisec=osWaitForever); |
va009039 | 0:b7d6879637a8 | 317 | // |
va009039 | 3:ae77d63a1eda | 318 | virtual void enable() = 0; |
va009039 | 3:ae77d63a1eda | 319 | virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} // WDH |
va009039 | 0:b7d6879637a8 | 320 | int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever); |
va009039 | 0:b7d6879637a8 | 321 | // report |
va009039 | 0:b7d6879637a8 | 322 | uint8_t m_ConditionCode; |
va009039 | 0:b7d6879637a8 | 323 | int m_report_queue_error; |
va009039 | 3:ae77d63a1eda | 324 | protected: |
va009039 | 3:ae77d63a1eda | 325 | int send_receive(uint8_t* buf, int len, int millisec); |
va009039 | 3:ae77d63a1eda | 326 | HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever); |
va009039 | 3:ae77d63a1eda | 327 | HCED* m_pED; |
va009039 | 3:ae77d63a1eda | 328 | Queue<HCTD, HCTD_QUEUE_SIZE> m_queue; // TD done queue |
va009039 | 3:ae77d63a1eda | 329 | int m_td_queue_count; |
va009039 | 0:b7d6879637a8 | 330 | }; |
va009039 | 0:b7d6879637a8 | 331 | |
va009039 | 0:b7d6879637a8 | 332 | class ControlEp : public BaseEp { |
va009039 | 0:b7d6879637a8 | 333 | public: |
va009039 | 0:b7d6879637a8 | 334 | ControlEp(int lowSpeed = 0); |
va009039 | 0:b7d6879637a8 | 335 | int GetDescriptor(int descType, int descIndex, uint8_t* data, int length); |
va009039 | 0:b7d6879637a8 | 336 | int SetAddress(int addr); // device address |
va009039 | 0:b7d6879637a8 | 337 | int SetConfiguration(int config); |
va009039 | 0:b7d6879637a8 | 338 | int GetConfiguration(int *config); |
va009039 | 0:b7d6879637a8 | 339 | int SetInterfaceAlternate(int interface, int alternate); |
va009039 | 0:b7d6879637a8 | 340 | int GetInterface(int interface, int *alternate); |
va009039 | 0:b7d6879637a8 | 341 | int controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex=0, const uint8_t* data=NULL, int length=0); |
va009039 | 0:b7d6879637a8 | 342 | int controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t* data, int length); |
va009039 | 5:8a2d056e9b38 | 343 | string GetStringDescriptor(int index); |
va009039 | 3:ae77d63a1eda | 344 | private: |
va009039 | 0:b7d6879637a8 | 345 | int open(int addr); |
va009039 | 3:ae77d63a1eda | 346 | virtual void enable(){}; |
va009039 | 0:b7d6879637a8 | 347 | }; |
va009039 | 0:b7d6879637a8 | 348 | |
va009039 | 0:b7d6879637a8 | 349 | class BulkEp : public BaseEp { |
va009039 | 0:b7d6879637a8 | 350 | public: |
va009039 | 0:b7d6879637a8 | 351 | BulkEp(int addr, uint8_t ep, uint16_t size); |
va009039 | 1:3b7bc4f87a61 | 352 | int bulkSend(const uint8_t* buf, int len, int millisec=osWaitForever); |
va009039 | 1:3b7bc4f87a61 | 353 | int bulkReceive(uint8_t* buf, int len, int millisec=osWaitForever); |
va009039 | 3:ae77d63a1eda | 354 | private: |
va009039 | 3:ae77d63a1eda | 355 | virtual void enable(); |
va009039 | 0:b7d6879637a8 | 356 | }; |
va009039 | 0:b7d6879637a8 | 357 | |
va009039 | 0:b7d6879637a8 | 358 | class InterruptEp : public BaseEp { |
va009039 | 0:b7d6879637a8 | 359 | public: |
va009039 | 0:b7d6879637a8 | 360 | InterruptEp(int addr, uint8_t ep, uint16_t size, int lowSpeed=0); |
va009039 | 1:3b7bc4f87a61 | 361 | int interruptReceive(uint8_t* buf, int len, int millisec=osWaitForever); |
va009039 | 3:ae77d63a1eda | 362 | private: |
va009039 | 3:ae77d63a1eda | 363 | virtual void enable(); |
va009039 | 0:b7d6879637a8 | 364 | }; |
va009039 | 0:b7d6879637a8 | 365 | |
va009039 | 0:b7d6879637a8 | 366 | class IsochronousEp : public BaseEp { |
va009039 | 0:b7d6879637a8 | 367 | public: |
va009039 | 0:b7d6879637a8 | 368 | IsochronousEp(int addr, uint8_t ep, uint16_t size); |
va009039 | 3:ae77d63a1eda | 369 | void reset(int delay_ms = 100); |
va009039 | 2:fe1e62051d88 | 370 | HCITD* isochronousReveive(int millisec=osWaitForever); |
va009039 | 2:fe1e62051d88 | 371 | int isochronousSend(uint8_t* buf, int len, int millisec=osWaitForever); |
va009039 | 3:ae77d63a1eda | 372 | HCITD* get_queue_HCITD(int millisec); |
va009039 | 4:d931d24c2f81 | 373 | uint16_t m_PacketSize; |
va009039 | 3:ae77d63a1eda | 374 | private: |
va009039 | 4:d931d24c2f81 | 375 | HCITD* new_HCITD(BaseEp* obj); |
va009039 | 0:b7d6879637a8 | 376 | int m_itd_queue_count; |
va009039 | 0:b7d6879637a8 | 377 | uint16_t m_FrameNumber; |
va009039 | 0:b7d6879637a8 | 378 | int m_FrameCount; // 1-8 |
va009039 | 3:ae77d63a1eda | 379 | virtual void enable(); |
va009039 | 0:b7d6879637a8 | 380 | }; |
va009039 | 0:b7d6879637a8 | 381 | |
va009039 | 1:3b7bc4f87a61 | 382 | // --- HUB -------------------------------------------------- |
va009039 | 0:b7d6879637a8 | 383 | class UsbHub { |
va009039 | 0:b7d6879637a8 | 384 | public: |
va009039 | 0:b7d6879637a8 | 385 | UsbHub(ControlEp* ctlEp = NULL); |
va009039 | 3:ae77d63a1eda | 386 | static bool check(ControlEp* ctlEp); |
va009039 | 2:fe1e62051d88 | 387 | int SetPortPower(int port); |
va009039 | 2:fe1e62051d88 | 388 | int ClearPortPower(int port); |
va009039 | 3:ae77d63a1eda | 389 | vector<ControlEp*> PortEp; |
va009039 | 4:d931d24c2f81 | 390 | template<class T> ControlEp* search(int skip = 0) { |
va009039 | 4:d931d24c2f81 | 391 | for(vector<ControlEp*>::iterator it = PortEp.begin(); it != PortEp.end(); ++it) { |
va009039 | 4:d931d24c2f81 | 392 | if (T::check(*it)) { |
va009039 | 4:d931d24c2f81 | 393 | if (skip-- <= 0) { |
va009039 | 4:d931d24c2f81 | 394 | return *it; |
va009039 | 4:d931d24c2f81 | 395 | } |
va009039 | 4:d931d24c2f81 | 396 | } |
va009039 | 4:d931d24c2f81 | 397 | } |
va009039 | 4:d931d24c2f81 | 398 | return NULL; |
va009039 | 4:d931d24c2f81 | 399 | } |
va009039 | 4:d931d24c2f81 | 400 | template<class T> ControlEp* assign(int port) { |
va009039 | 4:d931d24c2f81 | 401 | if (port >= 0 && port < PortEp.size()) { |
va009039 | 4:d931d24c2f81 | 402 | return PortEp[port]; |
va009039 | 4:d931d24c2f81 | 403 | } |
va009039 | 4:d931d24c2f81 | 404 | return NULL; |
va009039 | 4:d931d24c2f81 | 405 | } |
va009039 | 3:ae77d63a1eda | 406 | private: |
va009039 | 0:b7d6879637a8 | 407 | int PortReset(int port); |
va009039 | 0:b7d6879637a8 | 408 | int SetPortFeature(int feature, int index); |
va009039 | 0:b7d6879637a8 | 409 | int ClearPortFeature(int feature, int index); |
va009039 | 0:b7d6879637a8 | 410 | int SetPortReset(int port); |
va009039 | 0:b7d6879637a8 | 411 | int GetPortStatus(int port, uint32_t* status); |
va009039 | 0:b7d6879637a8 | 412 | ControlEp* m_ctlEp; |
va009039 | 0:b7d6879637a8 | 413 | }; |
va009039 | 0:b7d6879637a8 | 414 | |
va009039 | 1:3b7bc4f87a61 | 415 | // --- UVC -------------------------------------------------- |
va009039 | 1:3b7bc4f87a61 | 416 | #define _30FPS 333333 |
va009039 | 1:3b7bc4f87a61 | 417 | #define _25FPS 400000 |
va009039 | 1:3b7bc4f87a61 | 418 | #define _20FPS 500000 |
va009039 | 1:3b7bc4f87a61 | 419 | #define _15FPS 666666 |
va009039 | 1:3b7bc4f87a61 | 420 | #define _10FPS 1000000 |
va009039 | 1:3b7bc4f87a61 | 421 | #define _5FPS 2000000 |
va009039 | 1:3b7bc4f87a61 | 422 | #define _1FPS 10000000 |
va009039 | 1:3b7bc4f87a61 | 423 | |
va009039 | 1:3b7bc4f87a61 | 424 | #define SET_CUR 0x01 |
va009039 | 1:3b7bc4f87a61 | 425 | #define GET_CUR 0x81 |
va009039 | 1:3b7bc4f87a61 | 426 | #define GET_MIN 0x82 |
va009039 | 1:3b7bc4f87a61 | 427 | #define GET_MAX 0x83 |
va009039 | 1:3b7bc4f87a61 | 428 | #define GET_RES 0x84 |
va009039 | 1:3b7bc4f87a61 | 429 | #define GET_LEN 0x85 |
va009039 | 1:3b7bc4f87a61 | 430 | #define GET_INFO 0x86 |
va009039 | 1:3b7bc4f87a61 | 431 | #define GET_DEF 0x87 |
va009039 | 1:3b7bc4f87a61 | 432 | |
va009039 | 1:3b7bc4f87a61 | 433 | #define VS_PROBE_CONTROL 0x01 |
va009039 | 1:3b7bc4f87a61 | 434 | #define VS_COMMIT_CONTROL 0x02 |
va009039 | 1:3b7bc4f87a61 | 435 | |
va009039 | 1:3b7bc4f87a61 | 436 | class BaseUvc { |
va009039 | 1:3b7bc4f87a61 | 437 | public: |
va009039 | 2:fe1e62051d88 | 438 | void poll(int millisec=osWaitForever); |
va009039 | 1:3b7bc4f87a61 | 439 | int Control(int req, int cs, int index, uint8_t* buf, int size); |
va009039 | 1:3b7bc4f87a61 | 440 | ControlEp* m_ctlEp; |
va009039 | 1:3b7bc4f87a61 | 441 | IsochronousEp* m_isoEp; |
va009039 | 1:3b7bc4f87a61 | 442 | uint32_t report_cc_count[16]; // ConditionCode |
va009039 | 1:3b7bc4f87a61 | 443 | uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode |
va009039 | 1:3b7bc4f87a61 | 444 | // callback |
va009039 | 1:3b7bc4f87a61 | 445 | void onResult(uint16_t frame, uint8_t* buf, int len); |
va009039 | 1:3b7bc4f87a61 | 446 | void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) ); |
va009039 | 1:3b7bc4f87a61 | 447 | class CDummy; |
va009039 | 1:3b7bc4f87a61 | 448 | template<class T> |
va009039 | 1:3b7bc4f87a61 | 449 | void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) ) |
va009039 | 1:3b7bc4f87a61 | 450 | { |
va009039 | 1:3b7bc4f87a61 | 451 | m_pCb = NULL; |
va009039 | 1:3b7bc4f87a61 | 452 | m_pCbItem = (CDummy*) pItem; |
va009039 | 1:3b7bc4f87a61 | 453 | m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod; |
va009039 | 1:3b7bc4f87a61 | 454 | } |
va009039 | 1:3b7bc4f87a61 | 455 | void clearOnResult(); |
va009039 | 1:3b7bc4f87a61 | 456 | CDummy* m_pCbItem; |
va009039 | 1:3b7bc4f87a61 | 457 | void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int); |
va009039 | 1:3b7bc4f87a61 | 458 | void (*m_pCb)(uint16_t, uint8_t*, int); |
va009039 | 1:3b7bc4f87a61 | 459 | }; |