@@ -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; |
@@ -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); |
@@ -24,7 +24,7 @@ | |||
#include <Arduino.h> | |||
#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 |