static bool queue_Data_Transfer(Pipe_t *pipe, void *buffer, | static bool queue_Data_Transfer(Pipe_t *pipe, void *buffer, | ||||
uint32_t len, USBDriver *driver); | uint32_t len, USBDriver *driver); | ||||
static Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port); | static Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port); | ||||
static void disconnect_Device(Device_t *dev); | |||||
static void enumeration(const Transfer_t *transfer); | static void enumeration(const Transfer_t *transfer); | ||||
static void driver_ready_for_device(USBDriver *driver); | static void driver_ready_for_device(USBDriver *driver); | ||||
private: | private: | ||||
static void print(const Transfer_t *first, const Transfer_t *last); | static void print(const Transfer_t *first, const Transfer_t *last); | ||||
static void print_token(uint32_t token); | static void print_token(uint32_t token); | ||||
static void print(const Pipe_t *pipe); | static void print(const Pipe_t *pipe); | ||||
static void print_driverlist(const char *name, const USBDriver *driver); | |||||
static void print_hexbytes(const void *ptr, uint32_t len); | static void print_hexbytes(const void *ptr, uint32_t len); | ||||
static void print(const char *s) { Serial.print(s); } | static void print(const char *s) { Serial.print(s); } | ||||
static void print(int n) { Serial.print(n); } | static void print(int n) { Serial.print(n); } |
println(" disconnect"); | println(" disconnect"); | ||||
port_state = PORT_STATE_DISCONNECTED; | port_state = PORT_STATE_DISCONNECTED; | ||||
USBPHY_CTRL_CLR = USBPHY_CTRL_ENHOSTDISCONDETECT; | USBPHY_CTRL_CLR = USBPHY_CTRL_ENHOSTDISCONDETECT; | ||||
// TODO: delete & clean up device state... | |||||
disconnect_Device(rootdev); | |||||
rootdev = NULL; | |||||
} | } | ||||
} | } | ||||
if (portstat & USBHS_PORTSC_PEC) { | if (portstat & USBHS_PORTSC_PEC) { | ||||
return true; | return true; | ||||
} | } | ||||
static uint8_t enumbuf[256] __attribute__ ((aligned(16))); | static uint8_t enumbuf[256] __attribute__ ((aligned(16))); | ||||
static setup_t enumsetup __attribute__ ((aligned(16))); | static setup_t enumsetup __attribute__ ((aligned(16))); | ||||
static uint16_t enumlen; | static uint16_t enumlen; | ||||
static Device_t *devlist=NULL; | |||||
static uint32_t assign_addr(void); | static uint32_t assign_addr(void); | ||||
// go onto a waiting list | // go onto a waiting list | ||||
mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR | mk_setup(enumsetup, 0x80, 6, 0x0100, 0, 8); // 6=GET_DESCRIPTOR | ||||
queue_Control_Transfer(dev, &enumsetup, enumbuf, NULL); | queue_Control_Transfer(dev, &enumsetup, enumbuf, NULL); | ||||
if (devlist == NULL) { | |||||
devlist = dev; | |||||
} else { | |||||
Device_t *p; | |||||
for (p = devlist; p->next; p = p->next) ; // walk devlist | |||||
p->next = dev; | |||||
} | |||||
return dev; | return dev; | ||||
} | } | ||||
pipe->qh.capabilities[0] = (pipe->qh.capabilities[0] & 0xFFFFFF80) | addr; | pipe->qh.capabilities[0] = (pipe->qh.capabilities[0] & 0xFFFFFF80) | addr; | ||||
} | } | ||||
//static uint32_t pipe_get_addr(Pipe_t *pipe) | |||||
//{ | |||||
// return pipe->qh.capabilities[0] & 0xFFFFFF80; | |||||
//} | |||||
void USBHost::disconnect_Device(Device_t *dev) | |||||
{ | |||||
if (!dev) return; | |||||
println("disconnect_Device:"); | |||||
// Disconnect all drivers using this device. If this device is | |||||
// a hub, the hub driver is responsible for recursively calling | |||||
// this function to disconnect its downstream devices. | |||||
print_driverlist("available_drivers", available_drivers); | |||||
print_driverlist("dev->drivers", dev->drivers); | |||||
for (USBDriver *p = dev->drivers; p; ) { | |||||
println("disconnect driver ", (uint32_t)p, HEX); | |||||
p->disconnect(); | |||||
USBDriver *next = p->next; | |||||
p->next = available_drivers; | |||||
available_drivers = p; | |||||
p = next; | |||||
} | |||||
print_driverlist("available_drivers", available_drivers); | |||||
// TODO: halt all pipes, free their Transfer_t | |||||
// TODO: remove periodic scheduled pipes, free their Pipe_t | |||||
// TODO: remove async scheduled pipes, free their Pipe_t | |||||
// remove device from devlist and free its Device_t | |||||
Device_t *prev_dev = NULL; | |||||
for (Device_t *p = devlist; p; p = p->next) { | |||||
if (p == dev) { | |||||
if (prev_dev == NULL) { | |||||
devlist = p->next; | |||||
} else { | |||||
prev_dev->next = p->next; | |||||
} | |||||
println("removed Device_t from devlist"); | |||||
free_Device(p); | |||||
break; | |||||
} | |||||
prev_dev = p; | |||||
} | |||||
} | |||||
//Serial.print(); | //Serial.print(); | ||||
} | } | ||||
void USBHost::print_driverlist(const char *name, const USBDriver *driver) | |||||
{ | |||||
Serial.print("USBDriver ("); | |||||
Serial.print(name); | |||||
Serial.print(") list: "); | |||||
if (driver == NULL) { | |||||
Serial.println("(empty"); | |||||
return; | |||||
} | |||||
uint32_t count=0; | |||||
for (const USBDriver *p = driver; p; p = p->next) { | |||||
Serial.print((uint32_t)p, HEX); | |||||
if (p->next) Serial.print(" -> "); | |||||
if (++count > 30) { | |||||
Serial.println("abort:list too long"); | |||||
return; | |||||
} | |||||
} | |||||
Serial.println(); | |||||
} | |||||
void USBHost::print_hexbytes(const void *ptr, uint32_t len) | void USBHost::print_hexbytes(const void *ptr, uint32_t len) | ||||
{ | { |