usbd_core.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /* This file is the part of the LUS32 project
  2. *
  3. * Copyright ©2016 Dmitry Filimonchuk <dmitrystu[at]gmail[dot]com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stdint.h>
  16. #include <stdbool.h>
  17. #include <string.h>
  18. #include "../usb.h"
  19. #define _MIN(a, b) ((a) < (b)) ? (a) : (b)
  20. static void usbd_process_ep0 (usbd_device *dev, uint8_t event, uint8_t ep);
  21. /** \brief Resets USB device state
  22. * \param dev pointer to usb device
  23. * \return none
  24. */
  25. static void usbd_process_reset(usbd_device *dev) {
  26. dev->status.device_state = usbd_state_default;
  27. dev->status.control_state = usbd_ctl_idle;
  28. dev->status.device_cfg = 0;
  29. dev->driver->ep_config(0, USB_EPTYPE_CONTROL, dev->status.ep0size);
  30. dev->endpoint[0] = usbd_process_ep0;
  31. dev->driver->setaddr(0);
  32. }
  33. /** \brief Callback that sets USB device address
  34. * \param dev pointer to usb device
  35. * \param req pointer to usb control request data
  36. * \return none
  37. */
  38. static void usbd_set_address (usbd_device *dev, usbd_ctlreq *req) {
  39. dev->driver->setaddr(req->wValue);
  40. dev->status.device_state = (req->wValue) ? usbd_state_addressed : usbd_state_default;
  41. }
  42. /** \brief Callback processing after STATUS-IN or STATUS-OUT stage completed
  43. * \param dev pointer to the usb device
  44. * \return none
  45. */
  46. static void usbd_process_callback (usbd_device *dev) {
  47. if (dev->complete_callback) {
  48. dev->complete_callback(dev, dev->status.data_buf);
  49. dev->complete_callback = 0;
  50. }
  51. }
  52. static usbd_respond usbd_configure(usbd_device *dev, uint8_t config) {
  53. usbd_respond resp = usbd_fail;
  54. if (dev->config_callback) {
  55. resp = dev->config_callback(dev, config);
  56. }
  57. if (config == 0 && resp == usbd_ack) {
  58. dev->status.device_state = usbd_state_addressed;
  59. }
  60. return resp;
  61. }
  62. /** \brief Processing standard device control request
  63. * \param dev pointer to usb device
  64. * \param req pointer to control request
  65. * \return TRUE if request is handled
  66. */
  67. static usbd_respond usbd_process_devrq (usbd_device *dev, usbd_ctlreq *req) {
  68. switch (req->bRequest) {
  69. case USB_STD_CLEAR_FEATURE:
  70. /* not yet supported */
  71. break;
  72. case USB_STD_GET_CONFIG:
  73. req->data[0] = dev->status.device_cfg;
  74. return usbd_ack;
  75. case USB_STD_GET_DESCRIPTOR:
  76. if (req->wValue == ((USB_DTYPE_STRING << 8) | INTSERIALNO_DESCRIPTOR )) {
  77. dev->status.data_count = dev->driver->get_serialno_desc(req->data);
  78. return usbd_ack;
  79. } else {
  80. if (dev->descriptor_callback) {
  81. return dev->descriptor_callback(req, &(dev->status.data_ptr), &(dev->status.data_count));
  82. }
  83. }
  84. break;
  85. case USB_STD_GET_STATUS:
  86. req->data[0] = 0;
  87. req->data[1] = 0;
  88. return usbd_ack;
  89. case USB_STD_SET_ADDRESS:
  90. dev->complete_callback = usbd_set_address;
  91. return usbd_ack;
  92. case USB_STD_SET_CONFIG:
  93. return usbd_configure(dev, req->wValue);
  94. case USB_STD_SET_DESCRIPTOR:
  95. /* should be externally handled */
  96. break;
  97. case USB_STD_SET_FEATURE:
  98. /* not yet supported */
  99. break;
  100. default:
  101. break;
  102. }
  103. return usbd_fail;
  104. }
  105. /** \brief Processing standard interface control request
  106. * \param dev pointer to usb device
  107. * \param req pointer to control request
  108. * \return TRUE if request is handled
  109. */
  110. static usbd_respond usbd_process_intrq(usbd_device *dev, usbd_ctlreq *req) {
  111. (void)dev;
  112. switch (req->bRequest) {
  113. case USB_STD_GET_STATUS:
  114. req->data[0] = 0;
  115. req->data[1] = 0;
  116. return usbd_ack;
  117. default:
  118. break;
  119. }
  120. return usbd_fail;
  121. }
  122. /** \brief Processing standard endpoint control request
  123. * \param dev pointer to usb device
  124. * \param req pointer to control request
  125. * \return TRUE if request is handled
  126. */
  127. static usbd_respond usbd_process_eptrq(usbd_device *dev, usbd_ctlreq *req) {
  128. switch (req->bRequest) {
  129. case USB_STD_SET_FEATURE:
  130. dev->driver->ep_setstall(req->wIndex, 1);
  131. return usbd_ack;
  132. case USB_STD_CLEAR_FEATURE:
  133. dev->driver->ep_setstall(req->wIndex, 0);
  134. return usbd_ack;
  135. case USB_STD_GET_STATUS:
  136. req->data[0] = dev->driver->ep_isstalled(req->wIndex) ? 1 : 0;
  137. req->data[1] = 0;
  138. return usbd_ack;
  139. default:
  140. break;
  141. }
  142. return usbd_fail;
  143. }
  144. /** \brief Processing control request
  145. * \param dev pointer to usb device
  146. * \param req pointer to usb control request
  147. * \return TRUE if request is handled
  148. */
  149. static usbd_respond usbd_process_request(usbd_device *dev, usbd_ctlreq *req) {
  150. /* processing control request by callback */
  151. if (dev->control_callback) {
  152. usbd_respond r = dev->control_callback(dev, req, &(dev->complete_callback));
  153. if (r != usbd_fail) return r;
  154. }
  155. /* continuing standard USB requests */
  156. switch (req->bmRequestType & (USB_REQ_TYPE | USB_REQ_RECIPIENT)) {
  157. case USB_REQ_STANDARD | USB_REQ_DEVICE:
  158. return usbd_process_devrq(dev, req);
  159. case USB_REQ_STANDARD | USB_REQ_INTERFACE:
  160. return usbd_process_intrq(dev, req);
  161. case USB_REQ_STANDARD | USB_REQ_ENDPOINT:
  162. return usbd_process_eptrq(dev, req);
  163. default:
  164. break;
  165. }
  166. return usbd_fail;
  167. }
  168. /** \brief Control endpoint stall (STALL PID)
  169. * \param dev pointer to usb device
  170. * \param ep endpoint number
  171. */
  172. static void usbd_stall_pid(usbd_device *dev, uint8_t ep) {
  173. dev->driver->ep_setstall(ep & 0x7F, 1);
  174. dev->driver->ep_setstall(ep | 0x80, 1);
  175. dev->status.control_state = usbd_ctl_idle;
  176. }
  177. /** \brief Control endpoint TX event processing
  178. * \param dev pointer to usb device
  179. * \param ep endpoint number
  180. */
  181. static void usbd_process_eptx(usbd_device *dev, uint8_t ep) {
  182. uint16_t _t;
  183. switch (dev->status.control_state) {
  184. case usbd_ctl_ztxdata:
  185. case usbd_ctl_txdata:
  186. _t = _MIN(dev->status.data_count, dev->status.ep0size);
  187. dev->driver->ep_write(ep, dev->status.data_ptr, _t);
  188. dev->status.data_ptr += _t;
  189. dev->status.data_count -= _t;
  190. /* if all data is not sent */
  191. if (0 != dev->status.data_count) break;
  192. /* if last packet has a EP0 size and host awaiting for the more data ZLP should be sent*/
  193. /* if ZLP required, control state will be unchanged, therefore next TX event sends ZLP */
  194. if ( usbd_ctl_txdata == dev->status.control_state || _t != dev->status.ep0size ) {
  195. dev->status.control_state = usbd_ctl_lastdata; /* no ZLP required */
  196. }
  197. break;
  198. case usbd_ctl_lastdata:
  199. dev->status.control_state = usbd_ctl_statusout;
  200. break;
  201. case usbd_ctl_statusin:
  202. dev->status.control_state = usbd_ctl_idle;
  203. return usbd_process_callback(dev);
  204. default:
  205. /* unexpected TX completion */
  206. /* just skipping it */
  207. break;
  208. }
  209. }
  210. /** \brief Control endpoint RX event processing
  211. * \param dev pointer to usb device
  212. * \param ep endpoint number
  213. */
  214. static void usbd_process_eprx(usbd_device *dev, uint8_t ep) {
  215. uint16_t _t;
  216. usbd_ctlreq *const req = dev->status.data_buf;
  217. switch (dev->status.control_state) {
  218. case usbd_ctl_idle:
  219. /* read SETUP packet, send STALL_PID if incorrect packet length */
  220. if (0x08 != dev->driver->ep_read(ep, req, dev->status.data_maxsize)) {
  221. return usbd_stall_pid(dev, ep);
  222. }
  223. dev->status.data_ptr = req->data;
  224. dev->status.data_count = req->wLength;
  225. /* processing request with no payload data*/
  226. if ((req->bmRequestType & USB_REQ_DEVTOHOST) || (0 == req->wLength)) goto do_process_request;
  227. /* checking available memory for DATA OUT stage */
  228. if (req->wLength > dev->status.data_maxsize) {
  229. return usbd_stall_pid(dev, ep);
  230. }
  231. /* continue DATA OUT stage */
  232. dev->status.control_state = usbd_ctl_rxdata;
  233. break;
  234. case usbd_ctl_rxdata:
  235. /*receive DATA OUT packet(s) */
  236. _t = dev->driver->ep_read(ep, dev->status.data_ptr, dev->status.data_count);
  237. if (dev->status.data_count < _t) {
  238. /* if received packet is large than expected */
  239. /* Must be error. Let's drop this request */
  240. return usbd_stall_pid(dev, ep);
  241. } else if (dev->status.data_count != _t) {
  242. /* if all data payload was not received yet */
  243. dev->status.data_count -= _t;
  244. dev->status.data_ptr += _t;
  245. break;
  246. }
  247. do_process_request:
  248. /* usb request received */
  249. /* let's handle it */
  250. /* preparing */
  251. dev->status.data_ptr = req->data;
  252. dev->status.data_count = req->wLength;/*dev->status.data_maxsize;*/
  253. switch (usbd_process_request(dev, req)){
  254. case usbd_ack:
  255. if (req->bmRequestType & USB_REQ_DEVTOHOST) {
  256. /* return data from function */
  257. if (dev->status.data_count >= req->wLength) {
  258. dev->status.data_count = req->wLength;
  259. dev->status.control_state = usbd_ctl_txdata;
  260. } else {
  261. /* DATA IN packet smaller than requested */
  262. /* ZLP maybe wanted */
  263. dev->status.control_state = usbd_ctl_ztxdata;
  264. }
  265. return usbd_process_eptx(dev, ep | 0x80);
  266. } else {
  267. /* confirming by ZLP in STATUS_IN stage */
  268. dev->driver->ep_write(ep | 0x80, 0, 0);
  269. dev->status.control_state = usbd_ctl_statusin;
  270. }
  271. break;
  272. case usbd_nak:
  273. dev->status.control_state = usbd_ctl_statusin;
  274. break;
  275. default:
  276. return usbd_stall_pid(dev, ep);
  277. }
  278. break;
  279. case usbd_ctl_statusout:
  280. /* reading STATUS OUT data to buffer */
  281. dev->driver->ep_read(ep, dev->status.data_ptr, dev->status.data_maxsize);
  282. dev->status.control_state = usbd_ctl_idle;
  283. return usbd_process_callback(dev);
  284. default:
  285. /* unexpected RX packet */
  286. return usbd_stall_pid(dev, ep);
  287. }
  288. }
  289. /** \brief Control endpoint 0 event processing callback
  290. * \param dev usb device
  291. * \param event endpoint event
  292. */
  293. static void usbd_process_ep0 (usbd_device *dev, uint8_t event, uint8_t ep) {
  294. switch (event) {
  295. case usbd_evt_epsetup:
  296. /* force switch to setup state */
  297. dev->status.control_state = usbd_ctl_idle;
  298. dev->complete_callback = 0;
  299. case usbd_evt_eprx:
  300. return usbd_process_eprx(dev, ep);
  301. case usbd_evt_eptx:
  302. return usbd_process_eptx(dev, ep);
  303. default:
  304. break;
  305. }
  306. }
  307. /** \brief General event processing callback
  308. * \param dev usb device
  309. * \param evt usb event
  310. * \param ep active endpoint
  311. */
  312. static void usbd_process_evt(usbd_device *dev, uint8_t evt, uint8_t ep) {
  313. switch (evt) {
  314. case usbd_evt_reset:
  315. usbd_process_reset(dev);
  316. break;
  317. case usbd_evt_eprx:
  318. case usbd_evt_eptx:
  319. case usbd_evt_epsetup:
  320. if (dev->endpoint[ep & 0x07]) dev->endpoint[ep & 0x07](dev, evt, ep);
  321. break;
  322. default:
  323. break;
  324. }
  325. if (dev->events[evt]) dev->events[evt](dev, evt, ep);
  326. }
  327. void usbd_poll(usbd_device *dev) {
  328. return dev->driver->poll(dev, usbd_process_evt);
  329. }
  330. void usbd_control(usbd_device *dev, enum usbd_commands cmd) {
  331. switch (cmd) {
  332. case usbd_cmd_enable:
  333. dev->driver->enable(true);
  334. dev->status.device_state = usbd_state_disconnected;
  335. break;
  336. case usbd_cmd_disable:
  337. dev->driver->enable(false);
  338. dev->status.device_state = usbd_state_disabled;
  339. break;
  340. case usbd_cmd_connect:
  341. dev->driver->connect(true);
  342. break;
  343. case usbd_cmd_disconnect:
  344. dev->driver->connect(false);
  345. dev->status.device_state = usbd_state_disconnected;
  346. break;
  347. case usbd_cmd_reset:
  348. dev->driver->reset();
  349. break;
  350. default:
  351. break;
  352. }
  353. }