USB host library, support isochronous,bulk,interrupt and control.

Dependents:   BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseUsbHost.h Source File

BaseUsbHost.h

00001 // BaseUsbHost.h 2013/2/11
00002 #pragma once
00003 #include <vector>
00004 #include <string>
00005 
00006 #define USB_OK            0
00007 #define USB_PROCESSING   -1
00008 #define USB_ERROR        -2
00009 #define USB_ERROR_MEMORY -3
00010 #define USB_ERROR_STALL  -4
00011 #define USB_ERROR_DEVICE_NOT_RESPONDING -5
00012 
00013 // USB STANDARD REQUEST DEFINITIONS
00014 #define  USB_DESCRIPTOR_TYPE_DEVICE         1
00015 #define  USB_DESCRIPTOR_TYPE_CONFIGURATION  2
00016 #define  USB_DESCRIPTOR_TYPE_STRING         3
00017 #define  USB_DESCRIPTOR_TYPE_INTERFACE      4
00018 #define  USB_DESCRIPTOR_TYPE_ENDPOINT       5
00019 #define  USB_DESCRIPTOR_TYPE_HUB         0x29
00020 // ----------- Control RequestType Fields  -----------
00021 #define  USB_DEVICE_TO_HOST      0x80
00022 #define  USB_HOST_TO_DEVICE      0x00
00023 #define  USB_REQUEST_TYPE_CLASS  0x20
00024 #define  USB_RECIPIENT_DEVICE    0x00
00025 #define  USB_RECIPIENT_INTERFACE 0x01
00026 #define  USB_RECIPIENT_OTHER     0x03
00027 // -------------- USB Standard Requests  --------------
00028 #define  GET_STATUS              0
00029 #define  CLEAR_FEATURE           1
00030 #define  SET_FEATURE             3
00031 #define  SET_ADDRESS             5
00032 #define  GET_DESCRIPTOR          6
00033 #define  SET_CONFIGURATION       9
00034 #define  SET_INTERFACE           11
00035 
00036 #pragma pack(push,1)
00037 struct StandardDeviceDescriptor {// offset 
00038     uint8_t bLength;            // +0
00039     uint8_t bDescriptorType;    // +1
00040     uint16_t bcdUSB;            // +2
00041     uint8_t bDeviceClass;       // +4
00042     uint8_t bDeviceSubClass;    // +5
00043     uint8_t bDeviceProtocol;    // +6
00044     uint8_t bMaxPacketSize;     // +7
00045     uint16_t idVendor;          // +8
00046     uint16_t idProduct;         // +10
00047     uint16_t bcdDevice;         // +12
00048     uint8_t iManufacturer;      // +14
00049     uint8_t iProduct;           // +15
00050     uint8_t iSerialNumber;      // +16
00051     uint8_t bNumConfigurations; // +17
00052 };                              // +18
00053 
00054 struct StandardConfigurationDescriptor {// offset
00055     uint8_t bLength;               // +0
00056     uint8_t bDescriptorType;       // +1
00057     uint16_t wTotalLength;         // +2
00058     uint8_t bNumInterfaces;        // +4
00059     uint8_t bConfigurationValue;   // +5
00060     uint8_t iConfiguration;        // +6
00061     uint8_t bmAttributes;          // +7
00062     uint8_t bMaxPower;             // +8
00063 };                                 // +9
00064 
00065 struct StandardInterfaceDescriptor {// offset
00066     uint8_t bLength;           // +0      
00067     uint8_t bDescriptorType;   // +1
00068     uint8_t bInterfaceNumber;  // +2
00069     uint8_t bAlternateSetting; // +3
00070     uint8_t bNumEndpoints;     // +4
00071     uint8_t bInterfaceClass;   // +5
00072     uint8_t bInterfaceSubClass;// +6
00073     uint8_t bInterfaceProtocol;// +7
00074     uint8_t iInterface;        // +8
00075 };                             // +9
00076 
00077 struct StandardEndpointDescriptor {// offset
00078     uint8_t bLength;          // +0
00079     uint8_t bDescriptorType;  // +1
00080     uint8_t bEndpointAddress; // +2
00081     uint8_t bmAttributes;     // +3
00082     uint16_t wMaxPacketSize;  // +4
00083     uint8_t bInterval;        // +6
00084 };                            // +7
00085 
00086 struct StandardStringDescriptor {// offset
00087     uint8_t bLength;          // +0
00088     uint8_t bDescriptorType;  // +1
00089     char bString[0];          // +2
00090 };                            // +3
00091 
00092 struct HubDescriptor {        // offset
00093     uint8_t bDescLength;      // +0
00094     uint8_t bDescriptorType;  // +1
00095     uint8_t bNbrPorts;        // +2
00096     uint16_t wHubCharacteristics;// +3
00097     uint8_t bPwrOn2PwrGood;   // +5
00098     uint8_t bHubContrCurrent; // +6
00099     uint8_t DeviceRemovable;  // +7
00100     uint8_t PortPweCtrlMak;   // +8
00101 };                            // +9
00102 #pragma pack(pop)
00103 
00104 // ------------------ HcControl Register ---------------------
00105 #define  OR_CONTROL_PLE                 0x00000004
00106 #define  OR_CONTROL_IE                  0x00000008
00107 #define  OR_CONTROL_CLE                 0x00000010
00108 #define  OR_CONTROL_BLE                 0x00000020
00109 #define  OR_CONTROL_HCFS                0x000000C0
00110 #define  OR_CONTROL_HC_OPER             0x00000080
00111 // ----------------- HcCommandStatus Register -----------------
00112 #define  OR_CMD_STATUS_HCR              0x00000001
00113 #define  OR_CMD_STATUS_CLF              0x00000002
00114 #define  OR_CMD_STATUS_BLF              0x00000004
00115 // --------------- HcInterruptStatus Register -----------------
00116 #define  OR_INTR_STATUS_WDH             0x00000002
00117 #define  OR_INTR_STATUS_UE              0x00000010
00118 #define  OR_INTR_STATUS_FNO             0x00000020
00119 #define  OR_INTR_STATUS_RHSC            0x00000040
00120 // --------------- HcInterruptEnable Register -----------------
00121 #define  OR_INTR_ENABLE_WDH             0x00000002
00122 #define  OR_INTR_ENABLE_FNO             0x00000020
00123 #define  OR_INTR_ENABLE_RHSC            0x00000040
00124 #define  OR_INTR_ENABLE_MIE             0x80000000
00125 // ---------------- HcRhDescriptorA Register ------------------
00126 #define  OR_RH_STATUS_LPSC              0x00010000
00127 #define  OR_RH_STATUS_DRWE              0x00008000
00128 // -------------- HcRhPortStatus[1:NDP] Register --------------
00129 #define  OR_RH_PORT_CCS                 0x00000001
00130 #define  OR_RH_PORT_PRS                 0x00000010
00131 #define  OR_RH_PORT_CSC                 0x00010000
00132 #define  OR_RH_PORT_PRSC                0x00100000
00133 
00134 // TRANSFER DESCRIPTOR CONTROL FIELDS
00135 #define  TD_ROUNDING     (uint32_t)(0x00040000) /* Buffer Rounding */
00136 #define  TD_SETUP        (uint32_t)(0x00000000) /* Direction of Setup Packet */
00137 #define  TD_IN           (uint32_t)(0x00100000) /* Direction In */
00138 #define  TD_OUT          (uint32_t)(0x00080000) /* Direction Out */
00139 #define  TD_DELAY_INT(x) (uint32_t)((x) << 21)  /* Delay Interrupt */
00140 #define  TD_DI           (uint32_t)(7<<21)      /* desable interrupt */
00141 #define  TD_TOGGLE_0     (uint32_t)(0x02000000) /* Toggle 0 */
00142 #define  TD_TOGGLE_1     (uint32_t)(0x03000000) /* Toggle 1 */
00143 #define  TD_CC           (uint32_t)(0xF0000000) /* Completion Code */
00144 
00145 class BaseEp;
00146 struct HCTD {    // HostController Transfer Descriptor
00147     __IO uint32_t Control;    // +0 Transfer descriptor control
00148     __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer
00149     HCTD* Next;               // +8 Physical pointer to next Transfer Descriptor
00150     uint8_t*  BufEnd;         // +12 Physical address of end of buffer
00151     uint8_t* buf_top;         // +16 Buffer start address
00152     uint16_t buf_size;        // +20 buffer size size
00153     uint8_t _dummy[10];       // +22 dummy
00154     BaseEp* ep;               // +32 endpoint object
00155                               // +36
00156     HCTD(BaseEp* obj);
00157     inline void* operator new(size_t size) {
00158         void* p;
00159         if (posix_memalign(&p, 16, size) == 0) {
00160             return p;
00161         }
00162         return NULL;
00163     }
00164 
00165     inline void operator delete(void* p) {
00166         free(p);
00167     }
00168 
00169     inline void transfer(uint8_t* data, int len) {
00170         CurrBufPtr = data;
00171         buf_top = data;
00172         buf_size = len;
00173         BufEnd = const_cast<uint8_t*>(data)+len-1;
00174     }
00175 
00176     inline int status() {
00177         if (CurrBufPtr) {
00178             return CurrBufPtr - buf_top;
00179         }
00180         return buf_size;
00181     }
00182     
00183     inline uint8_t ConditionCode() {
00184         return Control>>28;
00185     }    
00186 }; 
00187 
00188 struct HCITD {    // HostController Isochronous Transfer Descriptor
00189     __IO uint32_t Control;      // +0 Transfer descriptor control
00190     uint8_t*  BufferPage0;      // +4 Buffer Page 0
00191     HCITD* Next;                // +8 Physical pointer to next Isochronous Transfer Descriptor
00192     uint8_t*  BufferEnd;        // +12 buffer End
00193     __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
00194     BaseEp* ep;                 // +32 endpoint object
00195     __IO uint8_t buf[0];        // +36 buffer
00196                                 // +36
00197     HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize);
00198     inline void* operator new(size_t size, int buf_size) {
00199         void* p;
00200         if (posix_memalign(&p, 32, size+buf_size) == 0) {
00201             return p;
00202         }
00203         return NULL;
00204     }
00205 
00206     inline void operator delete(void* p) {
00207         free(p);
00208     }
00209 
00210     inline uint16_t StartingFrame() {
00211         return Control & 0xffff;
00212     }
00213 
00214     inline uint8_t FrameCount() {
00215         return ((Control>>24)&7)+1;
00216     }    
00217 
00218     inline uint8_t ConditionCode() {
00219         return Control>>28;
00220     }
00221 };
00222 
00223 struct HCED {    // HostController EndPoint Descriptor
00224     __IO uint32_t Control; // +0 Endpoint descriptor control
00225     HCTD* TailTd;          // +4 Physical address of tail in Transfer descriptor list
00226     __IO HCTD* HeadTd;     // +8 Physcial address of head in Transfer descriptor list
00227     HCED* Next;            // +12 Physical address of next Endpoint descriptor
00228                            // +16
00229     HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed) {
00230         Control =  addr            | /* USB address */
00231         ((ep & 0x7F) << 7)         | /* Endpoint address */
00232         (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
00233         ((lowSpeed?1:0) << 13)     | /* speed full=0 low=1 */
00234         (size << 16);                /* MaxPkt Size */
00235         Next = NULL;
00236     }
00237 
00238     inline void* operator new(size_t size) {
00239         void* p;
00240         if (posix_memalign(&p, 16, size) == 0) {
00241             return p;
00242         }
00243         return NULL;
00244     }
00245 
00246     inline void operator delete(void* p) {
00247         free(p);
00248     }
00249 
00250     inline uint8_t FunctionAddress() {
00251         return Control & 0x7f;
00252     }
00253 
00254     inline int Speed() {
00255         return (Control>>13)&1;
00256     }
00257 
00258     inline void setFunctionAddress(int addr) {
00259         Control &= ~0x7f;
00260         Control |= addr;
00261     }
00262 
00263     inline void setMaxPacketSize(uint16_t size) {
00264         Control &= ~0xffff0000;
00265         Control |= size<<16;
00266     }
00267 };
00268 
00269 struct HCCA {    // Host Controller Communication Area
00270     HCED* InterruptTable[32]; // +0 Interrupt Table
00271     __IO uint16_t FrameNumber;// +128 Frame Number
00272     __IO uint16_t Pad1;       // +130
00273     __IO HCTD* DoneHead;      // +132 Done Head
00274     uint8_t Reserved[116];    // +136 Reserved for future use
00275     uint8_t Unknown[4];       // +252 Unused
00276                               // +256
00277     inline void* operator new(size_t size) {
00278         void* p;
00279         if (posix_memalign(&p, 256, size) == 0) {
00280             return p;
00281         }
00282         return NULL;
00283     }
00284 
00285     inline void operator delete(void* p) {
00286         free(p);
00287     }
00288 };
00289 
00290 class BaseUsbHost {
00291 public:
00292     BaseUsbHost();
00293     void irqHandler();
00294     // report
00295     uint32_t m_report_irq; 
00296     uint32_t m_report_RHSC;
00297     uint32_t m_report_FNO; 
00298     uint32_t m_report_WDH;  
00299     uint32_t m_report_sp;
00300 private:
00301     void init_hw_ohci(HCCA* pHcca);
00302     void ResetRootHub();
00303     HCCA* m_pHcca;
00304 };
00305 
00306 #define HCTD_QUEUE_SIZE 3
00307 
00308 class BaseEp { // endpoint
00309 public:
00310     BaseEp(int addr, uint8_t ep = 0, uint16_t size = 8, int lowSpeed = 0);
00311     int GetAddr();
00312     int GetLowSpeed();
00313     void update_FunctionAddress(int addr);
00314     void update_MaxPacketSize(uint16_t size);
00315     int transfer(uint8_t* buf, int len);
00316     int status(uint32_t millisec=osWaitForever);
00317     //
00318     virtual void enable() = 0;
00319     virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} // WDH
00320     int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever);
00321     // report
00322     uint8_t m_ConditionCode;
00323     int m_report_queue_error;
00324 protected:
00325     int send_receive(uint8_t* buf, int len, int millisec);
00326     HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever);
00327     HCED* m_pED;
00328     Queue<HCTD, HCTD_QUEUE_SIZE> m_queue; // TD done queue
00329     int m_td_queue_count;
00330 };
00331 
00332 class ControlEp : public BaseEp {
00333 public:
00334     ControlEp(int lowSpeed = 0);
00335     int GetDescriptor(int descType, int descIndex, uint8_t* data, int length);
00336     int SetAddress(int addr); // device address 
00337     int SetConfiguration(int config);
00338     int GetConfiguration(int *config);
00339     int SetInterfaceAlternate(int interface, int alternate);
00340     int GetInterface(int interface, int *alternate);
00341     int controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex=0, const uint8_t* data=NULL, int length=0);
00342     int controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t* data, int length);
00343     string GetStringDescriptor(int index);
00344 private:
00345     int open(int addr);
00346     virtual void enable(){};
00347 };
00348 
00349 class BulkEp : public BaseEp {
00350 public:
00351     BulkEp(int addr, uint8_t ep, uint16_t size);
00352     int bulkSend(const uint8_t* buf, int len, int millisec=osWaitForever);
00353     int bulkReceive(uint8_t* buf, int len, int millisec=osWaitForever);
00354 private:
00355     virtual void enable();
00356 };
00357 
00358 class InterruptEp : public BaseEp {
00359 public:
00360     InterruptEp(int addr, uint8_t ep, uint16_t size, int lowSpeed=0);
00361     int interruptReceive(uint8_t* buf, int len, int millisec=osWaitForever);
00362 private:
00363     virtual void enable();
00364 };
00365 
00366 class IsochronousEp : public BaseEp {
00367 public:
00368     IsochronousEp(int addr, uint8_t ep, uint16_t size);
00369     void reset(int delay_ms = 100);
00370     HCITD* isochronousReveive(int millisec=osWaitForever);
00371     int isochronousSend(uint8_t* buf, int len, int millisec=osWaitForever);
00372     HCITD* get_queue_HCITD(int millisec);
00373     uint16_t m_PacketSize;
00374 private:
00375     HCITD* new_HCITD(BaseEp* obj);
00376     int m_itd_queue_count;
00377     uint16_t m_FrameNumber;
00378     int m_FrameCount; // 1-8
00379     virtual void enable();
00380 };
00381 
00382 // --- HUB --------------------------------------------------
00383 class UsbHub {
00384 public:
00385     UsbHub(ControlEp* ctlEp = NULL);
00386     static bool check(ControlEp* ctlEp);
00387     int SetPortPower(int port);
00388     int ClearPortPower(int port);
00389     vector<ControlEp*> PortEp;
00390     template<class T> ControlEp* search(int skip = 0) {
00391         for(vector<ControlEp*>::iterator it = PortEp.begin(); it != PortEp.end(); ++it) {
00392             if (T::check(*it)) {
00393                 if (skip-- <= 0) {
00394                     return *it;
00395                 }
00396             }
00397         }
00398         return NULL;   
00399     }
00400     template<class T> ControlEp* assign(int port) {
00401         if (port >= 0 && port < PortEp.size()) {
00402             return PortEp[port];
00403         }
00404         return NULL;
00405     }
00406 private:
00407     int PortReset(int port);
00408     int SetPortFeature(int feature, int index);
00409     int ClearPortFeature(int feature, int index);
00410     int SetPortReset(int port);
00411     int GetPortStatus(int port, uint32_t* status);
00412     ControlEp* m_ctlEp;
00413 };
00414 
00415 // --- UVC --------------------------------------------------
00416 #define _30FPS  333333
00417 #define _25FPS  400000
00418 #define _20FPS  500000
00419 #define _15FPS  666666
00420 #define _10FPS 1000000
00421 #define _5FPS  2000000
00422 #define _1FPS 10000000
00423 
00424 #define SET_CUR  0x01
00425 #define GET_CUR  0x81
00426 #define GET_MIN  0x82
00427 #define GET_MAX  0x83
00428 #define GET_RES  0x84
00429 #define GET_LEN  0x85
00430 #define GET_INFO 0x86
00431 #define GET_DEF  0x87
00432 
00433 #define VS_PROBE_CONTROL  0x01
00434 #define VS_COMMIT_CONTROL 0x02
00435 
00436 class BaseUvc {
00437 public:
00438     void poll(int millisec=osWaitForever);
00439     int Control(int req, int cs, int index, uint8_t* buf, int size);
00440     ControlEp* m_ctlEp;
00441     IsochronousEp* m_isoEp;
00442     uint32_t report_cc_count[16];  // ConditionCode
00443     uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode
00444     // callback
00445     void onResult(uint16_t frame, uint8_t* buf, int len);
00446     void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) );
00447     class CDummy;
00448     template<class T> 
00449     void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) )
00450     {
00451         m_pCb = NULL;
00452         m_pCbItem = (CDummy*) pItem;
00453         m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod;
00454     }
00455     void clearOnResult();
00456     CDummy* m_pCbItem;
00457     void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int);
00458     void (*m_pCb)(uint16_t, uint8_t*, int);
00459 };