USB host library, support isochronous,bulk,interrupt and control.
Dependents: BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example
Import programBaseUsbHost_example
BaseUsbHost example program
Diff: BaseUsbHost.h
- Revision:
- 0:b7d6879637a8
- Child:
- 1:3b7bc4f87a61
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbHost.h Tue Dec 04 13:29:41 2012 +0000 @@ -0,0 +1,222 @@ +// BaseUsbHost.h 2012/12/4 +#ifndef BASE_USB_HOST_H +#define BASE_USB_HOST_H + +#define USB_OK 0 +#define USB_ERROR -1 +#define USB_TIMEOUT -2 +#define USB_ERROR2 -3 + +// 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 +// ------------------ 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 */ + +typedef struct { // Host Controller Communication Area + uint32_t InterruptTable[32]; // Interrupt Table + __IO uint16_t FrameNumber; // Frame Number + __IO uint16_t Pad1; + __IO uint32_t DoneHead; // Done Head + uint8_t Reserved[116]; // Reserved for future use + uint8_t Unknown[4]; // Unused +} HCCA; + +typedef struct { // HostController Transfer Descriptor + __IO uint32_t Control; // +0 Transfer descriptor control + __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer + __IO uint32_t 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 setup[8]; // +22 setup cmd area + uint8_t _dummy[2]; // +30 dummy + void *ep; // +32 endpoint object + __IO uint8_t buf[0]; // +36 buffer +} HCTD; // +36 + +typedef struct { // HostController Isochronous Transfer Descriptor + __IO uint32_t Control; // +0 Transfer descriptor control + uint8_t* BufferPage0; // +4 Buffer Page 0 + __IO uint32_t Next; // +8 Physical pointer to next Transfer Descriptor + uint8_t* BufferEnd; // +12 buffer End + __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW + void *ep; // +32 endpoint object + __IO uint8_t buf[0]; // +36 buffer +} HCITD; // +36 + +typedef struct { // 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 + uint32_t Next; // +12 Physical address of next Endpoint descriptor +} HCED; + +#define DELETE_TD(A) free(A) +#define DELETE_ITD(A) free(A) + +class BaseUsbHost { +public: + BaseUsbHost(); + void init_hw_ohci(HCCA* pHcca); + void ResetRootHub(); + void irqHandler(); + HCCA* m_pHcca; + // 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; +}; + +#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); + // + HCTD* new_HCTD(int buf_size=0); + void delete_HCTD(HCTD* p); + HCED* m_pED; + // TD done queue + virtual void irqWdhHandler(HCTD* td) = 0; // WDH + HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever); + int wait_queue_HCTD(HCTD* wait_td, uint32_t millisec=osWaitForever); + Queue<HCTD, HCTD_QUEUE_SIZE> m_queue; + int m_td_queue_count; + // report + uint8_t m_ConditionCode; + int m_report_queue_error; +}; + +class ControlEp : public BaseEp { +public: + ControlEp(int lowSpeed = 0); + virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} + 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); + // + uint8_t DeviceClass; + uint8_t DeviceSubClass; + uint8_t DeviceProtocol; + // + int open(int addr); + void setup(HCTD* td, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex=0, uint16_t wLength=0); +}; + +class BulkEp : public BaseEp { +public: + BulkEp(int addr, uint8_t ep, uint16_t size); + virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} + int read(uint8_t* buf, int len, int millisec=osWaitForever); + int write(const uint8_t* buf, int len, int millisec=osWaitForever); +}; + +class InterruptEp : public BaseEp { +public: + InterruptEp(int addr, uint8_t ep, uint16_t size, int lowSpeed=0); + virtual void irqWdhHandler(HCTD* td) {m_queue.put(td);} + int read(uint8_t* buf, int len, int millisec=osWaitForever); +}; + +class IsochronousEp : public BaseEp { +public: + IsochronousEp(int addr, uint8_t ep, uint16_t size); + virtual void irqWdhHandler(HCTD* td); + void reset(); + HCITD* read(); + HCITD* new_HCITD(); + HCITD* get_queue_HCITD(uint32_t millisec); + int m_itd_queue_count; + uint16_t m_FrameNumber; + int m_PacketSize; // 128,192 + int m_FrameCount; // 1-8 +}; + +#define MAX_HUB_PORT 4 + +class UsbHub { +public: + UsbHub(ControlEp* ctlEp = NULL); + void DeviceConnected(int port, int low_speed); + int PortReset(int port); + // + int SetPortFeature(int feature, int index); + int ClearPortFeature(int feature, int index); + int SetPortPower(int port); + int SetPortReset(int port); + int GetPortStatus(int port, uint32_t* status); + ControlEp* m_ctlEp; + ControlEp* PortEp[MAX_HUB_PORT]; // port endpoint(control) +}; + + +#endif //BASE_USB_HOST_H