usbh_hub.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  121. static int _usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
  122. {
  123. struct usb_setup_packet *setup;
  124. setup = hub->parent->setup;
  125. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
  126. setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
  127. setup->wValue = depth;
  128. setup->wIndex = 0;
  129. setup->wLength = 0;
  130. return usbh_control_transfer(hub->parent, setup, NULL);
  131. }
  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_DBG("Hub Descriptor:\r\n");
  143. USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
  144. USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
  145. USB_LOG_DBG("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
  146. USB_LOG_DBG("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
  147. USB_LOG_DBG("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
  148. USB_LOG_DBG("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
  149. USB_LOG_DBG("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
  150. USB_LOG_DBG("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_DBG("SuperSpeed Hub Descriptor:\r\n");
  165. USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
  166. USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
  167. USB_LOG_DBG("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
  168. USB_LOG_DBG("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
  169. USB_LOG_DBG("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
  170. USB_LOG_DBG("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
  171. USB_LOG_DBG("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. int ret;
  197. if (hub->is_roothub) {
  198. setup = &roothub_setup;
  199. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  200. setup->bRequest = HUB_REQUEST_SET_FEATURE;
  201. setup->wValue = feature;
  202. setup->wIndex = port;
  203. setup->wLength = 0;
  204. ret = usbh_roothub_control(hub->bus, setup, NULL);
  205. if ((feature == HUB_PORT_FEATURE_RESET) && (ret >= 0)) {
  206. hub->bus->event_handler(hub->bus->busid, hub->index, port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_RESET);
  207. }
  208. return ret;
  209. } else {
  210. ret = _usbh_hub_set_feature(hub, port, feature);
  211. if ((feature == HUB_PORT_FEATURE_RESET) && (ret >= 0)) {
  212. hub->bus->event_handler(hub->bus->busid, hub->index, port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_RESET);
  213. }
  214. return ret;
  215. }
  216. }
  217. int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
  218. {
  219. struct usb_setup_packet roothub_setup;
  220. struct usb_setup_packet *setup;
  221. if (hub->is_roothub) {
  222. setup = &roothub_setup;
  223. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
  224. setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
  225. setup->wValue = feature;
  226. setup->wIndex = port;
  227. setup->wLength = 0;
  228. return usbh_roothub_control(hub->bus, setup, NULL);
  229. } else {
  230. return _usbh_hub_clear_feature(hub, port, feature);
  231. }
  232. }
  233. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  234. static int usbh_hub_set_depth(struct usbh_hub *hub, uint16_t depth)
  235. {
  236. struct usb_setup_packet roothub_setup;
  237. struct usb_setup_packet *setup;
  238. if (hub->is_roothub) {
  239. setup = &roothub_setup;
  240. setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
  241. setup->bRequest = HUB_REQUEST_SET_HUB_DEPTH;
  242. setup->wValue = depth;
  243. setup->wIndex = 0;
  244. setup->wLength = 0;
  245. return usbh_roothub_control(hub->bus, setup, NULL);
  246. } else {
  247. return _usbh_hub_set_depth(hub, depth);
  248. }
  249. }
  250. static void hub_int_complete_callback(void *arg, int nbytes)
  251. {
  252. struct usbh_hub *hub = (struct usbh_hub *)arg;
  253. if (nbytes > 0) {
  254. usbh_hub_thread_wakeup(hub);
  255. } else if (nbytes == -USB_ERR_NAK) {
  256. /* Restart timer to submit urb again */
  257. USB_LOG_DBG("Restart timer\r\n");
  258. usb_osal_timer_start(hub->int_timer);
  259. } else {
  260. }
  261. }
  262. static void hub_int_timeout(void *arg)
  263. {
  264. struct usbh_hub *hub = (struct usbh_hub *)arg;
  265. usbh_int_urb_fill(&hub->intin_urb, hub->parent, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
  266. usbh_submit_urb(&hub->intin_urb);
  267. }
  268. static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
  269. {
  270. struct usb_endpoint_descriptor *ep_desc;
  271. struct hub_port_status port_status;
  272. int ret;
  273. struct usbh_hub *hub = usbh_hub_class_alloc();
  274. if (hub == NULL) {
  275. USB_LOG_ERR("Fail to alloc hub_class\r\n");
  276. return -USB_ERR_NOMEM;
  277. }
  278. hub->hub_addr = hport->dev_addr;
  279. hub->parent = hport;
  280. hub->bus = hport->bus;
  281. hub->speed = hport->speed;
  282. hport->self = hub;
  283. hport->config.intf[intf].priv = hub;
  284. if (hport->depth > HUB_MAX_DEPTH) {
  285. USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
  286. return -USB_ERR_INVAL;
  287. }
  288. /*
  289. * Super-Speed hubs need to know their depth to be able to
  290. * parse the bits of the route-string that correspond to
  291. * their downstream port number.
  292. *
  293. */
  294. if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
  295. ret = usbh_hub_set_depth(hub, hport->depth - 1);
  296. if (ret < 0) {
  297. USB_LOG_ERR("Unable to set hub depth \r\n");
  298. return ret;
  299. }
  300. }
  301. /* Get hub descriptor. */
  302. if (hport->speed == USB_SPEED_SUPER) {
  303. ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
  304. if (ret < 0) {
  305. return ret;
  306. }
  307. parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
  308. hub->nports = hub->hub_ss_desc.bNbrPorts;
  309. hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
  310. hub->tt_think = 0U;
  311. } else {
  312. ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
  313. if (ret < 0) {
  314. return ret;
  315. }
  316. parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
  317. hub->nports = hub->hub_desc.bNbrPorts;
  318. hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
  319. hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
  320. }
  321. if (hub->nports > CONFIG_USBHOST_MAX_EHPORTS) {
  322. USB_LOG_ERR("Hub nports %u overflow\r\n", hub->nports);
  323. return -USB_ERR_NOMEM;
  324. }
  325. for (uint8_t port = 0; port < hub->nports; port++) {
  326. hub->child[port].port = port + 1;
  327. hub->child[port].parent = hub;
  328. hub->child[port].bus = hport->bus;
  329. }
  330. if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
  331. hub->ismtt = 1;
  332. } else {
  333. hub->ismtt = 0;
  334. }
  335. ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
  336. if (ep_desc->bEndpointAddress & 0x80) {
  337. USBH_EP_INIT(hub->intin, ep_desc);
  338. } else {
  339. return -1;
  340. }
  341. for (uint8_t port = 0; port < hub->nports; port++) {
  342. ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
  343. if (ret < 0) {
  344. return ret;
  345. }
  346. }
  347. usb_osal_msleep(hub->powerdelay);
  348. for (uint8_t port = 0; port < hub->nports; port++) {
  349. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  350. USB_LOG_DBG("port %u, status:0x%03x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
  351. if (ret < 0) {
  352. return ret;
  353. }
  354. }
  355. hub->connected = true;
  356. snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
  357. USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
  358. hub->int_buffer = g_hub_intbuf[hub->bus->busid][hub->index - 1];
  359. hub->int_timer = usb_osal_timer_create("hubint_tim", USBH_GET_URB_INTERVAL(hub->intin->bInterval, hport->speed) / 1000, hub_int_timeout, hub, 0);
  360. if (hub->int_timer == NULL) {
  361. USB_LOG_ERR("No memory to alloc int_timer\r\n");
  362. return -USB_ERR_NOMEM;
  363. }
  364. usb_osal_timer_start(hub->int_timer);
  365. return 0;
  366. }
  367. static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
  368. {
  369. struct usbh_hubport *child;
  370. int ret = 0;
  371. struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
  372. if (hub) {
  373. if (hub->intin) {
  374. usbh_kill_urb(&hub->intin_urb);
  375. }
  376. if (hub->int_timer) {
  377. usb_osal_timer_delete(hub->int_timer);
  378. }
  379. for (uint8_t port = 0; port < hub->nports; port++) {
  380. child = &hub->child[port];
  381. usbh_hubport_release(child);
  382. child->parent = NULL;
  383. }
  384. if (hport->config.intf[intf].devname[0] != '\0') {
  385. USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
  386. }
  387. usbh_hub_class_free(hub);
  388. }
  389. return ret;
  390. }
  391. #endif
  392. static void usbh_hub_events(struct usbh_hub *hub)
  393. {
  394. struct usbh_hubport *child;
  395. struct hub_port_status port_status;
  396. uint16_t portchange_index;
  397. uint16_t portstatus;
  398. uint16_t portchange;
  399. uint16_t mask;
  400. uint16_t feat;
  401. uint8_t speed;
  402. int ret;
  403. size_t flags;
  404. (void)speed_table;
  405. if (!hub->connected) {
  406. return;
  407. }
  408. flags = usb_osal_enter_critical_section();
  409. memcpy(&portchange_index, hub->int_buffer, 2);
  410. usb_osal_leave_critical_section(flags);
  411. for (uint8_t port = 0; port < hub->nports; port++) {
  412. USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
  413. if (!(portchange_index & (1 << (port + 1)))) {
  414. continue;
  415. }
  416. portchange_index &= ~(1 << (port + 1));
  417. USB_LOG_DBG("Port %d change\r\n", port + 1);
  418. /* Read hub port status */
  419. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  420. if (ret < 0) {
  421. USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
  422. continue;
  423. }
  424. portstatus = port_status.wPortStatus;
  425. portchange = port_status.wPortChange;
  426. USB_LOG_DBG("port %u, status:0x%03x, change:0x%02x\r\n", port + 1, portstatus, portchange);
  427. /* First, clear all change bits */
  428. mask = 1;
  429. feat = HUB_PORT_FEATURE_C_CONNECTION;
  430. while (portchange) {
  431. if (portchange & mask) {
  432. ret = usbh_hub_clear_feature(hub, port + 1, feat);
  433. if (ret < 0) {
  434. USB_LOG_ERR("Failed to clear port %u, change mask:%04x, errorcode:%d\r\n", port + 1, mask, ret);
  435. continue;
  436. }
  437. portchange &= (~mask);
  438. }
  439. mask <<= 1;
  440. feat++;
  441. }
  442. portchange = port_status.wPortChange;
  443. /* Second, if port changes, debounces first */
  444. if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
  445. uint16_t connection = 0;
  446. uint16_t debouncestable = 0;
  447. for (uint32_t debouncetime = 0; debouncetime < HUB_DEBOUNCE_TIMEOUT; debouncetime += HUB_DEBOUNCE_STEP) {
  448. /* Read hub port status */
  449. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  450. if (ret < 0) {
  451. USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
  452. continue;
  453. }
  454. portstatus = port_status.wPortStatus;
  455. portchange = port_status.wPortChange;
  456. USB_LOG_DBG("Port %u, status:0x%03x, change:0x%02x\r\n", port + 1, portstatus, portchange);
  457. if (!(portchange & HUB_PORT_STATUS_C_CONNECTION) &&
  458. ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection)) {
  459. debouncestable += HUB_DEBOUNCE_STEP;
  460. if (debouncestable >= HUB_DEBOUNCE_STABLE) {
  461. break;
  462. }
  463. } else {
  464. debouncestable = 0;
  465. connection = portstatus & HUB_PORT_STATUS_CONNECTION;
  466. }
  467. if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
  468. usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION);
  469. }
  470. usb_osal_msleep(HUB_DEBOUNCE_STEP);
  471. }
  472. /** check if debounce ok */
  473. if (debouncestable < HUB_DEBOUNCE_STABLE) {
  474. USB_LOG_ERR("Failed to debounce port %u\r\n", port + 1);
  475. break;
  476. }
  477. /* Last, check connect status */
  478. if (portstatus & HUB_PORT_STATUS_CONNECTION) {
  479. hub->bus->event_handler(hub->bus->busid, hub->index, port + 1, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_CONNECTED);
  480. ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_RESET);
  481. if (ret < 0) {
  482. USB_LOG_ERR("Failed to reset port %u, errorcode: %d\r\n", port + 1, ret);
  483. continue;
  484. }
  485. usb_osal_msleep(DELAY_TIME_AFTER_RESET);
  486. /* Read hub port status */
  487. ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
  488. if (ret < 0) {
  489. USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
  490. continue;
  491. }
  492. portstatus = port_status.wPortStatus;
  493. portchange = port_status.wPortChange;
  494. USB_LOG_DBG("Port %u, status:0x%03x, change:0x%02x\r\n", port + 1, portstatus, portchange);
  495. if (!(portstatus & HUB_PORT_STATUS_RESET) && (portstatus & HUB_PORT_STATUS_ENABLE)) {
  496. if (portchange & HUB_PORT_STATUS_C_RESET) {
  497. ret = usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_RESET);
  498. if (ret < 0) {
  499. USB_LOG_ERR("Failed to clear port %u reset change, errorcode: %d\r\n", port + 1, ret);
  500. continue;
  501. }
  502. }
  503. /*
  504. * Figure out device speed. This is a bit tricky because
  505. * HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
  506. */
  507. if (portstatus & HUB_PORT_STATUS_POWER) {
  508. if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
  509. speed = USB_SPEED_HIGH;
  510. } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
  511. speed = USB_SPEED_LOW;
  512. } else {
  513. speed = USB_SPEED_FULL;
  514. }
  515. } else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
  516. speed = USB_SPEED_SUPER;
  517. } else {
  518. USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
  519. continue;
  520. }
  521. child = &hub->child[port];
  522. /** release child sources first */
  523. usbh_hubport_release(child);
  524. memset(child, 0, sizeof(struct usbh_hubport));
  525. child->parent = hub;
  526. child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
  527. child->connected = true;
  528. child->port = port + 1;
  529. child->speed = speed;
  530. child->bus = hub->bus;
  531. child->mutex = usb_osal_mutex_create();
  532. 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);
  533. if (usbh_enumerate(child) < 0) {
  534. /** release child sources */
  535. usbh_hubport_release(child);
  536. USB_LOG_ERR("Port %u enumerate fail\r\n", child->port);
  537. }
  538. } else {
  539. child = &hub->child[port];
  540. /** release child sources */
  541. usbh_hubport_release(child);
  542. /** some USB 3.0 ip may failed to enable USB 2.0 port for USB 3.0 device */
  543. USB_LOG_WRN("Failed to enable port %u\r\n", port + 1);
  544. continue;
  545. }
  546. } else {
  547. child = &hub->child[port];
  548. /** release child sources */
  549. usbh_hubport_release(child);
  550. }
  551. }
  552. }
  553. /* Start next hub int transfer */
  554. if (!hub->is_roothub && hub->connected) {
  555. usb_osal_timer_start(hub->int_timer);
  556. }
  557. }
  558. static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
  559. {
  560. struct usbh_hub *hub;
  561. int ret = 0;
  562. struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
  563. usb_hc_init(bus);
  564. bus->event_handler(bus->busid, USB_HUB_INDEX_ANY, USB_HUB_PORT_ANY, USB_INTERFACE_ANY, USBH_EVENT_INIT);
  565. while (1) {
  566. ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
  567. if (ret < 0) {
  568. continue;
  569. }
  570. usb_osal_mutex_take(bus->mutex);
  571. usbh_hub_events(hub);
  572. usb_osal_mutex_give(bus->mutex);
  573. }
  574. }
  575. void usbh_hub_thread_wakeup(struct usbh_hub *hub)
  576. {
  577. usb_osal_mq_send(hub->bus->hub_mq, (uintptr_t)hub);
  578. }
  579. int usbh_hub_initialize(struct usbh_bus *bus)
  580. {
  581. char thread_name[32] = { 0 };
  582. struct usbh_hub *hub;
  583. hub = &bus->hcd.roothub;
  584. hub->connected = true;
  585. hub->index = 1;
  586. hub->is_roothub = true;
  587. hub->parent = NULL;
  588. hub->hub_addr = 1;
  589. hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
  590. hub->int_buffer = bus->hcd.roothub_intbuf;
  591. hub->bus = bus;
  592. bus->hub_mq = usb_osal_mq_create(7);
  593. if (bus->hub_mq == NULL) {
  594. USB_LOG_ERR("Failed to create hub mq\r\n");
  595. return -1;
  596. }
  597. bus->mutex = usb_osal_mutex_create();
  598. if (bus->mutex == NULL) {
  599. USB_LOG_ERR("Failed to create bus mutex\r\n");
  600. return -1;
  601. }
  602. snprintf(thread_name, 32, "usbh_hub%u", bus->busid);
  603. bus->hub_thread = usb_osal_thread_create(thread_name, CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, bus);
  604. if (bus->hub_thread == NULL) {
  605. USB_LOG_ERR("Failed to create hub thread\r\n");
  606. return -1;
  607. }
  608. return 0;
  609. }
  610. int usbh_hub_deinitialize(struct usbh_bus *bus)
  611. {
  612. struct usbh_hubport *hport;
  613. struct usbh_hub *hub;
  614. usb_osal_mutex_take(bus->mutex);
  615. hub = &bus->hcd.roothub;
  616. for (uint8_t port = 0; port < hub->nports; port++) {
  617. hport = &hub->child[port];
  618. usbh_hubport_release(hport);
  619. }
  620. usb_hc_deinit(bus);
  621. usb_osal_thread_delete(bus->hub_thread);
  622. usb_osal_mq_delete(bus->hub_mq);
  623. usb_osal_mutex_give(bus->mutex);
  624. usb_osal_mutex_delete(bus->mutex);
  625. return 0;
  626. }
  627. #if CONFIG_USBHOST_MAX_EXTHUBS > 0
  628. const struct usbh_class_driver hub_class_driver = {
  629. .driver_name = "hub",
  630. .connect = usbh_hub_connect,
  631. .disconnect = usbh_hub_disconnect
  632. };
  633. CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
  634. .match_flags = USB_CLASS_MATCH_INTF_CLASS,
  635. .bInterfaceClass = USB_DEVICE_CLASS_HUB,
  636. .bInterfaceSubClass = 0,
  637. .bInterfaceProtocol = 0,
  638. .id_table = NULL,
  639. .class_driver = &hub_class_driver
  640. };
  641. #endif