optimise hub debounce process

This commit is contained in:
sakimisu
2022-12-31 14:06:53 +08:00
parent 902f1da407
commit 62276b1e8b

View File

@@ -7,8 +7,9 @@
#define DEV_FORMAT "/dev/hub%d" #define DEV_FORMAT "/dev/hub%d"
#define DEBOUNCE_TIMEOUT 400 #define HUB_DEBOUNCE_TIMEOUT 1500
#define DEBOUNCE_TIME_STEP 25 #define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
#define DELAY_TIME_AFTER_RESET 200 #define DELAY_TIME_AFTER_RESET 200
#define EXTHUB_FIRST_INDEX 2 #define EXTHUB_FIRST_INDEX 2
@@ -351,6 +352,20 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
} }
#endif #endif
static void usbh_hubport_release(struct usbh_hubport *child)
{
if (child->connected) {
child->connected = false;
usbh_hport_deactivate_ep0(child);
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(child, i);
}
}
child->config.config_desc.bNumInterfaces = 0;
}
}
static void usbh_hub_events(struct usbh_hub *hub) static void usbh_hub_events(struct usbh_hub *hub)
{ {
struct usbh_hubport *child; struct usbh_hubport *child;
@@ -412,8 +427,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
if (portchange & HUB_PORT_STATUS_C_CONNECTION) { if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
uint16_t connection = 0; uint16_t connection = 0;
uint16_t debouncestable = 0; uint16_t debouncestable = 0;
for (uint32_t debouncetime = 0; debouncetime < DEBOUNCE_TIMEOUT; debouncetime += DEBOUNCE_TIME_STEP) { for (uint32_t debouncetime = 0; debouncetime < HUB_DEBOUNCE_TIMEOUT; debouncetime += HUB_DEBOUNCE_STEP) {
usb_osal_msleep(DEBOUNCE_TIME_STEP);
/* Read hub port status */ /* Read hub port status */
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status); ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
if (ret < 0) { if (ret < 0) {
@@ -425,21 +439,29 @@ static void usbh_hub_events(struct usbh_hub *hub)
portchange = port_status.wPortChange; portchange = port_status.wPortChange;
USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange); USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
if ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection) {
if (connection) { if (!(portchange & HUB_PORT_STATUS_C_CONNECTION) &&
if (++debouncestable == 4) { ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection)) {
break; debouncestable += HUB_DEBOUNCE_STEP;
} if (debouncestable >= HUB_DEBOUNCE_STABLE) {
break;
} }
} else { } else {
debouncestable = 0; debouncestable = 0;
connection = portstatus & HUB_PORT_STATUS_CONNECTION;
} }
connection = portstatus & HUB_PORT_STATUS_CONNECTION;
if (portchange & HUB_PORT_STATUS_C_CONNECTION) { if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION); usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION);
} }
usb_osal_msleep(HUB_DEBOUNCE_STEP);
}
/** check if debounce ok */
if (debouncestable < HUB_DEBOUNCE_STABLE) {
USB_LOG_ERR("Failed to debounce port %u\r\n", port + 1);
break;
} }
/* Last, check connect status */ /* Last, check connect status */
@@ -477,16 +499,8 @@ static void usbh_hub_events(struct usbh_hub *hub)
} }
child = &hub->child[port]; child = &hub->child[port];
if (child->connected) { /** release child sources first */
child->connected = false; usbh_hubport_release(child);
usbh_hport_deactivate_ep0(child);
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(child, i);
}
}
child->config.config_desc.bNumInterfaces = 0;
}
memset(child, 0, sizeof(struct usbh_hubport)); memset(child, 0, sizeof(struct usbh_hubport));
child->parent = hub; child->parent = hub;
@@ -503,30 +517,15 @@ static void usbh_hub_events(struct usbh_hub *hub)
USB_LOG_ERR("Failed to enable port %u\r\n", port + 1); USB_LOG_ERR("Failed to enable port %u\r\n", port + 1);
child = &hub->child[port]; child = &hub->child[port];
if (child->connected) { /** release child sources */
child->connected = false; usbh_hubport_release(child);
usbh_hport_deactivate_ep0(child);
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(child, i);
}
}
}
child->config.config_desc.bNumInterfaces = 0;
continue; continue;
} }
} else { } else {
child = &hub->child[port]; child = &hub->child[port];
child->connected = false; /** release child sources */
usbh_hport_deactivate_ep0(child); usbh_hubport_release(child);
for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
CLASS_DISCONNECT(child, i);
}
}
USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
child->config.config_desc.bNumInterfaces = 0;
} }
} }
} }