| 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) | ||||
| { | { |