diff --git a/USBHost.h b/USBHost.h index 9aa2b8e..9482b9e 100644 --- a/USBHost.h +++ b/USBHost.h @@ -32,9 +32,11 @@ class USBHost; 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. // These unions & structs allow convenient access to @@ -141,6 +143,7 @@ struct Transfer_struct { uint32_t unused; }; + /************************************************/ /* Main USB EHCI Controller */ /************************************************/ @@ -227,6 +230,11 @@ protected: // All USB device drivers inherit from this base class. 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: USBDriver() : next(NULL), device(NULL) {} // Check if a driver wishes to claim a device or interface or group @@ -248,6 +256,10 @@ protected: // transfers and wishes to be notified when they complete. 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. // The driver must free all resources it allocated and update any // internal state necessary to deal with the possibility of user @@ -268,13 +280,24 @@ protected: Device_t *device; 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 */ @@ -295,6 +318,8 @@ protected: void status_change(const Transfer_t *transfer); void new_port_status(uint32_t port, uint32_t status); void update_status(); + USBDriverTimer mytimer; + USBDriverTimer othertimer; setup_t setup; uint8_t hub_desc[16]; uint8_t endpoint; diff --git a/ehci.cpp b/ehci.cpp index 5a1d0ec..e984923 100644 --- a/ehci.cpp +++ b/ehci.cpp @@ -43,6 +43,7 @@ static Transfer_t *async_followup_first=NULL; static Transfer_t *async_followup_last=NULL; static Transfer_t *periodic_followup_first=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, @@ -172,7 +173,7 @@ void USBHost::begin() // enable interrupts, after this point interruts to all the work attachInterruptVector(IRQ_USBHS, isr); 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_AAE; USBHS_USBINTR |= USBHS_USBINTR_UPIE | USBHS_USBINTR_UAIE; @@ -306,8 +307,8 @@ void USBHost::isr() } } - 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) { port_state = PORT_STATE_RESET; USBHS_PORTSC1 |= USBHS_PORTSC_PR; // begin reset sequence @@ -321,6 +322,34 @@ void USBHost::isr() 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; } @@ -403,6 +432,7 @@ Pipe_t * USBHost::new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, // bulk } else if (type == 3) { // interrupt + //pipe->qh.token = 0x80000000; // TODO: OUT starts with DATA0 or DATA1? } pipe->qh.capabilities[0] = QH_capabilities1(15, c, maxlen, 0, dtc, dev->speed, endpoint, 0, dev->address); diff --git a/hub.cpp b/hub.cpp index ad2d8a2..daf46b6 100644 --- a/hub.cpp +++ b/hub.cpp @@ -24,7 +24,7 @@ #include #include "USBHost.h" -USBHub::USBHub() +USBHub::USBHub() : /* mytimer(this), */ othertimer(this) { // TODO: free Device_t, Pipe_t & Transfer_t we will need driver_ready_for_device(this); @@ -37,6 +37,11 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t 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 if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; // protocol must be 0=FS, 1=HS Single-TT, or 2=HS Multi-TT