usb_ctrl_std.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /*
  2. * usb_ctrl_std.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. /* Control Request implementation */
  30. static bool
  31. _get_status_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  32. {
  33. xfer->data[0] = 0x00; /* No remote wakeup, bus-powered */
  34. xfer->data[1] = 0x00;
  35. xfer->len = 2;
  36. return true;
  37. }
  38. static bool
  39. _get_status_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  40. {
  41. /* Check interface exits */
  42. if (usb_desc_find_intf(NULL, req->wIndex, 0, NULL))
  43. return false;
  44. /* Nothing to return really */
  45. xfer->data[0] = 0x00;
  46. xfer->data[1] = 0x00;
  47. xfer->len = 2;
  48. return true;
  49. }
  50. static bool
  51. _get_status_ep(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  52. {
  53. uint8_t ep = req->wIndex;
  54. if (!usb_ep_is_configured(ep))
  55. return false;
  56. xfer->data[0] = usb_ep_is_halted(ep) ? 0x01 : 0x00;
  57. xfer->data[1] = 0x00;
  58. xfer->len = 2;
  59. return true;
  60. }
  61. static bool
  62. _clear_feature_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  63. {
  64. /* No support for any device feature */
  65. return false;
  66. }
  67. static bool
  68. _clear_feature_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  69. {
  70. /* No support for any interface feature */
  71. return false;
  72. }
  73. static bool
  74. _clear_feature_ep(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  75. {
  76. uint8_t ep = req->wIndex;
  77. /* Only support ENDPOINT_HALT feature on non-zero EP that exist
  78. * and only when in CONFIGURED state */
  79. if ((usb_get_state() < USB_DS_CONFIGURED) ||
  80. (req->wValue != 0) || /* ENDPOINT_HALT */
  81. (ep == 0) ||
  82. (!usb_ep_is_configured(ep)))
  83. return false;
  84. /* Resume the EP */
  85. return usb_ep_resume(ep);
  86. }
  87. static bool
  88. _set_feature_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  89. {
  90. /* No support for any device feature */
  91. return false;
  92. }
  93. static bool
  94. _set_feature_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  95. {
  96. /* No support for any interface feature */
  97. return false;
  98. }
  99. static bool
  100. _set_feature_ep(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  101. {
  102. uint8_t ep = req->wIndex;
  103. /* Only support ENDPOINT_HALT feature on non-zero EP that exist
  104. * and only when in CONFIGURED state */
  105. if ((usb_get_state() < USB_DS_CONFIGURED) ||
  106. (req->wValue != 0) || /* ENDPOINT_HALT */
  107. (ep == 0) ||
  108. (!usb_ep_is_configured(ep)))
  109. return false;
  110. /* Halt the EP */
  111. return usb_ep_halt(ep);
  112. }
  113. static bool
  114. _set_addr_done(struct usb_xfer *xfer)
  115. {
  116. struct usb_ctrl_req *req = xfer->cb_ctx;
  117. usb_set_address(req->wValue);
  118. return true;
  119. }
  120. static bool
  121. _set_address(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  122. {
  123. xfer->len = 0;
  124. xfer->cb_done = _set_addr_done;
  125. xfer->cb_ctx = req;
  126. return true;
  127. }
  128. static bool
  129. _get_descriptor(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  130. {
  131. int idx = req->wValue & 0xff;
  132. xfer->data = NULL;
  133. switch (req->wValue & 0xff00)
  134. {
  135. case 0x0100: /* Device */
  136. xfer->data = (void*)g_usb.stack_desc->dev;
  137. xfer->len = g_usb.stack_desc->dev->bLength;
  138. break;
  139. case 0x0200: /* Configuration */
  140. if (idx < g_usb.stack_desc->n_conf) {
  141. xfer->data = (void*)g_usb.stack_desc->conf[idx];
  142. xfer->len = g_usb.stack_desc->conf[idx]->wTotalLength;
  143. }
  144. break;
  145. case 0x0300: /* String */
  146. if (idx < g_usb.stack_desc->n_str) {
  147. xfer->data = (void*)g_usb.stack_desc->str[idx];
  148. xfer->len = g_usb.stack_desc->str[idx]->bLength;
  149. }
  150. break;
  151. }
  152. return xfer->data != NULL;
  153. }
  154. static bool
  155. _get_configuration(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  156. {
  157. xfer->data[0] = g_usb.conf ? g_usb.conf->bConfigurationValue : 0;
  158. xfer->len = 1;
  159. return true;
  160. }
  161. static bool
  162. _set_configuration(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  163. {
  164. const struct usb_conf_desc *conf = NULL;
  165. enum usb_dev_state new_state;
  166. /* Handle the 'zero' case first */
  167. if (req->wValue == 0) {
  168. new_state = USB_DS_DEFAULT;
  169. } else {
  170. /* Find the requested config */
  171. for (int i=0; i<g_usb.stack_desc->n_conf; i++)
  172. if (g_usb.stack_desc->conf[i]->bConfigurationValue == req->wValue) {
  173. conf = g_usb.stack_desc->conf[i];
  174. break;
  175. }
  176. if (!conf)
  177. return false;
  178. new_state = USB_DS_CONFIGURED;
  179. }
  180. /* Update state */
  181. /* FIXME: configure all endpoint */
  182. g_usb.conf = conf;
  183. g_usb.intf_alt = 0;
  184. usb_set_state(new_state);
  185. usb_dispatch_set_conf(g_usb.conf);
  186. return true;
  187. }
  188. static bool
  189. _get_interface(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  190. {
  191. const struct usb_intf_desc *intf;
  192. uint8_t idx = req->wIndex;
  193. uint8_t alt = req->wValue;
  194. enum usb_fnd_resp rv;
  195. /* Check interface exits */
  196. if (usb_desc_find_intf(NULL, idx, 0, NULL))
  197. if (intf == NULL)
  198. return false;
  199. /* Fast path */
  200. if (!(g_usb.intf_alt & (1 << idx))) {
  201. xfer->data[0] = 0x00;
  202. xfer->len = 1;
  203. return true;
  204. }
  205. /* Dispatch for an answer */
  206. rv = usb_dispatch_get_intf(intf, &alt);
  207. if (rv != USB_FND_SUCCESS)
  208. return false;
  209. /* Setup response */
  210. xfer->data[0] = alt;
  211. xfer->len = 1;
  212. return true;
  213. }
  214. static bool
  215. _set_interface(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  216. {
  217. const struct usb_intf_desc *intf_base, *intf_alt;
  218. uint8_t idx = req->wIndex;
  219. uint8_t alt = req->wValue;
  220. enum usb_fnd_resp rv;
  221. /* Check interface exits and its altsettings */
  222. intf_alt = usb_desc_find_intf(NULL, req->wIndex, alt, &intf_base);
  223. if (intf_alt == NULL)
  224. return false;
  225. /* Disable fast path */
  226. g_usb.intf_alt |= (1 << idx);
  227. /* Dispatch enable */
  228. rv = usb_dispatch_set_intf(intf_base, intf_alt);
  229. if (rv != USB_FND_SUCCESS)
  230. return false;
  231. return true;
  232. }
  233. /* Control Request dispatch */
  234. static enum usb_fnd_resp
  235. usb_ctrl_std_handle(struct usb_ctrl_req *req, struct usb_xfer *xfer)
  236. {
  237. bool rv = false;
  238. /* Main dispatch */
  239. switch (req->wRequestAndType)
  240. {
  241. case USB_RT_GET_STATUS_DEV:
  242. rv = _get_status_dev(req, xfer);
  243. break;
  244. case USB_RT_GET_STATUS_INTF:
  245. rv = _get_status_intf(req, xfer);
  246. break;
  247. case USB_RT_GET_STATUS_EP:
  248. rv = _get_status_ep(req, xfer);
  249. break;
  250. case USB_RT_CLEAR_FEATURE_DEV:
  251. rv = _clear_feature_dev(req, xfer);
  252. break;
  253. case USB_RT_CLEAR_FEATURE_INTF:
  254. rv = _clear_feature_intf(req, xfer);
  255. break;
  256. case USB_RT_CLEAR_FEATURE_EP:
  257. rv = _clear_feature_ep(req, xfer);
  258. break;
  259. case USB_RT_SET_FEATURE_DEV:
  260. rv = _set_feature_dev(req, xfer);
  261. break;
  262. case USB_RT_SET_FEATURE_INTF:
  263. rv = _set_feature_intf(req, xfer);
  264. break;
  265. case USB_RT_SET_FEATURE_EP:
  266. rv = _set_feature_ep(req, xfer);
  267. break;
  268. case USB_RT_SET_ADDRESS:
  269. rv = _set_address(req, xfer);
  270. break;
  271. case USB_RT_GET_DESCRIPTOR:
  272. rv = _get_descriptor(req, xfer);
  273. break;
  274. case USB_RT_GET_CONFIGURATION:
  275. rv = _get_configuration(req, xfer);
  276. break;
  277. case USB_RT_SET_CONFIGURATION:
  278. rv = _set_configuration(req, xfer);
  279. break;
  280. case USB_RT_GET_INTERFACE:
  281. rv = _get_interface(req, xfer);
  282. break;
  283. case USB_RT_SET_INTERFACE:
  284. rv = _set_interface(req, xfer);
  285. break;
  286. default:
  287. return USB_FND_CONTINUE;
  288. }
  289. return rv ? USB_FND_SUCCESS : USB_FND_ERROR;
  290. }
  291. struct usb_fn_drv usb_ctrl_std_drv = {
  292. .ctrl_req = usb_ctrl_std_handle,
  293. };