usb_ctrl_ep0.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * usb_ctrl_ep0.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. #define EP0_PKT_LEN 64
  30. /* Helpers to manipulate BDs */
  31. /* IN */
  32. static inline uint32_t
  33. usb_ep0_in_peek(void)
  34. {
  35. return usb_ep_regs[0].in.bd[0].csr;
  36. }
  37. static inline void
  38. usb_ep0_in_clear(void)
  39. {
  40. usb_ep_regs[0].in.bd[0].csr = 0;
  41. }
  42. static inline void
  43. usb_ep0_in_queue_data(unsigned int len)
  44. {
  45. usb_ep_regs[0].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(len);
  46. }
  47. static inline void
  48. usb_ep0_in_queue_stall(void)
  49. {
  50. usb_ep_regs[0].in.bd[0].csr = USB_BD_STATE_RDY_STALL;
  51. }
  52. /* OUT */
  53. static inline uint32_t
  54. usb_ep0_out_peek(void)
  55. {
  56. return usb_ep_regs[0].out.bd[0].csr;
  57. }
  58. static inline void
  59. usb_ep0_out_clear(void)
  60. {
  61. usb_ep_regs[0].out.bd[0].csr = 0;
  62. }
  63. static inline void
  64. usb_ep0_out_queue_data(void)
  65. {
  66. usb_ep_regs[0].out.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(EP0_PKT_LEN);
  67. }
  68. static inline void
  69. usb_ep0_out_queue_stall(void)
  70. {
  71. usb_ep_regs[0].out.bd[0].csr = USB_BD_STATE_RDY_STALL;
  72. }
  73. /* SETUP */
  74. static inline uint32_t
  75. usb_ep0_setup_peek(void)
  76. {
  77. return usb_ep_regs[0].out.bd[1].csr;
  78. }
  79. static inline void
  80. usb_ep0_setup_clear(void)
  81. {
  82. usb_ep_regs[0].out.bd[1].csr = 0;
  83. }
  84. static inline void
  85. usb_ep0_setup_queue_data(void)
  86. {
  87. usb_ep_regs[0].out.bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(EP0_PKT_LEN);
  88. }
  89. /* Handle control transfers */
  90. static void
  91. usb_handle_control_data()
  92. {
  93. /* Handle read requests */
  94. if (g_usb.ctrl.state == DATA_IN) {
  95. /* How much left to do ? */
  96. int xflen = g_usb.ctrl.xfer.len - g_usb.ctrl.xfer.ofs;
  97. if (xflen > EP0_PKT_LEN)
  98. xflen = EP0_PKT_LEN;
  99. /* Setup descriptor for output */
  100. if (xflen)
  101. usb_data_write(0, &g_usb.ctrl.xfer.data[g_usb.ctrl.xfer.ofs], xflen);
  102. usb_ep0_in_queue_data(xflen);
  103. /* Move on */
  104. g_usb.ctrl.xfer.ofs += xflen;
  105. /* If we're done, setup the OUT ack */
  106. if (xflen < EP0_PKT_LEN) {
  107. usb_ep0_out_queue_data();
  108. g_usb.ctrl.state = STATUS_DONE_OUT;
  109. }
  110. }
  111. /* Handle write requests */
  112. if (g_usb.ctrl.state == DATA_OUT) {
  113. /* Read off any data we got */
  114. uint32_t bds_out = usb_ep0_out_peek();
  115. if ((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK)
  116. {
  117. /* Read data from USB buffer */
  118. int xflen = (bds_out & USB_BD_LEN_MSK) - 2;
  119. usb_data_read(&g_usb.ctrl.xfer.data[g_usb.ctrl.xfer.ofs], 0, xflen);
  120. /* Move on */
  121. g_usb.ctrl.xfer.ofs += xflen;
  122. /* Done with that buffer */
  123. usb_ep0_out_clear();
  124. }
  125. /* Next ? */
  126. if (g_usb.ctrl.xfer.ofs == g_usb.ctrl.xfer.len)
  127. {
  128. /* Done, ACK with a ZLP */
  129. usb_ep0_in_queue_data(0);
  130. g_usb.ctrl.state = STATUS_DONE_IN;
  131. }
  132. else if ((bds_out & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
  133. {
  134. /* Submit next BD to fill */
  135. usb_ep0_out_queue_data();
  136. }
  137. }
  138. }
  139. static void
  140. usb_handle_control_request(struct usb_ctrl_req *req)
  141. {
  142. enum usb_fnd_resp rv = USB_FND_CONTINUE;
  143. /* Defaults */
  144. g_usb.ctrl.xfer.data = g_usb.ctrl.buf;
  145. g_usb.ctrl.xfer.len = sizeof(g_usb.ctrl.buf);
  146. g_usb.ctrl.xfer.ofs = 0;
  147. g_usb.ctrl.xfer.cb_data = NULL;
  148. g_usb.ctrl.xfer.cb_done = NULL;
  149. g_usb.ctrl.xfer.cb_ctx = NULL;
  150. /* Dipatch to all handlers */
  151. rv = usb_dispatch_ctrl_req(req, &g_usb.ctrl.xfer);
  152. /* If the request isn't handled, answer with STALL */
  153. if (rv != USB_FND_SUCCESS)
  154. goto error;
  155. /* Buffer size vs request size checks */
  156. if (req->wLength > g_usb.ctrl.xfer.len) {
  157. if (!USB_REQ_IS_READ(req)) {
  158. /* If this is a OUT treansaction and no suitable buffer was
  159. * provided, there isn't much we can do ... */
  160. USB_LOG_ERR("[!] Control request handler failed to provide enough buffer space");
  161. goto error;
  162. }
  163. } else {
  164. g_usb.ctrl.xfer.len = req->wLength;
  165. }
  166. /* Handle the 'data' stage now */
  167. g_usb.ctrl.state = USB_REQ_IS_READ(req) ? DATA_IN : DATA_OUT;
  168. usb_handle_control_data();
  169. return;
  170. /* Error path */
  171. error:
  172. g_usb.ctrl.state = STALL;
  173. usb_ep0_in_queue_stall();
  174. usb_ep0_out_queue_stall();
  175. return;
  176. }
  177. /* Internally exposed "API" */
  178. void
  179. usb_ep0_reset(void)
  180. {
  181. /* Reset internal state */
  182. g_usb.ctrl.state = IDLE;
  183. /* Configure EP0 */
  184. usb_ep_regs[0].out.status = USB_EP_TYPE_CTRL | USB_EP_BD_CTRL; /* Type=Control, control mode buffered */
  185. usb_ep_regs[0].in.status = USB_EP_TYPE_CTRL | USB_EP_DT_BIT; /* Type=Control, single buffered, DT=1 */
  186. /* Setup the BD pointers */
  187. usb_ep_regs[0].in.bd[0].ptr = 0;
  188. usb_ep_regs[0].out.bd[0].ptr = 0;
  189. usb_ep_regs[0].out.bd[1].ptr = EP0_PKT_LEN;
  190. /* Clear BD for IN/OUT */
  191. usb_ep0_in_clear();
  192. usb_ep0_out_clear();
  193. /* Queue one buffer for SETUP */
  194. usb_ep0_setup_queue_data();
  195. }
  196. void
  197. usb_ep0_poll(void)
  198. {
  199. uint32_t bds_setup, bds_out, bds_in;
  200. bool acted;
  201. do {
  202. /* Not done anything yet */
  203. acted = false;
  204. /* Grab current EP status */
  205. bds_setup = usb_ep0_setup_peek();
  206. bds_out = usb_ep0_out_peek();
  207. bds_in = usb_ep0_in_peek();
  208. /* Check for status IN stage finishing */
  209. if (g_usb.ctrl.state == STATUS_DONE_IN) {
  210. if ((bds_in & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
  211. /* Return to IDLE */
  212. g_usb.ctrl.state = IDLE;
  213. usb_ep0_in_clear();
  214. /* Completion Callback */
  215. if (g_usb.ctrl.xfer.cb_done)
  216. g_usb.ctrl.xfer.cb_done(&g_usb.ctrl.xfer);
  217. /* Next event */
  218. acted = true;
  219. }
  220. }
  221. /* Check for status OUT stage finishing */
  222. else if (g_usb.ctrl.state == STATUS_DONE_OUT) {
  223. if ((bds_in & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
  224. /* Done with the last IN BD of this transfer */
  225. usb_ep0_in_clear();
  226. /* Next event */
  227. acted = true;
  228. }
  229. if ((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
  230. /* Sanity check */
  231. if ((bds_out & USB_BD_LEN_MSK) != 2)
  232. USB_LOG_ERR("[!] Got a non ZLP as a status stage packet ?!?\n");
  233. /* Return to IDLE */
  234. g_usb.ctrl.state = IDLE;
  235. usb_ep0_out_clear();
  236. /* Completion Callback */
  237. if (g_usb.ctrl.xfer.cb_done)
  238. g_usb.ctrl.xfer.cb_done(&g_usb.ctrl.xfer);
  239. /* Next event */
  240. acted = true;
  241. }
  242. }
  243. /* Check for STALL needing a refresh */
  244. else if (g_usb.ctrl.state == STALL) {
  245. if ((bds_in & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_STALL) {
  246. usb_ep0_in_queue_stall();
  247. acted = true;
  248. }
  249. if ((bds_out & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_STALL) {
  250. usb_ep0_out_queue_stall();
  251. acted = true;
  252. }
  253. }
  254. /* If any of the above was acted upon, we need a refresh */
  255. if (acted)
  256. continue;
  257. /* Retry any RX error on both setup and data buffers */
  258. if ((bds_setup & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
  259. USB_LOG_ERR("[!] Retry SETUP error\n");
  260. usb_ep0_setup_queue_data();
  261. acted = true;
  262. continue;
  263. }
  264. if ((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
  265. USB_LOG_ERR("[!] Retry OUT error\n");
  266. usb_ep0_out_queue_data();
  267. acted = true;
  268. continue;
  269. }
  270. /* Check for SETUP */
  271. if ((bds_setup & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
  272. /* Really setup ? */
  273. if (!(bds_setup & USB_BD_IS_SETUP)) {
  274. USB_LOG_ERR("[!] Got non-SETUP in the SETUP BD !?!\n");
  275. }
  276. /* Were we waiting for this ? */
  277. if ((g_usb.ctrl.state != IDLE) && (g_usb.ctrl.state != STALL)) {
  278. USB_LOG_ERR("[!] Got SETUP while busy !??\n");
  279. }
  280. /* Clear descriptors */
  281. usb_ep0_out_clear();
  282. usb_ep0_in_clear();
  283. /* Make sure DT=1 for IN endpoint after a SETUP */
  284. usb_ep_regs[0].in.status = USB_EP_TYPE_CTRL | USB_EP_DT_BIT; /* Type=Control, single buffered, DT=1 */
  285. /* We acked it, need to handle it */
  286. usb_data_read(&g_usb.ctrl.req, EP0_PKT_LEN, sizeof(struct usb_ctrl_req));
  287. usb_handle_control_request(&g_usb.ctrl.req);
  288. /* Release the lockout and allow new SETUP */
  289. usb_regs->ar = USB_AR_CEL_RELEASE;
  290. usb_ep0_setup_queue_data();
  291. return;
  292. }
  293. /* Process data stage */
  294. if (((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK)) {
  295. /* Sanity check */
  296. if (g_usb.ctrl.state != DATA_OUT) {
  297. USB_LOG_ERR("[!] Got unexpected DATA !?!\n");
  298. usb_ep0_out_clear();
  299. } else {
  300. /* Process data */
  301. usb_handle_control_data();
  302. }
  303. /* Next event */
  304. acted = true;
  305. continue;
  306. }
  307. if ((bds_in & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
  308. /* Sanity check */
  309. if (g_usb.ctrl.state != DATA_IN) {
  310. USB_LOG_ERR("[!] Got ack for DATA we didn't send !?!\n");
  311. usb_ep0_in_clear();
  312. } else {
  313. /* Process data */
  314. usb_handle_control_data();
  315. }
  316. /* Next event */
  317. acted = true;
  318. continue;
  319. }
  320. } while (acted);
  321. }