USB host library, support isochronous,bulk,interrupt and control.
Dependents: BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example
Import programBaseUsbHost_example
BaseUsbHost example program
BaseUsbHost.h
- Committer:
- va009039
- Date:
- 2013-02-11
- Revision:
- 5:8a2d056e9b38
- Parent:
- 4:d931d24c2f81
File content as of revision 5:8a2d056e9b38:
// BaseUsbHost.h 2013/2/11 #pragma once #include <vector> #include <string> #define USB_OK 0 #define USB_PROCESSING -1 #define USB_ERROR -2 #define USB_ERROR_MEMORY -3 #define USB_ERROR_STALL -4 #define USB_ERROR_DEVICE_NOT_RESPONDING -5 // USB STANDARD REQUEST DEFINITIONS #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_HUB 0x29 // ----------- Control RequestType Fields ----------- #define USB_DEVICE_TO_HOST 0x80 #define USB_HOST_TO_DEVICE 0x00 #define USB_REQUEST_TYPE_CLASS 0x20 #define USB_RECIPIENT_DEVICE 0x00 #define USB_RECIPIENT_INTERFACE 0x01 #define USB_RECIPIENT_OTHER 0x03 // -------------- USB Standard Requests -------------- #define GET_STATUS 0 #define CLEAR_FEATURE 1 #define SET_FEATURE 3 #define SET_ADDRESS 5 #define GET_DESCRIPTOR 6 #define SET_CONFIGURATION 9 #define SET_INTERFACE 11 #pragma pack(push,1) struct StandardDeviceDescriptor {// offset uint8_t bLength; // +0 uint8_t bDescriptorType; // +1 uint16_t bcdUSB; // +2 uint8_t bDeviceClass; // +4 uint8_t bDeviceSubClass; // +5 uint8_t bDeviceProtocol; // +6 uint8_t bMaxPacketSize; // +7 uint16_t idVendor; // +8 uint16_t idProduct; // +10 uint16_t bcdDevice; // +12 uint8_t iManufacturer; // +14 uint8_t iProduct; // +15 uint8_t iSerialNumber; // +16 uint8_t bNumConfigurations; // +17 }; // +18 struct StandardConfigurationDescriptor {// offset uint8_t bLength; // +0 uint8_t bDescriptorType; // +1 uint16_t wTotalLength; // +2 uint8_t bNumInterfaces; // +4 uint8_t bConfigurationValue; // +5 uint8_t iConfiguration; // +6 uint8_t bmAttributes; // +7 uint8_t bMaxPower; // +8 }; // +9 struct StandardInterfaceDescriptor {// offset uint8_t bLength; // +0 uint8_t bDescriptorType; // +1 uint8_t bInterfaceNumber; // +2 uint8_t bAlternateSetting; // +3 uint8_t bNumEndpoints; // +4 uint8_t bInterfaceClass; // +5 uint8_t bInterfaceSubClass;// +6 uint8_t bInterfaceProtocol;// +7 uint8_t iInterface; // +8 }; // +9 struct StandardEndpointDescriptor {// offset uint8_t bLength; // +0 uint8_t bDescriptorType; // +1 uint8_t bEndpointAddress; // +2 uint8_t bmAttributes; // +3 uint16_t wMaxPacketSize; // +4 uint8_t bInterval; // +6 }; // +7 struct StandardStringDescriptor {// offset uint8_t bLength; // +0 uint8_t bDescriptorType; // +1 char bString[0]; // +2 }; // +3 struct HubDescriptor { // offset uint8_t bDescLength; // +0 uint8_t bDescriptorType; // +1 uint8_t bNbrPorts; // +2 uint16_t wHubCharacteristics;// +3 uint8_t bPwrOn2PwrGood; // +5 uint8_t bHubContrCurrent; // +6 uint8_t DeviceRemovable; // +7 uint8_t PortPweCtrlMak; // +8 }; // +9 #pragma pack(pop) // ------------------ HcControl Register --------------------- #define OR_CONTROL_PLE 0x00000004 #define OR_CONTROL_IE 0x00000008 #define OR_CONTROL_CLE 0x00000010 #define OR_CONTROL_BLE 0x00000020 #define OR_CONTROL_HCFS 0x000000C0 #define OR_CONTROL_HC_OPER 0x00000080 // ----------------- HcCommandStatus Register ----------------- #define OR_CMD_STATUS_HCR 0x00000001 #define OR_CMD_STATUS_CLF 0x00000002 #define OR_CMD_STATUS_BLF 0x00000004 // --------------- HcInterruptStatus Register ----------------- #define OR_INTR_STATUS_WDH 0x00000002 #define OR_INTR_STATUS_UE 0x00000010 #define OR_INTR_STATUS_FNO 0x00000020 #define OR_INTR_STATUS_RHSC 0x00000040 // --------------- HcInterruptEnable Register ----------------- #define OR_INTR_ENABLE_WDH 0x00000002 #define OR_INTR_ENABLE_FNO 0x00000020 #define OR_INTR_ENABLE_RHSC 0x00000040 #define OR_INTR_ENABLE_MIE 0x80000000 // ---------------- HcRhDescriptorA Register ------------------ #define OR_RH_STATUS_LPSC 0x00010000 #define OR_RH_STATUS_DRWE 0x00008000 // -------------- HcRhPortStatus[1:NDP] Register -------------- #define OR_RH_PORT_CCS 0x00000001 #define OR_RH_PORT_PRS 0x00000010 #define OR_RH_PORT_CSC 0x00010000 #define OR_RH_PORT_PRSC 0x00100000 // TRANSFER DESCRIPTOR CONTROL FIELDS #define TD_ROUNDING (uint32_t)(0x00040000) /* Buffer Rounding */ #define TD_SETUP (uint32_t)(0x00000000) /* Direction of Setup Packet */ #define TD_IN (uint32_t)(0x00100000) /* Direction In */ #define TD_OUT (uint32_t)(0x00080000) /* Direction Out */ #define TD_DELAY_INT(x) (uint32_t)((x) << 21) /* Delay Interrupt */ #define TD_DI (uint32_t)(7<<21) /* desable interrupt */ #define TD_TOGGLE_0 (uint32_t)(0x02000000) /* Toggle 0 */ #define TD_TOGGLE_1 (uint32_t)(0x03000000) /* Toggle 1 */ #define TD_CC (uint32_t)(0xF0000000) /* Completion Code */ class BaseEp; struct HCTD { // HostController Transfer Descriptor __IO uint32_t Control; // +0 Transfer descriptor control __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer HCTD* Next; // +8 Physical pointer to next Transfer Descriptor uint8_t* BufEnd; // +12 Physical address of end of buffer uint8_t* buf_top; // +16 Buffer start address uint16_t buf_size; // +20 buffer size size uint8_t _dummy[10]; // +22 dummy BaseEp* ep; // +32 endpoint object // +36 HCTD(BaseEp* obj); inline void* operator new(size_t size) { void* p; if (posix_memalign(&p, 16, size) == 0) { return p; } return NULL; } inline void operator delete(void* p) { free(p); } inline void transfer(uint8_t* data, int len) { CurrBufPtr = data; buf_top = data; buf_size = len; BufEnd = const_cast<uint8_t*>(data)+len-1; } inline int status() { if (CurrBufPtr) { return CurrBufPtr - buf_top; } return buf_size; } inline uint8_t ConditionCode() { return Control>>28; } }; struct HCITD { // HostController Isochronous Transfer Descriptor __IO uint32_t Control; // +0 Transfer descriptor control uint8_t* BufferPage0; // +4 Buffer Page 0 HCITD* Next; // +8 Physical pointer to next Isochronous Transfer Descriptor uint8_t* BufferEnd; // +12 buffer End __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW BaseEp* ep; // +32 endpoint object __IO uint8_t buf[0]; // +36 buffer // +36 HCITD(BaseEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize); inline void* operator new(size_t size, int buf_size) { void* p; if (posix_memalign(&p, 32, size+buf_size) == 0) { return p; } return NULL; } inline void operator delete(void* p) { free(p); } inline uint16_t StartingFrame() { return Control & 0xffff; } inline uint8_t FrameCount() { return ((Control>>24)&7)+1; } inline uint8_t ConditionCode() { return Control>>28; } }; struct HCED { // HostController EndPoint Descriptor __IO uint32_t Control; // +0 Endpoint descriptor control HCTD* TailTd; // +4 Physical address of tail in Transfer descriptor list __IO HCTD* HeadTd; // +8 Physcial address of head in Transfer descriptor list HCED* Next; // +12 Physical address of next Endpoint descriptor // +16 HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed) { Control = addr | /* USB address */ ((ep & 0x7F) << 7) | /* Endpoint address */ (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */ ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */ (size << 16); /* MaxPkt Size */ Next = NULL; } inline void* operator new(size_t size) { void* p; if (posix_memalign(&p, 16, size) == 0) { return p; } return NULL; } inline void operator delete(void* p) { free(p); } inline uint8_t FunctionAddress() { return Control & 0x7f; } inline int Speed() { return (Control>>13)&1; } inline void setFunctionAddress(int addr) { Control &= ~0x7f; Control |= addr; } inline void setMaxPacketSize(uint16_t size) { Control &= ~0xffff0000; Control |= size<<16; } }; struct HCCA { // Host Controller Communication Area HCED* InterruptTable[32]; // +0 Interrupt Table __IO uint16_t FrameNumber;// +128 Frame Number __IO uint16_t Pad1; // +130 __IO HCTD* DoneHead; // +132 Done Head uint8_t Reserved[116]; // +136 Reserved for future use uint8_t Unknown[4]; // +252 Unused // +256 inline void* operator new(size_t size) { void* p; if (posix_memalign(&p, 256, size) == 0) { return p; } return NULL; } inline void operator delete(void* p) { free(p); } }; class BaseUsbHost { public: BaseUsbHost(); void irqHandler(); // report uint32_t m_report_irq; uint32_t m_report_RHSC; uint32_t m_report_FNO; uint32_t m_report_WDH; uint32_t m_report_sp; private: void init_hw_ohci(HCCA* pHcca); void ResetRootHub(); HCCA* m_pHcca; }; #define HCTD_QUEUE_SIZE 3 class BaseEp { // endpoint public: BaseEp(int addr, uint8_t ep = 0, uint16_t size = 8, int lowSpeed = 0); int GetAddr(); int GetLowSpeed(); void update_FunctionAddress(int addr); void update_MaxPacketSize(uint16_t size); int transfer(uint8_t* buf, int len); int status(uint32_t millisec=osWaitForever); // virtual void enable() = 0; virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} // WDH int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever); // report uint8_t m_ConditionCode; int m_report_queue_error; protected: int send_receive(uint8_t* buf, int len, int millisec); HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever); HCED* m_pED; Queue<HCTD, HCTD_QUEUE_SIZE> m_queue; // TD done queue int m_td_queue_count; }; class ControlEp : public BaseEp { public: ControlEp(int lowSpeed = 0); int GetDescriptor(int descType, int descIndex, uint8_t* data, int length); int SetAddress(int addr); // device address int SetConfiguration(int config); int GetConfiguration(int *config); int SetInterfaceAlternate(int interface, int alternate); int GetInterface(int interface, int *alternate); int controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex=0, const uint8_t* data=NULL, int length=0); int controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t* data, int length); string GetStringDescriptor(int index); private: int open(int addr); virtual void enable(){}; }; class BulkEp : public BaseEp { public: BulkEp(int addr, uint8_t ep, uint16_t size); int bulkSend(const uint8_t* buf, int len, int millisec=osWaitForever); int bulkReceive(uint8_t* buf, int len, int millisec=osWaitForever); private: virtual void enable(); }; class InterruptEp : public BaseEp { public: InterruptEp(int addr, uint8_t ep, uint16_t size, int lowSpeed=0); int interruptReceive(uint8_t* buf, int len, int millisec=osWaitForever); private: virtual void enable(); }; class IsochronousEp : public BaseEp { public: IsochronousEp(int addr, uint8_t ep, uint16_t size); void reset(int delay_ms = 100); HCITD* isochronousReveive(int millisec=osWaitForever); int isochronousSend(uint8_t* buf, int len, int millisec=osWaitForever); HCITD* get_queue_HCITD(int millisec); uint16_t m_PacketSize; private: HCITD* new_HCITD(BaseEp* obj); int m_itd_queue_count; uint16_t m_FrameNumber; int m_FrameCount; // 1-8 virtual void enable(); }; // --- HUB -------------------------------------------------- class UsbHub { public: UsbHub(ControlEp* ctlEp = NULL); static bool check(ControlEp* ctlEp); int SetPortPower(int port); int ClearPortPower(int port); vector<ControlEp*> PortEp; template<class T> ControlEp* search(int skip = 0) { for(vector<ControlEp*>::iterator it = PortEp.begin(); it != PortEp.end(); ++it) { if (T::check(*it)) { if (skip-- <= 0) { return *it; } } } return NULL; } template<class T> ControlEp* assign(int port) { if (port >= 0 && port < PortEp.size()) { return PortEp[port]; } return NULL; } private: int PortReset(int port); int SetPortFeature(int feature, int index); int ClearPortFeature(int feature, int index); int SetPortReset(int port); int GetPortStatus(int port, uint32_t* status); ControlEp* m_ctlEp; }; // --- UVC -------------------------------------------------- #define _30FPS 333333 #define _25FPS 400000 #define _20FPS 500000 #define _15FPS 666666 #define _10FPS 1000000 #define _5FPS 2000000 #define _1FPS 10000000 #define SET_CUR 0x01 #define GET_CUR 0x81 #define GET_MIN 0x82 #define GET_MAX 0x83 #define GET_RES 0x84 #define GET_LEN 0x85 #define GET_INFO 0x86 #define GET_DEF 0x87 #define VS_PROBE_CONTROL 0x01 #define VS_COMMIT_CONTROL 0x02 class BaseUvc { public: void poll(int millisec=osWaitForever); int Control(int req, int cs, int index, uint8_t* buf, int size); ControlEp* m_ctlEp; IsochronousEp* m_isoEp; uint32_t report_cc_count[16]; // ConditionCode uint32_t report_ps_cc_count[16]; // Packt Status ConditionCode // callback void onResult(uint16_t frame, uint8_t* buf, int len); void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) ); class CDummy; template<class T> void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) ) { m_pCb = NULL; m_pCbItem = (CDummy*) pItem; m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod; } void clearOnResult(); CDummy* m_pCbItem; void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int); void (*m_pCb)(uint16_t, uint8_t*, int); };