mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-27 19:42:15 -05:00
Simplify and document USB device driver interface
This commit is contained in:
parent
26fa6f2e34
commit
5d39664c89
50
USBHost.h
50
USBHost.h
@ -62,8 +62,7 @@ typedef union {
|
|||||||
struct Device_struct {
|
struct Device_struct {
|
||||||
Pipe_t *control_pipe;
|
Pipe_t *control_pipe;
|
||||||
Device_t *next;
|
Device_t *next;
|
||||||
setup_t setup;
|
setup_t setup; // TODO: move this to static in enumeration.cpp
|
||||||
//USBHostDriver *driver[6];
|
|
||||||
USBHostDriver *drivers;
|
USBHostDriver *drivers;
|
||||||
uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec
|
uint8_t speed; // 0=12, 1=1.5, 2=480 Mbit/sec
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
@ -146,6 +145,7 @@ protected:
|
|||||||
static void driver_ready_for_device(USBHostDriver *driver);
|
static void driver_ready_for_device(USBHostDriver *driver);
|
||||||
private:
|
private:
|
||||||
static void isr();
|
static void isr();
|
||||||
|
static void claim_drivers(Device_t *dev);
|
||||||
static void init_Device_Pipe_Transfer_memory(void);
|
static void init_Device_Pipe_Transfer_memory(void);
|
||||||
static Device_t * allocate_Device(void);
|
static Device_t * allocate_Device(void);
|
||||||
static void free_Device(Device_t *q);
|
static void free_Device(Device_t *q);
|
||||||
@ -175,29 +175,55 @@ protected:
|
|||||||
/************************************************/
|
/************************************************/
|
||||||
|
|
||||||
class USBHostDriver : public USBHost {
|
class USBHostDriver : public USBHost {
|
||||||
public:
|
protected:
|
||||||
virtual bool claim_device(Device_t *device, const uint8_t *descriptors) {
|
USBHostDriver() : next(NULL), device(NULL) {}
|
||||||
|
// Check if a driver wishes to claim a device or interface or group
|
||||||
|
// of interfaces within a device. When this function returns true,
|
||||||
|
// the driver is considered bound or loaded for that device. When
|
||||||
|
// new devices are detected, enumeration.cpp calls this function on
|
||||||
|
// all unbound driver objects, to give them an opportunity to bind
|
||||||
|
// to the new device.
|
||||||
|
// device has its vid&pid, class/subclass fields initialized
|
||||||
|
// type is 0 for device level, 1 for interface level, 2 for IAD
|
||||||
|
// descriptors points to the specific descriptor data
|
||||||
|
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool claim_interface(Device_t *device, const uint8_t *descriptors) {
|
// When an unknown (not chapter 9) control transfer completes, this
|
||||||
return false;
|
// function is called for all drivers bound to the device. Return
|
||||||
}
|
// true means this driver originated this control transfer, so no
|
||||||
virtual bool control_callback(const Transfer_t *transfer) {
|
// more drivers need to be offered an opportunity to process it.
|
||||||
|
virtual bool control(const Transfer_t *transfer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// When a device disconnects from the USB, this function is called.
|
||||||
|
// The driver must free all resources it has allocated.
|
||||||
virtual void disconnect() {
|
virtual void disconnect() {
|
||||||
}
|
}
|
||||||
|
// Drivers are managed by this single-linked list. All inactive
|
||||||
|
// (not bound to any device) drivers are linked from
|
||||||
|
// available_drivers is enumeration.cpp. When bound to a device,
|
||||||
|
// drivers are linked from that Device_t drivers list.
|
||||||
USBHostDriver *next;
|
USBHostDriver *next;
|
||||||
|
// When not bound to any device, this must be NULL.
|
||||||
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
class USBHub : public USBHostDriver {
|
class USBHub : public USBHostDriver {
|
||||||
public:
|
public:
|
||||||
USBHub();
|
USBHub();
|
||||||
virtual bool claim_device(Device_t *device, const uint8_t *descriptors);
|
protected:
|
||||||
virtual bool control_callback(const Transfer_t *transfer);
|
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors);
|
||||||
setup_t setup;
|
virtual bool control(const Transfer_t *transfer);
|
||||||
|
setup_t setup; // TODO: use this for our control transfers, not device's
|
||||||
uint8_t hub_desc[12];
|
uint8_t hub_desc[12];
|
||||||
|
uint32_t change;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ static USBHostDriver *available_drivers = NULL;
|
|||||||
static uint8_t enumbuf[256] __attribute__ ((aligned(16)));
|
static uint8_t enumbuf[256] __attribute__ ((aligned(16)));
|
||||||
|
|
||||||
|
|
||||||
static void claim_drivers(Device_t *dev);
|
|
||||||
static uint32_t assign_addr(void);
|
static uint32_t assign_addr(void);
|
||||||
static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen);
|
static void pipe_set_maxlen(Pipe_t *pipe, uint32_t maxlen);
|
||||||
static void pipe_set_addr(Pipe_t *pipe, uint32_t addr);
|
static void pipe_set_addr(Pipe_t *pipe, uint32_t addr);
|
||||||
@ -220,7 +219,7 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
case 15: // control transfers for other stuff?
|
case 15: // control transfers for other stuff?
|
||||||
// TODO: handle other standard control: set/clear feature, etc
|
// TODO: handle other standard control: set/clear feature, etc
|
||||||
for (USBHostDriver *d = dev->drivers; d != NULL; d = d->next) {
|
for (USBHostDriver *d = dev->drivers; d != NULL; d = d->next) {
|
||||||
if (d->control_callback(transfer)) {
|
if (d->control(transfer)) {
|
||||||
// this driver processed the control transfer reply
|
// this driver processed the control transfer reply
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -231,18 +230,19 @@ void USBHost::enumeration(const Transfer_t *transfer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void claim_drivers(Device_t *dev)
|
void USBHost::claim_drivers(Device_t *dev)
|
||||||
{
|
{
|
||||||
USBHostDriver *driver, *prev=NULL;
|
USBHostDriver *driver, *prev=NULL;
|
||||||
|
|
||||||
// first check if any driver wishes to claim the entire device
|
// first check if any driver wishes to claim the entire device
|
||||||
for (driver=available_drivers; driver != NULL; driver = driver->next) {
|
for (driver=available_drivers; driver != NULL; driver = driver->next) {
|
||||||
if (driver->claim_device(dev, enumbuf + 9)) {
|
if (driver->claim(dev, 0, enumbuf + 9)) {
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = driver->next;
|
prev->next = driver->next;
|
||||||
} else {
|
} else {
|
||||||
available_drivers = driver->next;
|
available_drivers = driver->next;
|
||||||
}
|
}
|
||||||
|
driver->device = dev;
|
||||||
driver->next = NULL;
|
driver->next = NULL;
|
||||||
dev->drivers = driver;
|
dev->drivers = driver;
|
||||||
return;
|
return;
|
||||||
|
17
hub.cpp
17
hub.cpp
@ -30,8 +30,11 @@ USBHub::USBHub()
|
|||||||
driver_ready_for_device(this);
|
driver_ready_for_device(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USBHub::claim_device(Device_t *dev, const uint8_t *descriptors)
|
bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors)
|
||||||
{
|
{
|
||||||
|
// only claim entire device, never at interface level
|
||||||
|
if (type != 0) return false;
|
||||||
|
|
||||||
Serial.print("USBHub claim_device this=");
|
Serial.print("USBHub claim_device this=");
|
||||||
Serial.println((uint32_t)this, HEX);
|
Serial.println((uint32_t)this, HEX);
|
||||||
|
|
||||||
@ -66,17 +69,25 @@ bool USBHub::claim_device(Device_t *dev, const uint8_t *descriptors)
|
|||||||
Serial.print("bDeviceProtocol = ");
|
Serial.print("bDeviceProtocol = ");
|
||||||
Serial.println(dev->bDeviceProtocol);
|
Serial.println(dev->bDeviceProtocol);
|
||||||
|
|
||||||
|
// TODO: need a way to do control transfers with our own setup data.
|
||||||
mk_setup(dev->setup, 0xA0, 6, 0x2900, 0, sizeof(hub_desc));
|
mk_setup(dev->setup, 0xA0, 6, 0x2900, 0, sizeof(hub_desc));
|
||||||
new_Transfer(dev->control_pipe, hub_desc, sizeof(hub_desc));
|
new_Transfer(dev->control_pipe, hub_desc, sizeof(hub_desc));
|
||||||
// TODO: need to arrange for callback to this driver from enumeration.cpp
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USBHub::control_callback(const Transfer_t *transfer)
|
bool USBHub::control(const Transfer_t *transfer)
|
||||||
{
|
{
|
||||||
|
if (transfer->buffer == hub_desc) {
|
||||||
Serial.println("USBHub control callback");
|
Serial.println("USBHub control callback");
|
||||||
print_hexbytes(transfer->buffer, transfer->length);
|
print_hexbytes(transfer->buffer, transfer->length);
|
||||||
|
if (hub_desc[0] == 9 && hub_desc[1] == 0x29) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user