usb.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * usb.c
  3. *
  4. * Copyright (C) 2019 Sylvain Munaut
  5. * All rights reserved.
  6. *
  7. * LGPL v3+, see LICENSE.lgpl3
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 3 of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with this program; if not, write to the Free Software Foundation,
  21. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22. */
  23. #include <stdint.h>
  24. #include <stdbool.h>
  25. #include <string.h>
  26. #include "console.h"
  27. #include "usb_hw.h"
  28. #include "usb_priv.h"
  29. #include "usb.h"
  30. /* Main stack state */
  31. struct usb_stack g_usb;
  32. /* Helpers */
  33. /* ------- */
  34. /* Data buffer access */
  35. void
  36. usb_data_write(unsigned int dst_ofs, const void *src, int len)
  37. {
  38. /* FIXME unaligned ofs */
  39. const uint32_t *src_u32 = src;
  40. volatile uint32_t *dst_u32 = (volatile uint32_t *)((USB_DATA_BASE) + dst_ofs);
  41. len = (len + 3) >> 2;
  42. while (len--)
  43. *dst_u32++ = *src_u32++;
  44. }
  45. void
  46. usb_data_read (void *dst, unsigned int src_ofs, int len)
  47. {
  48. /* FIXME unaligned ofs */
  49. volatile uint32_t *src_u32 = (volatile uint32_t *)((USB_DATA_BASE) + src_ofs);
  50. uint32_t *dst_u32 = dst;
  51. int i = len >> 2;
  52. while (i--)
  53. *dst_u32++ = *src_u32++;
  54. if ((len &= 3) != 0) {
  55. uint32_t x = *src_u32;
  56. uint8_t *dst_u8 = (uint8_t *)dst_u32;
  57. while (len--) {
  58. *dst_u8++ = x & 0xff;
  59. x >>= 8;
  60. }
  61. }
  62. }
  63. /* Descriptors */
  64. const void *
  65. usb_desc_find(const void *sod, const void *eod, uint8_t dt)
  66. {
  67. const uint8_t *sod_p = sod, *eod_p = eod;
  68. while ((eod_p - sod_p) >= 2) {
  69. if (sod_p[1] == dt)
  70. return sod_p;
  71. sod_p += sod_p[0];
  72. }
  73. return NULL;
  74. }
  75. const void *
  76. usb_desc_next(const void *sod)
  77. {
  78. const uint8_t *sod_p = sod;
  79. return sod_p + sod_p[0];
  80. }
  81. const struct usb_conf_desc *
  82. usb_desc_find_conf(uint8_t cfg_value)
  83. {
  84. for (int i=0; i<g_usb.stack_desc->n_conf; i++)
  85. if (g_usb.stack_desc->conf[i]->bConfigurationValue == cfg_value)
  86. return g_usb.stack_desc->conf[i];
  87. return NULL;
  88. }
  89. const struct usb_intf_desc *
  90. usb_desc_find_intf(const struct usb_conf_desc *conf, uint8_t idx, uint8_t alt,
  91. const struct usb_intf_desc **alt0)
  92. {
  93. const struct usb_intf_desc *intf = NULL;
  94. const void *sod, *eod;
  95. /* Config select */
  96. if (!conf)
  97. conf = g_usb.conf;
  98. if (!conf)
  99. return NULL;
  100. /* Bound the search */
  101. sod = conf;
  102. eod = sod + conf->wTotalLength;
  103. while (1) {
  104. sod = usb_desc_find(sod, eod, USB_DT_INTF);
  105. if (!sod)
  106. break;
  107. intf = (void*)sod;
  108. if (intf->bInterfaceNumber == idx) {
  109. if (alt0 && !intf->bAlternateSetting)
  110. *alt0 = intf;
  111. if (intf->bAlternateSetting == alt)
  112. return intf;
  113. }
  114. sod = usb_desc_next(sod);
  115. }
  116. return NULL;
  117. }
  118. /* Callback dispatching */
  119. void
  120. usb_dispatch_sof(void)
  121. {
  122. struct usb_fn_drv *p = g_usb.fnd;
  123. while (p) {
  124. if (p->sof)
  125. p->sof();
  126. p = p->next;
  127. }
  128. }
  129. void
  130. usb_dipatch_bus_reset(void)
  131. {
  132. struct usb_fn_drv *p = g_usb.fnd;
  133. while (p) {
  134. if (p->bus_reset)
  135. p->bus_reset();
  136. p = p->next;
  137. }
  138. }
  139. void
  140. usb_dispatch_state_chg(enum usb_dev_state state)
  141. {
  142. struct usb_fn_drv *p = g_usb.fnd;
  143. while (p) {
  144. if (p->state_chg)
  145. p->state_chg(state);
  146. p = p->next;
  147. }
  148. }
  149. enum usb_fnd_resp
  150. usb_dispatch_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  151. {
  152. struct usb_fn_drv *p = g_usb.fnd;
  153. enum usb_fnd_resp rv = USB_FND_CONTINUE;
  154. while (p) {
  155. if (p->ctrl_req) {
  156. rv = p->ctrl_req(req, xfer);
  157. if (rv != USB_FND_CONTINUE)
  158. return rv;
  159. }
  160. p = p->next;
  161. }
  162. return rv;
  163. }
  164. enum usb_fnd_resp
  165. usb_dispatch_set_conf(const struct usb_conf_desc *desc)
  166. {
  167. struct usb_fn_drv *p = g_usb.fnd;
  168. enum usb_fnd_resp rv = USB_FND_SUCCESS;
  169. while (p) {
  170. if (p->set_conf) {
  171. if (p->set_conf(desc) == USB_FND_ERROR)
  172. rv = USB_FND_ERROR;
  173. }
  174. p = p->next;
  175. }
  176. return rv;
  177. }
  178. enum usb_fnd_resp
  179. usb_dispatch_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
  180. {
  181. struct usb_fn_drv *p = g_usb.fnd;
  182. enum usb_fnd_resp rv = USB_FND_CONTINUE;
  183. while (p) {
  184. if (p->set_intf) {
  185. rv = p->set_intf(base, sel);
  186. if (rv != USB_FND_CONTINUE)
  187. return rv;
  188. }
  189. p = p->next;
  190. }
  191. return rv;
  192. }
  193. enum usb_fnd_resp
  194. usb_dispatch_get_intf(const struct usb_intf_desc *base, uint8_t *sel)
  195. {
  196. struct usb_fn_drv *p = g_usb.fnd;
  197. enum usb_fnd_resp rv = USB_FND_CONTINUE;
  198. while (p) {
  199. if (p->get_intf) {
  200. rv = p->get_intf(base, sel);
  201. if (rv != USB_FND_CONTINUE)
  202. return rv;
  203. }
  204. p = p->next;
  205. }
  206. return rv;
  207. }
  208. /* Debug */
  209. /* ----- */
  210. static void
  211. _fast_print_hex(uint32_t v)
  212. {
  213. const char _hex[] = "0123456789abcdef";
  214. int i;
  215. for (i=0; i<4; i++) {
  216. putchar(_hex[(v & 0xf0) >> 4]);
  217. putchar(_hex[ v & 0x0f ]);
  218. putchar(' ');
  219. v >>= 8;
  220. }
  221. }
  222. void
  223. usb_debug_print_ep(int ep, int dir)
  224. {
  225. volatile struct usb_ep *ep_regs = dir ? &usb_ep_regs[ep].in : &usb_ep_regs[ep].out;
  226. printf("EP%d %s", ep, dir ? "IN" : "OUT");
  227. printf("\tS %04x\n", ep_regs->status);
  228. printf("\tBD0.0 %04x\n", ep_regs->bd[0].csr);
  229. printf("\tBD0.1 %04x\n", ep_regs->bd[0].ptr);
  230. printf("\tBD1.0 %04x\n", ep_regs->bd[1].csr);
  231. printf("\tBD1.1 %04x\n", ep_regs->bd[1].ptr);
  232. printf("\n");
  233. }
  234. void
  235. usb_debug_print_data(int ofs, int len)
  236. {
  237. volatile uint32_t *data = (volatile uint32_t *)((USB_DATA_BASE) + (ofs << 2));
  238. int i;
  239. for (i=0; i<len; i++) {
  240. _fast_print_hex(*data++);
  241. putchar((((i & 3) == 3) | (i == (len-1))) ? '\n' : ' ');
  242. }
  243. puts("\n");
  244. }
  245. void
  246. usb_debug_print(void)
  247. {
  248. printf("Stack:\n");
  249. printf("\tState: %d\n", g_usb.state);
  250. printf("HW:\n");
  251. printf("\tSR : %04x\n", usb_regs->csr);
  252. printf("\tTick : %04x\n", g_usb.tick);
  253. printf("\n");
  254. usb_debug_print_ep(0, 0);
  255. usb_debug_print_ep(0, 1);
  256. printf("Data:\n");
  257. usb_debug_print_data(0, 4);
  258. }
  259. /* Internal API */
  260. /* ------------ */
  261. static void
  262. _usb_hw_reset_ep(volatile struct usb_ep *ep)
  263. {
  264. ep->status = 0;
  265. ep->bd[0].csr = 0;
  266. ep->bd[0].ptr = 0;
  267. ep->bd[1].csr = 0;
  268. ep->bd[1].ptr = 0;
  269. }
  270. static void
  271. _usb_hw_reset(bool pu)
  272. {
  273. /* Clear all descriptors */
  274. for (int i=0; i<16; i++) {
  275. _usb_hw_reset_ep(&usb_ep_regs[i].out);
  276. _usb_hw_reset_ep(&usb_ep_regs[i].in);
  277. }
  278. /* Main control */
  279. usb_regs->csr = (pu ? USB_CSR_PU_ENA : 0) | USB_CSR_CEL_ENA | USB_CSR_ADDR_MATCH | USB_CSR_ADDR(0);
  280. usb_regs->ar = USB_AR_BUS_RST_CLEAR | USB_AR_SOF_CLEAR | USB_AR_CEL_RELEASE;
  281. }
  282. static void
  283. usb_bus_reset(void)
  284. {
  285. /* Reset hw */
  286. _usb_hw_reset(true);
  287. /* Reset EP0 */
  288. usb_ep0_reset();
  289. /* Dispatch event */
  290. usb_dipatch_bus_reset();
  291. /* Set state */
  292. usb_set_state(USB_DS_DEFAULT);
  293. }
  294. /* Exposed API */
  295. /* ----------- */
  296. void
  297. usb_init(const struct usb_stack_descriptors *stack_desc)
  298. {
  299. /* Main state reset */
  300. memset(&g_usb, 0x00, sizeof(g_usb));
  301. /* Stack setup */
  302. g_usb.state = USB_DS_DISCONNECTED;
  303. g_usb.stack_desc = stack_desc;
  304. usb_register_function_driver(&usb_ctrl_std_drv);
  305. /* Reset and enable the core */
  306. _usb_hw_reset(false);
  307. }
  308. void
  309. usb_poll(void)
  310. {
  311. uint32_t csr;
  312. /* Active ? */
  313. if (g_usb.state < USB_DS_CONNECTED)
  314. return;
  315. /* Read CSR */
  316. csr = usb_regs->csr;
  317. /* Check for pending bus reset */
  318. if (csr & USB_CSR_BUS_RST_PENDING) {
  319. if (csr & USB_CSR_BUS_RST)
  320. return;
  321. usb_bus_reset();
  322. }
  323. /* If we've not been reset, only reset is of interest */
  324. if (g_usb.state < USB_DS_DEFAULT)
  325. return;
  326. /* Supspend handling */
  327. if (csr & USB_CSR_BUS_SUSPEND) {
  328. if (!(g_usb.state & USB_DS_SUSPENDED)) {
  329. usb_set_state(USB_DS_SUSPENDED);
  330. }
  331. return;
  332. } else if (g_usb.state & USB_DS_SUSPENDED) {
  333. usb_set_state(USB_DS_RESUME);
  334. }
  335. /* SOF Tick */
  336. if (csr & USB_CSR_SOF_PENDING) {
  337. g_usb.tick++;
  338. usb_regs->ar = USB_AR_SOF_CLEAR;
  339. usb_dispatch_sof();
  340. }
  341. /* Check for activity */
  342. if (!(csr & USB_CSR_EVT_PENDING))
  343. return;
  344. csr = usb_regs->evt;
  345. /* Poll EP0 (control) */
  346. usb_ep0_poll();
  347. }
  348. void
  349. usb_set_state(enum usb_dev_state new_state)
  350. {
  351. /* Handle resume/suspend 'markers' */
  352. if (new_state == USB_DS_RESUME)
  353. new_state = g_usb.state & ~USB_DS_SUSPENDED;
  354. else if (new_state == USB_DS_SUSPENDED)
  355. new_state = g_usb.state | USB_DS_SUSPENDED;
  356. /* If state is new, update */
  357. if (g_usb.state != new_state) {
  358. g_usb.state = new_state;
  359. usb_dispatch_state_chg(usb_get_state());
  360. }
  361. }
  362. enum usb_dev_state
  363. usb_get_state(void)
  364. {
  365. return (g_usb.state & USB_DS_SUSPENDED) ? USB_DS_SUSPENDED : g_usb.state;
  366. }
  367. uint32_t
  368. usb_get_tick(void)
  369. {
  370. return g_usb.tick;
  371. }
  372. void
  373. usb_connect(void)
  374. {
  375. /* Sanity check */
  376. if (g_usb.state != USB_DS_DISCONNECTED)
  377. return;
  378. /* Turn-off pull-up */
  379. usb_regs->csr |= USB_CSR_PU_ENA;
  380. /* Stack update */
  381. usb_set_state(USB_DS_CONNECTED);
  382. }
  383. void
  384. usb_disconnect(void)
  385. {
  386. /* Sanity check */
  387. if (g_usb.state < USB_DS_CONNECTED)
  388. return;
  389. /* Turn-off pull-up */
  390. usb_regs->csr &= ~USB_CSR_PU_ENA;
  391. /* Stack state */
  392. usb_set_state(USB_DS_DISCONNECTED);
  393. }
  394. void
  395. usb_set_address(uint8_t addr)
  396. {
  397. usb_regs->csr = USB_CSR_PU_ENA | USB_CSR_CEL_ENA | USB_CSR_ADDR_MATCH | USB_CSR_ADDR(addr);
  398. }
  399. void
  400. usb_register_function_driver(struct usb_fn_drv *drv)
  401. {
  402. drv->next = g_usb.fnd;
  403. g_usb.fnd = drv;
  404. }
  405. void
  406. usb_unregister_function_driver(struct usb_fn_drv *drv)
  407. {
  408. struct usb_fn_drv **p = &g_usb.fnd;
  409. while (*p) {
  410. if (*p == drv) {
  411. *p = drv->next;
  412. drv->next = NULL;
  413. break;
  414. }
  415. p = &(*p)->next->next;
  416. }
  417. }
  418. static volatile struct usb_ep *
  419. _get_ep_regs(uint8_t ep)
  420. {
  421. return (ep & 0x80) ?
  422. &usb_ep_regs[ep & 0xf].in :
  423. &usb_ep_regs[ep & 0xf].out;
  424. }
  425. bool
  426. usb_ep_is_configured(uint8_t ep)
  427. {
  428. volatile struct usb_ep *epr = _get_ep_regs(ep);
  429. uint32_t s = epr->status;
  430. return USB_EP_TYPE(s) != USB_EP_TYPE_NONE;
  431. }
  432. bool
  433. usb_ep_is_halted(uint8_t ep)
  434. {
  435. volatile struct usb_ep *epr = _get_ep_regs(ep);
  436. uint32_t s = epr->status;
  437. return USB_EP_TYPE_IS_BCI(s) && (s & USB_EP_TYPE_HALTED);
  438. }
  439. bool
  440. usb_ep_halt(uint8_t ep)
  441. {
  442. volatile struct usb_ep *epr = _get_ep_regs(ep);
  443. uint32_t s = epr->status;
  444. if (!USB_EP_TYPE_IS_BCI(s))
  445. return false;
  446. epr->status = s | USB_EP_TYPE_HALTED;
  447. return true;
  448. }
  449. bool
  450. usb_ep_resume(uint8_t ep)
  451. {
  452. volatile struct usb_ep *epr = _get_ep_regs(ep);
  453. uint32_t s = epr->status;
  454. if (!USB_EP_TYPE_IS_BCI(s))
  455. return false;
  456. epr->status = s & ~(USB_EP_TYPE_HALTED | USB_EP_DT_BIT); /* DT bit clear needed by CLEAR_FEATURE */
  457. return true;
  458. }