update(core/usbh_core): do not use slist, we use recursion

This commit is contained in:
sakumisu
2024-06-22 15:15:58 +08:00
parent a1ab76dd3e
commit 10437a7d13
3 changed files with 147 additions and 101 deletions

View File

@@ -366,8 +366,6 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->connected = true; hub->connected = true;
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index); snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
usb_slist_add_tail(&hub->bus->hub_list, &hub->list);
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname); USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1]; hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
@@ -405,7 +403,6 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
if (hport->config.intf[intf].devname[0] != '\0') { if (hport->config.intf[intf].devname[0] != '\0') {
USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname); USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
usb_slist_remove(&hub->bus->hub_list, &hub->list);
} }
usbh_hub_class_free(hub); usbh_hub_class_free(hub);
@@ -555,8 +552,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
speed = USB_SPEED_HIGH; speed = USB_SPEED_HIGH;
} else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) { } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
speed = USB_SPEED_LOW; speed = USB_SPEED_LOW;
} } else {
else {
speed = USB_SPEED_FULL; speed = USB_SPEED_FULL;
} }
@@ -626,6 +622,17 @@ void usbh_hub_thread_wakeup(struct usbh_hub *hub)
int usbh_hub_initialize(struct usbh_bus *bus) int usbh_hub_initialize(struct usbh_bus *bus)
{ {
char thread_name[32] = { 0 }; char thread_name[32] = { 0 };
struct usbh_hub *hub;
hub = &bus->hcd.roothub;
hub->connected = true;
hub->index = 1;
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
bus->hub_mq = usb_osal_mq_create(7); bus->hub_mq = usb_osal_mq_create(7);
if (bus->hub_mq == NULL) { if (bus->hub_mq == NULL) {
@@ -644,22 +651,18 @@ int usbh_hub_initialize(struct usbh_bus *bus)
int usbh_hub_deinitialize(struct usbh_bus *bus) int usbh_hub_deinitialize(struct usbh_bus *bus)
{ {
usb_slist_t *hub_list;
struct usbh_hubport *hport; struct usbh_hubport *hport;
struct usbh_hub *hub;
size_t flags; size_t flags;
flags = usb_osal_enter_critical_section(); flags = usb_osal_enter_critical_section();
usb_slist_for_each(hub_list, &bus->hub_list) hub = &bus->hcd.roothub;
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port]; hport = &hub->child[port];
usbh_hubport_release(hport); usbh_hubport_release(hport);
} }
}
usb_hc_deinit(bus); usb_hc_deinit(bus);

View File

@@ -602,8 +602,6 @@ void usbh_hubport_release(struct usbh_hubport *hport)
static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base) static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base)
{ {
struct usbh_hub *hub;
memset(bus, 0, sizeof(struct usbh_bus)); memset(bus, 0, sizeof(struct usbh_bus));
bus->busid = busid; bus->busid = busid;
bus->hcd.hcd_id = busid; bus->hcd.hcd_id = busid;
@@ -612,20 +610,6 @@ static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uint32_t reg_base
/* devaddr 1 is for roothub */ /* devaddr 1 is for roothub */
bus->devgen.next = 2; bus->devgen.next = 2;
usb_slist_init(&bus->hub_list);
hub = &bus->hcd.roothub;
hub->connected = true;
hub->index = 1;
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
usb_slist_init(&bus->hub_list);
usb_slist_add_tail(&bus->hub_list, &hub->list);
usb_slist_add_tail(&g_bus_head, &bus->list); usb_slist_add_tail(&g_bus_head, &bus->list);
} }
@@ -669,7 +653,6 @@ int usbh_deinitialize(uint8_t busid)
usbh_hub_deinitialize(bus); usbh_hub_deinitialize(bus);
usb_slist_init(&bus->hub_list);
usb_slist_remove(&g_bus_head, &bus->list); usb_slist_remove(&g_bus_head, &bus->list);
return 0; return 0;
@@ -742,24 +725,29 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett
return usbh_control_transfer(hport, setup, NULL); return usbh_control_transfer(hport, setup, NULL);
} }
void *usbh_find_class_instance(const char *devname) static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devname)
{ {
struct usbh_hubport *hport; struct usbh_hubport *hport;
usb_slist_t *hub_list; struct usbh_hub *hub_next;
usb_slist_t *bus_list; void *priv;
usb_slist_for_each(bus_list, &g_bus_head)
{
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list)
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) { for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port]; hport = &hub->child[port];
if (hport->connected) { if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv) if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
return hport->config.intf[itf].priv; return hport->config.intf[itf].priv;
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
priv = usbh_list_all_interface_name(hub_next, devname);
if (priv) {
return priv;
}
}
} }
} }
} }
@@ -768,11 +756,101 @@ void *usbh_find_class_instance(const char *devname)
return NULL; return NULL;
} }
static void usbh_list_all_interface_driver(struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
for (uint8_t j = 0; j < hub->index; j++) {
USB_LOG_RAW("\t");
}
USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
itf,
hport->config.intf[itf].class_driver->driver_name);
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
usbh_list_all_interface_driver(hub_next);
}
}
}
}
}
}
}
static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
bus->busid,
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
if (hub_next && hub_next->connected) {
usbh_list_all_interface_desc(bus, hub_next);
}
}
}
}
}
}
}
void *usbh_find_class_instance(const char *devname)
{
usb_slist_t *bus_list;
struct usbh_hub *hub;
struct usbh_bus *bus;
void *priv;
size_t flags;
flags = usb_osal_enter_critical_section();
usb_slist_for_each(bus_list, &g_bus_head)
{
bus = usb_slist_entry(bus_list, struct usbh_bus, list);
hub = &bus->hcd.roothub;
priv = usbh_list_all_interface_name(hub, devname);
if (priv) {
usb_osal_leave_critical_section(flags);
return priv;
}
}
usb_osal_leave_critical_section(flags);
return NULL;
}
int lsusb(int argc, char **argv) int lsusb(int argc, char **argv)
{ {
usb_slist_t *hub_list;
usb_slist_t *bus_list; usb_slist_t *bus_list;
struct usbh_hubport *hport; struct usbh_hub *hub;
struct usbh_bus *bus;
size_t flags;
if (argc < 2) { if (argc < 2) {
USB_LOG_RAW("Usage: lsusb [options]...\r\n"); USB_LOG_RAW("Usage: lsusb [options]...\r\n");
@@ -795,69 +873,36 @@ int lsusb(int argc, char **argv)
return 0; return 0;
} }
flags = usb_osal_enter_critical_section();
if (strcmp(argv[1], "-V") == 0) {
USB_LOG_RAW("CherryUSB Version %s\r\n", CHERRYUSB_VERSION_STR);
}
if (strcmp(argv[1], "-t") == 0) { if (strcmp(argv[1], "-t") == 0) {
usb_slist_for_each(bus_list, &g_bus_head) usb_slist_for_each(bus_list, &g_bus_head)
{ {
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list); bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list) hub = &bus->hcd.roothub;
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
if (hub->is_roothub) {
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n", USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
bus->busid, bus->busid,
hub->index, hub->index,
hub->hub_desc.bNbrPorts); hub->hub_desc.bNbrPorts);
} else { usbh_list_all_interface_driver(hub);
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, mounted on Hub %02u:Port %u\r\n",
bus->busid,
hub->index,
hub->hub_desc.bNbrPorts,
hub->parent->parent->index,
hub->parent->port);
}
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->driver_name) {
USB_LOG_RAW("\t|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
hport->port,
hport->dev_addr,
i,
hport->config.intf[i].class_driver->driver_name);
}
}
}
}
}
} }
} }
if (strcmp(argv[1], "-v") == 0) { if (strcmp(argv[1], "-v") == 0) {
usb_slist_for_each(bus_list, &g_bus_head) usb_slist_for_each(bus_list, &g_bus_head)
{ {
struct usbh_bus *bus = usb_slist_entry(bus_list, struct usbh_bus, list); bus = usb_slist_entry(bus_list, struct usbh_bus, list);
usb_slist_for_each(hub_list, &bus->hub_list) hub = &bus->hcd.roothub;
{
struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list); usbh_list_all_interface_desc(bus, hub);
for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("Bus %u, Hub %02u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
bus->busid,
hub->index,
hport->port,
hport->dev_addr,
hport->device_desc.idVendor,
hport->device_desc.idProduct);
usbh_print_hubport_info(hport);
}
}
}
} }
} }
usb_osal_leave_critical_section(flags);
return 0; return 0;
} }

View File

@@ -116,7 +116,6 @@ struct usbh_hubport {
}; };
struct usbh_hub { struct usbh_hub {
usb_slist_t list;
bool connected; bool connected;
bool is_roothub; bool is_roothub;
uint8_t index; uint8_t index;
@@ -157,7 +156,6 @@ struct usbh_bus {
struct usbh_devaddr_map devgen; struct usbh_devaddr_map devgen;
usb_osal_thread_t hub_thread; usb_osal_thread_t hub_thread;
usb_osal_mq_t hub_mq; usb_osal_mq_t hub_mq;
usb_slist_t hub_list;
}; };
static inline void usbh_control_urb_fill(struct usbh_urb *urb, static inline void usbh_control_urb_fill(struct usbh_urb *urb,