usbh_hub.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /*
  2. * Copyright (c) 2022, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbh_core.h"
  7. #include "usbh_hub.h"
  8. #undef USB_DBG_TAG
  9. #define USB_DBG_TAG "usbh_hub"
  10. #include "usb_log.h"
  11. #define DEV_FORMAT "/dev/hub%d"
  12. #define HUB_DEBOUNCE_TIMEOUT 1500
  13. #define HUB_DEBOUNCE_STEP 25
  14. #define HUB_DEBOUNCE_STABLE 100
  15. #define DELAY_TIME_AFTER_RESET 200
  16. #define EXTHUB_FIRST_INDEX 2
  17. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(32, CONFIG_USB_ALIGN_SIZE)];
  18. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_intbuf[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][USB_ALIGN_UP(1, CONFIG_USB_ALIGN_SIZE)];
  19. extern int usbh_enumerate(struct usbh_hubport *hport);
  20. extern void usbh_hubport_release(struct usbh_hubport *hport);
  21. static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
  22. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  23. static struct usbh_hub g_hub_class[CONFIG_USBHOST_MAX_EXTHUBS];
  24. static uint32_t g_devinuse = 0;
  25. static struct usbh_hub *usbh_hub_class_alloc(void)
  26. {
  27. uint8_t devno;
  28. for (devno = 0; devno < CONFIG_USBHOST_MAX_EXTHUBS; devno++) {
  29. if ((g_devinuse & (1U << devno)) == 0) {
  30. g_devinuse |= (1U << devno);
  31. memset(&g_hub_class[devno], 0, sizeof(struct usbh_hub));
  32. g_hub_class[devno].index = EXTHUB_FIRST_INDEX + devno;
  33. return &g_hub_class[devno];
  34. }
  35. }
  36. return NULL;
  37. }
  38. static void usbh_hub_class_free(struct usbh_hub *hub_class)
  39. {
  40. uint8_t devno = hub_class->index - EXTHUB_FIRST_INDEX;
  41. if (devno < 32) {
  42. g_devinuse &= ~(1U << devno);
  43. }
  44. memset(hub_class, 0, sizeof(struct usbh_hub));
  45. }
  46. static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
  47. {
  48. struct usb_setup_packet *setup;
  49. int ret;
  50. setup = hub->parent->setup;
  51. setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
  52. setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
  53. setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
  54. setup->wIndex = 0;
  55. setup->wLength = USB_SIZEOF_HUB_DESC;
  56. ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
  57. if (ret < 0) {
  58. return ret;
  59. }
  60. memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
  61. return ret;
  62. }
  63. static int _usbh_hub_get_hub_ss_descriptor(struct usbh_hub *hub, uint8_t *buffer)
  64. {
  65. struct usb_setup_packet *setup;
  66. int ret;
  67. setup = hub->parent->setup;
  68. setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
  69. setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
  70. setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
  71. setup->wIndex = 0;
  72. setup->wLength = USB_SIZEOF_HUB_SS_DESC;
  73. ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
  74. if (ret < 0) {
  75. return ret;
  76. }
  77. memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_SS_DESC);
  78. return ret;
  79. }
  80. #endif
  81. static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
  82. {
  83. struct usb_setup_packet *setup;
  84. int ret;
  85. setup = hub->parent->setup;
  86. setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  87. setup->bRequest = HUB_REQUEST_GET_STATUS;
  88. setup->wValue = 0;
  89. setup->wIndex = port;
  90. setup->wLength = 4;
  91. ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
  92. if (ret < 0) {
  93. return ret;
  94. }
  95. memcpy(port_status, g_hub_buf[hub->bus->busid], 4);
  96. return ret;
  97. }
  98. static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
  99. {
  100. struct usb_setup_packet *setup;
  101. setup = hub->parent->setup;
  102. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  103. setup->bRequest = HUB_REQUEST_SET_FEATURE;
  104. setup->wValue = feature;
  105. setup->wIndex = port;
  106. setup->wLength = 0;
  107. return usbh_control_transfer(hub->parent, setup, NULL);
  108. }
  109. static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
  110. {
  111. struct usb_setup_packet *setup;
  112. setup = hub->parent->setup;
  113. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  114. setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
  115. setup->wValue = feature;
  116. setup->wIndex = port;
  117. setup->wLength = 0;
  118. return usbh_control_transfer(hub->parent, setup, NULL);
  119. }
  120. static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
  121. {
  122. struct usb_setup_packet *setup;
  123. setup = hub->parent->setup;
  124. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
  125. setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
  126. setup->wValue = depth;
  127. setup->wIndex = 0;
  128. setup->wLength = 0;
  129. return usbh_control_transfer(hub->parent, setup, NULL);
  130. }
  131. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  132. static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
  133. {
  134. (void)length;
  135. if (desc->bLength != USB_SIZEOF_HUB_DESC) {
  136. USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
  137. return -1;
  138. } else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB) {
  139. USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
  140. return -2;
  141. } else {
  142. USB_LOG_RAW("Hub Descriptor:\r\n");
  143. USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
  144. USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
  145. USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
  146. USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
  147. USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
  148. USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
  149. USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
  150. USB_LOG_RAW("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask);
  151. }
  152. return 0;
  153. }
  154. static int parse_hub_ss_descriptor(struct usb_hub_ss_descriptor *desc, uint16_t length)
  155. {
  156. (void)length;
  157. if (desc->bLength < USB_SIZEOF_HUB_SS_DESC) {
  158. USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
  159. return -1;
  160. } else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB3) {
  161. USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
  162. return -2;
  163. } else {
  164. USB_LOG_RAW("SuperSpeed Hub Descriptor:\r\n");
  165. USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
  166. USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
  167. USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
  168. USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
  169. USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
  170. USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
  171. USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
  172. }
  173. return 0;
  174. }
  175. #endif
  176. static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
  177. {
  178. struct usb_setup_packet roothub_setup;
  179. struct usb_setup_packet *setup;
  180. if (hub->is_roothub) {
  181. setup = &roothub_setup;
  182. setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  183. setup->bRequest = HUB_REQUEST_GET_STATUS;
  184. setup->wValue = 0;
  185. setup->wIndex = port;
  186. setup->wLength = 4;
  187. return usbh_roothub_control(hub->bus, &roothub_setup, (uint8_t *)port_status);
  188. } else {
  189. return _usbh_hub_get_portstatus(hub, port, port_status);
  190. }
  191. }
  192. int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
  193. {
  194. struct usb_setup_packet roothub_setup;
  195. struct usb_setup_packet *setup;
  196. if (hub->is_roothub) {
  197. setup = &roothub_setup;
  198. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  199. setup->bRequest = HUB_REQUEST_SET_FEATURE;
  200. setup->wValue = feature;
  201. setup->wIndex = port;
  202. setup->wLength = 0;
  203. return usbh_roothub_control(hub->bus, setup, NULL);
  204. } else {
  205. return _usbh_hub_set_feature(hub, port, feature);
  206. }
  207. }
  208. int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
  209. {
  210. struct usb_setup_packet roothub_setup;
  211. struct usb_setup_packet *setup;
  212. if (hub->is_roothub) {
  213. setup = &roothub_setup;
  214. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  215. setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
  216. setup->wValue = feature;
  217. setup->wIndex = port;
  218. setup->wLength = 0;
  219. return usbh_roothub_control(hub->bus, setup, NULL);
  220. } else {
  221. return _usbh_hub_clear_feature(hub, port, feature);
  222. }
  223. }
  224. static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
  225. {
  226. struct usb_setup_packet roothub_setup;
  227. struct usb_setup_packet *setup;
  228. if (hub->is_roothub) {
  229. setup = &roothub_setup;
  230. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
  231. setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
  232. setup->wValue = depth;
  233. setup->wIndex = 0;
  234. setup->wLength = 0;
  235. return usbh_roothub_control(hub->bus, setup, NULL);
  236. } else {
  237. return _usbh_hub_set_depth(hub, depth);
  238. }
  239. }
  240. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  241. static void hub_int_complete_callback(void *arg, int nbytes)
  242. {
  243. struct usbh_hub *hub = (struct usbh_hub *)arg;
  244. if (nbytes > 0) {
  245. usbh_hub_thread_wakeup(hub);
  246. } else if (nbytes == -USB_ERR_NAK) {
  247. /* Restart timer to submit urb again */
  248. USB_LOG_DBG("Restart timer\r\n");
  249. usb_osal_timer_start(hub->int_timer);
  250. } else {
  251. }
  252. }
  253. static void hub_int_timeout(void *arg)
  254. {
  255. struct usbh_hub *hub = (struct usbh_hub *)arg;
  256. usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
  257. usbh_submit_urb(&hub->intin_urb);
  258. }
  259. static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
  260. {
  261. struct usb_endpoint_descriptor *ep_desc;
  262. struct hub_port_status port_status;
  263. int ret;
  264. struct usbh_hub *hub = usbh_hub_class_alloc();
  265. if (hub == NULL) {
  266. USB_LOG_ERR("Fail to alloc hub_class\r\n");
  267. return -USB_ERR_NOMEM;
  268. }
  269. hub->hub_addr = hport->dev_addr;
  270. hub->parent = hport;
  271. hub->bus = hport->bus;
  272. hub->speed = hport->speed;
  273. hport->self = hub;
  274. hport->config.intf[intf].priv = hub;
  275. if (hport->depth > HUB_MAX_DEPTH) {
  276. USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
  277. return -USB_ERR_INVAL;
  278. }
  279. /*
  280. * Super-Speed hubs need to know their depth to be able to
  281. * parse the bits of the route-string that correspond to
  282. * their downstream port number.
  283. *
  284. */
  285. if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
  286. ret = usbh_hub_set_depth(hub, hport->depth - 1);
  287. if (ret < 0) {
  288. USB_LOG_ERR("Unable to set hub depth \r\n");
  289. return ret;
  290. }
  291. }
  292. /* Get hub descriptor. */
  293. if (hport->speed == USB_SPEED_SUPER) {
  294. ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
  295. if (ret < 0) {
  296. return ret;
  297. }
  298. parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
  299. hub->nports = hub->hub_ss_desc.bNbrPorts;
  300. hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
  301. hub->tt_think = 0U;
  302. } else {
  303. ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
  304. if (ret < 0) {
  305. return ret;
  306. }
  307. parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
  308. hub->nports = hub->hub_desc.bNbrPorts;
  309. hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
  310. hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
  311. }
  312. for (uint8_t port = 0; port < hub->nports; port++) {
  313. hub->child[port].port = port + 1;
  314. hub->child[port].parent = hub;
  315. hub->child[port].bus = hport->bus;
  316. }
  317. if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
  318. hub->ismtt = 1;
  319. } else {
  320. hub->ismtt = 0;
  321. }
  322. ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
  323. if (ep_desc->bEndpointAddress & 0x80) {
  324. USBH_EP_INIT(hub->intin, ep_desc);
  325. } else {
  326. return -1;
  327. }
  328. for (uint8_t port = 0; port < hub->nports; port++) {
  329. ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
  330. if (ret < 0) {
  331. return ret;
  332. }
  333. }
  334. usb_osal_msleep(hub->powerdelay);
  335. for (uint8_t port = 0; port < hub->nports; port++) {
  336. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  337. USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
  338. if (ret < 0) {
  339. return ret;
  340. }
  341. }
  342. hub->connected = true;
  343. snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
  344. USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
  345. hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
  346. hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed), hub_int_timeout, hub, 0);
  347. if (hub->int_timer == NULL) {
  348. USB_LOG_ERR("No memory to alloc int_timer\r\n");
  349. return -USB_ERR_NOMEM;
  350. }
  351. usb_osal_timer_start(hub->int_timer);
  352. return 0;
  353. }
  354. static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
  355. {
  356. struct usbh_hubport *child;
  357. int ret = 0;
  358. struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
  359. if (hub) {
  360. if (hub->intin) {
  361. usbh_kill_urb(&hub->intin_urb);
  362. }
  363. if (hub->int_timer) {
  364. usb_osal_timer_delete(hub->int_timer);
  365. }
  366. for (uint8_t port = 0; port < hub->nports; port++) {
  367. child = &hub->child[port];
  368. usbh_hubport_release(child);
  369. child->parent = NULL;
  370. }
  371. if (hport->config.intf[intf].devname[0] != '\0') {
  372. USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
  373. }
  374. usbh_hub_class_free(hub);
  375. }
  376. return ret;
  377. }
  378. #endif
  379. static void usbh_hub_events(struct usbh_hub *hub)
  380. {
  381. struct usbh_hubport *child;
  382. struct hub_port_status port_status;
  383. uint16_t portchange_index;
  384. uint16_t portstatus;
  385. uint16_t portchange;
  386. uint16_t mask;
  387. uint16_t feat;
  388. uint8_t speed;
  389. int ret;
  390. size_t flags;
  391. if (!hub->connected) {
  392. return;
  393. }
  394. flags = usb_osal_enter_critical_section();
  395. memcpy(&portchange_index, hub->int_buffer, 2);
  396. usb_osal_leave_critical_section(flags);
  397. for (uint8_t port = 0; port < hub->nports; port++) {
  398. USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
  399. if (!(portchange_index & (1 << (port + 1)))) {
  400. continue;
  401. }
  402. portchange_index &= ~(1 << (port + 1));
  403. USB_LOG_DBG("Port %d change\r\n", port + 1);
  404. /* Read hub port status */
  405. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  406. if (ret < 0) {
  407. USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
  408. continue;
  409. }
  410. portstatus = port_status.wPortStatus;
  411. portchange = port_status.wPortChange;
  412. USB_LOG_DBG("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
  413. /* First, clear all change bits */
  414. mask = 1;
  415. feat = HUB_PORT_FEATURE_C_CONNECTION;
  416. while (portchange) {
  417. if (portchange & mask) {
  418. ret = usbh_hub_clear_feature(hub, port + 1, feat);
  419. if (ret < 0) {
  420. USB_LOG_ERR("Failed to clear port %u, change mask:%04x, errorcode:%d\r\n", port + 1, mask, ret);
  421. continue;
  422. }
  423. portchange &= (~mask);
  424. }
  425. mask <<= 1;
  426. feat++;
  427. }
  428. portchange = port_status.wPortChange;
  429. /* Second, if port changes, debounces first */
  430. if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
  431. uint16_t connection = 0;
  432. uint16_t debouncestable = 0;
  433. for (uint32_t debouncetime = 0; debouncetime < HUB_DEBOUNCE_TIMEOUT; debouncetime += HUB_DEBOUNCE_STEP) {
  434. /* Read hub port status */
  435. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  436. if (ret < 0) {
  437. USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
  438. continue;
  439. }
  440. portstatus = port_status.wPortStatus;
  441. portchange = port_status.wPortChange;
  442. USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
  443. if (!(portchange & HUB_PORT_STATUS_C_CONNECTION) &&
  444. ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection)) {
  445. debouncestable += HUB_DEBOUNCE_STEP;
  446. if (debouncestable >= HUB_DEBOUNCE_STABLE) {
  447. break;
  448. }
  449. } else {
  450. debouncestable = 0;
  451. connection = portstatus & HUB_PORT_STATUS_CONNECTION;
  452. }
  453. if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
  454. usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION);
  455. }
  456. usb_osal_msleep(HUB_DEBOUNCE_STEP);
  457. }
  458. /** check if debounce ok */
  459. if (debouncestable < HUB_DEBOUNCE_STABLE) {
  460. USB_LOG_ERR("Failed to debounce port %u\r\n", port + 1);
  461. break;
  462. }
  463. /* Last, check connect status */
  464. if (portstatus & HUB_PORT_STATUS_CONNECTION) {
  465. ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_RESET);
  466. if (ret < 0) {
  467. USB_LOG_ERR("Failed to reset port %u,errorcode:%d\r\n", port, ret);
  468. continue;
  469. }
  470. usb_osal_msleep(DELAY_TIME_AFTER_RESET);
  471. /* Read hub port status */
  472. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  473. if (ret < 0) {
  474. USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
  475. continue;
  476. }
  477. portstatus = port_status.wPortStatus;
  478. portchange = port_status.wPortChange;
  479. if (!(portstatus & HUB_PORT_STATUS_RESET) && (portstatus & HUB_PORT_STATUS_ENABLE)) {
  480. if (portchange & HUB_PORT_STATUS_C_RESET) {
  481. ret = usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_RESET);
  482. if (ret < 0) {
  483. USB_LOG_ERR("Failed to clear port %u reset change, errorcode: %d\r\n", port, ret);
  484. }
  485. }
  486. /*
  487. * Figure out device speed. This is a bit tricky because
  488. * HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
  489. */
  490. if (portstatus & HUB_PORT_STATUS_POWER) {
  491. if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
  492. speed = USB_SPEED_HIGH;
  493. } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
  494. speed = USB_SPEED_LOW;
  495. } else {
  496. speed = USB_SPEED_FULL;
  497. }
  498. } else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
  499. speed = USB_SPEED_SUPER;
  500. } else {
  501. USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
  502. continue;
  503. }
  504. child = &hub->child[port];
  505. /** release child sources first */
  506. usbh_hubport_release(child);
  507. memset(child, 0, sizeof(struct usbh_hubport));
  508. child->parent = hub;
  509. child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
  510. child->connected = true;
  511. child->port = port + 1;
  512. child->speed = speed;
  513. child->bus = hub->bus;
  514. child->mutex = usb_osal_mutex_create();
  515. USB_LOG_INFO("New %s device on Bus %u, Hub %u, Port %u connected\r\n", speed_table[speed], hub->bus->busid, hub->index, port + 1);
  516. if (usbh_enumerate(child) < 0) {
  517. /** release child sources */
  518. usbh_hubport_release(child);
  519. USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
  520. }
  521. } else {
  522. child = &hub->child[port];
  523. /** release child sources */
  524. usbh_hubport_release(child);
  525. /** some USB 3.0 ip may failed to enable USB 2.0 port for USB 3.0 device */
  526. USB_LOG_WRN("Failed to enable port %u\r\n", port + 1);
  527. continue;
  528. }
  529. } else {
  530. child = &hub->child[port];
  531. /** release child sources */
  532. usbh_hubport_release(child);
  533. USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hub->bus->busid, hub->index, port + 1);
  534. }
  535. }
  536. }
  537. /* Start next hub int transfer */
  538. if (!hub->is_roothub && hub->connected) {
  539. usb_osal_timer_start(hub->int_timer);
  540. }
  541. }
  542. static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
  543. {
  544. struct usbh_hub *hub;
  545. int ret = 0;
  546. struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
  547. usb_hc_init(bus);
  548. while (1) {
  549. ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
  550. if (ret < 0) {
  551. continue;
  552. }
  553. usbh_hub_events(hub);
  554. }
  555. }
  556. void usbh_hub_thread_wakeup(struct usbh_hub *hub)
  557. {
  558. usb_osal_mq_send(hub->bus->hub_mq, (uintptr_t)hub);
  559. }
  560. int usbh_hub_initialize(struct usbh_bus *bus)
  561. {
  562. char thread_name[32] = { 0 };
  563. struct usbh_hub *hub;
  564. hub = &bus->hcd.roothub;
  565. hub->connected = true;
  566. hub->index = 1;
  567. hub->is_roothub = true;
  568. hub->parent = NULL;
  569. hub->hub_addr = 1;
  570. hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
  571. hub->int_buffer = bus->hcd.roothub_intbuf;
  572. hub->bus = bus;
  573. bus->hub_mq = usb_osal_mq_create(7);
  574. if (bus->hub_mq == NULL) {
  575. USB_LOG_ERR("Failed to create hub mq\r\n");
  576. return -1;
  577. }
  578. snprintf(thread_name, 32, "usbh_hub%u", bus->busid);
  579. bus->hub_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, bus);
  580. if (bus->hub_thread == NULL) {
  581. USB_LOG_ERR("Failed to create hub thread\r\n");
  582. return -1;
  583. }
  584. return 0;
  585. }
  586. int usbh_hub_deinitialize(struct usbh_bus *bus)
  587. {
  588. struct usbh_hubport *hport;
  589. struct usbh_hub *hub;
  590. size_t flags;
  591. flags = usb_osal_enter_critical_section();
  592. hub = &bus->hcd.roothub;
  593. for (uint8_t port = 0; port < hub->nports; port++) {
  594. hport = &hub->child[port];
  595. usbh_hubport_release(hport);
  596. }
  597. usb_hc_deinit(bus);
  598. usb_osal_leave_critical_section(flags);
  599. usb_osal_mq_delete(bus->hub_mq);
  600. usb_osal_thread_delete(bus->hub_thread);
  601. return 0;
  602. }
  603. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  604. const struct usbh_class_driver hub_class_driver = {
  605. .driver_name = "hub",
  606. .connect = usbh_hub_connect,
  607. .disconnect = usbh_hub_disconnect
  608. };
  609. CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
  610. .match_flags = USB_CLASS_MATCH_INTF_CLASS,
  611. .bInterfaceClass = USB_DEVICE_CLASS_HUB,
  612. .bInterfaceSubClass = 0,
  613. .bInterfaceProtocol = 0,
  614. .id_table = NULL,
  615. .class_driver = &hub_class_driver
  616. };
  617. #endif