| class USBHost; | class USBHost; | ||||
| class USBDriver; | class USBDriver; | ||||
| typedef struct Device_struct Device_t; | |||||
| typedef struct Pipe_struct Pipe_t; | |||||
| typedef struct Transfer_struct Transfer_t; | |||||
| class USBDriverTimer; | |||||
| typedef struct Device_struct Device_t; | |||||
| typedef struct Pipe_struct Pipe_t; | |||||
| typedef struct Transfer_struct Transfer_t; | |||||
| //typedef struct DriverTimer_struct DriverTimer_t; | |||||
| // setup_t holds the 8 byte USB SETUP packet data. | // setup_t holds the 8 byte USB SETUP packet data. | ||||
| // These unions & structs allow convenient access to | // These unions & structs allow convenient access to | ||||
| uint32_t unused; | uint32_t unused; | ||||
| }; | }; | ||||
| /************************************************/ | /************************************************/ | ||||
| /* Main USB EHCI Controller */ | /* Main USB EHCI Controller */ | ||||
| /************************************************/ | /************************************************/ | ||||
| // All USB device drivers inherit from this base class. | // All USB device drivers inherit from this base class. | ||||
| class USBDriver : public USBHost { | class USBDriver : public USBHost { | ||||
| public: | |||||
| // TODO: user-level functions | |||||
| // check if device is bound/active/online | |||||
| // query vid, pid | |||||
| // query string: manufacturer, product, serial number | |||||
| protected: | protected: | ||||
| USBDriver() : next(NULL), device(NULL) {} | USBDriver() : next(NULL), device(NULL) {} | ||||
| // Check if a driver wishes to claim a device or interface or group | // Check if a driver wishes to claim a device or interface or group | ||||
| // transfers and wishes to be notified when they complete. | // transfers and wishes to be notified when they complete. | ||||
| virtual void control(const Transfer_t *transfer) { } | virtual void control(const Transfer_t *transfer) { } | ||||
| // When any of the USBDriverTimer objects a driver creates generates | |||||
| // a timer event, this function is called. | |||||
| virtual void timer(USBDriverTimer &whichTimer) { } | |||||
| // When a device disconnects from the USB, this function is called. | // When a device disconnects from the USB, this function is called. | ||||
| // The driver must free all resources it allocated and update any | // The driver must free all resources it allocated and update any | ||||
| // internal state necessary to deal with the possibility of user | // internal state necessary to deal with the possibility of user | ||||
| Device_t *device; | Device_t *device; | ||||
| friend class USBHost; | friend class USBHost; | ||||
| public: | |||||
| // TODO: user-level functions | |||||
| // check if device is bound/active/online | |||||
| // query vid, pid | |||||
| // query string: manufacturer, product, serial number | |||||
| }; | }; | ||||
| // Device drivers may create these timer objects to schedule a timer call | |||||
| class USBDriverTimer { | |||||
| public: | |||||
| USBDriverTimer() { } | |||||
| USBDriverTimer(USBDriver *d) : driver(d) { } | |||||
| void init(USBDriver *d) { driver = d; }; | |||||
| void start(uint32_t microseconds); | |||||
| void *pointer; | |||||
| uint32_t integer; | |||||
| private: | |||||
| USBDriver *driver; | |||||
| uint32_t usec; | |||||
| USBDriverTimer *next; | |||||
| USBDriverTimer *prev; | |||||
| friend class USBHost; | |||||
| }; | |||||
| /************************************************/ | /************************************************/ | ||||
| /* USB Device Drivers */ | /* USB Device Drivers */ | ||||
| void status_change(const Transfer_t *transfer); | void status_change(const Transfer_t *transfer); | ||||
| void new_port_status(uint32_t port, uint32_t status); | void new_port_status(uint32_t port, uint32_t status); | ||||
| void update_status(); | void update_status(); | ||||
| USBDriverTimer mytimer; | |||||
| USBDriverTimer othertimer; | |||||
| setup_t setup; | setup_t setup; | ||||
| uint8_t hub_desc[16]; | uint8_t hub_desc[16]; | ||||
| uint8_t endpoint; | uint8_t endpoint; |
| static Transfer_t *async_followup_last=NULL; | static Transfer_t *async_followup_last=NULL; | ||||
| static Transfer_t *periodic_followup_first=NULL; | static Transfer_t *periodic_followup_first=NULL; | ||||
| static Transfer_t *periodic_followup_last=NULL; | static Transfer_t *periodic_followup_last=NULL; | ||||
| static USBDriverTimer *active_timers=NULL; | |||||
| static void init_qTD(volatile Transfer_t *t, void *buf, uint32_t len, | static void init_qTD(volatile Transfer_t *t, void *buf, uint32_t len, | ||||
| // enable interrupts, after this point interruts to all the work | // enable interrupts, after this point interruts to all the work | ||||
| attachInterruptVector(IRQ_USBHS, isr); | attachInterruptVector(IRQ_USBHS, isr); | ||||
| NVIC_ENABLE_IRQ(IRQ_USBHS); | NVIC_ENABLE_IRQ(IRQ_USBHS); | ||||
| USBHS_USBINTR = USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0; | |||||
| USBHS_USBINTR = USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0 | USBHS_USBINTR_TIE1; | |||||
| USBHS_USBINTR |= USBHS_USBINTR_UEE | USBHS_USBINTR_SEE; | USBHS_USBINTR |= USBHS_USBINTR_UEE | USBHS_USBINTR_SEE; | ||||
| USBHS_USBINTR |= USBHS_USBINTR_AAE; | USBHS_USBINTR |= USBHS_USBINTR_AAE; | ||||
| USBHS_USBINTR |= USBHS_USBINTR_UPIE | USBHS_USBINTR_UAIE; | USBHS_USBINTR |= USBHS_USBINTR_UPIE | USBHS_USBINTR_UAIE; | ||||
| } | } | ||||
| } | } | ||||
| if (stat & USBHS_USBSTS_TI0) { // timer 0 | |||||
| println("timer"); | |||||
| if (stat & USBHS_USBSTS_TI0) { // timer 0 - used for built-in port events | |||||
| println("timer0"); | |||||
| if (port_state == PORT_STATE_DEBOUNCE) { | if (port_state == PORT_STATE_DEBOUNCE) { | ||||
| port_state = PORT_STATE_RESET; | port_state = PORT_STATE_RESET; | ||||
| USBHS_PORTSC1 |= USBHS_PORTSC_PR; // begin reset sequence | USBHS_PORTSC1 |= USBHS_PORTSC_PR; // begin reset sequence | ||||
| rootdev = new_Device(speed, 0, 0); | rootdev = new_Device(speed, 0, 0); | ||||
| } | } | ||||
| } | } | ||||
| if (stat & USBHS_USBSTS_TI1) { // timer 1 - used for USBDriverTimer | |||||
| println("timer1"); | |||||
| } | |||||
| } | |||||
| void USBDriverTimer::start(uint32_t microseconds) | |||||
| { | |||||
| Serial.print("start_timer, usec = "); | |||||
| Serial.print(usec); | |||||
| Serial.print(", driver = "); | |||||
| Serial.print((uint32_t)driver, HEX); | |||||
| Serial.print(", this = "); | |||||
| Serial.println((uint32_t)this, HEX); | |||||
| #if 1 | |||||
| if (!driver) return; | |||||
| if (microseconds < 100) return; // minimum timer duration | |||||
| if (active_timers == NULL) { | |||||
| usec = microseconds; | |||||
| next = NULL; | |||||
| prev = NULL; | |||||
| active_timers = this; | |||||
| USBHS_GPTIMER1LD = microseconds - 1; | |||||
| USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; | |||||
| return; | |||||
| } | |||||
| #endif | |||||
| // TODO, add to active_timers list | |||||
| //uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; | |||||
| } | } | ||||
| // bulk | // bulk | ||||
| } else if (type == 3) { | } else if (type == 3) { | ||||
| // interrupt | // interrupt | ||||
| //pipe->qh.token = 0x80000000; // TODO: OUT starts with DATA0 or DATA1? | |||||
| } | } | ||||
| pipe->qh.capabilities[0] = QH_capabilities1(15, c, maxlen, 0, | pipe->qh.capabilities[0] = QH_capabilities1(15, c, maxlen, 0, | ||||
| dtc, dev->speed, endpoint, 0, dev->address); | dtc, dev->speed, endpoint, 0, dev->address); |
| #include <Arduino.h> | #include <Arduino.h> | ||||
| #include "USBHost.h" | #include "USBHost.h" | ||||
| USBHub::USBHub() | |||||
| USBHub::USBHub() : /* mytimer(this), */ othertimer(this) | |||||
| { | { | ||||
| // TODO: free Device_t, Pipe_t & Transfer_t we will need | // TODO: free Device_t, Pipe_t & Transfer_t we will need | ||||
| driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
| println("USBHub claim_device this=", (uint32_t)this, HEX); | println("USBHub claim_device this=", (uint32_t)this, HEX); | ||||
| // timer testing TODO: remove this later | |||||
| mytimer.init(this); | |||||
| mytimer.start(99129); | |||||
| othertimer.start(12345); | |||||
| // check for HUB type | // check for HUB type | ||||
| if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; | if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; | ||||
| // protocol must be 0=FS, 1=HS Single-TT, or 2=HS Multi-TT | // protocol must be 0=FS, 1=HS Single-TT, or 2=HS Multi-TT |