core.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * File : core.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2011, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2011-12-12 Yi Qiu first version
  13. */
  14. #include <rtthread.h>
  15. #include "usbhost.h"
  16. #include "core.h"
  17. #include "driver.h"
  18. #include "hcd.h"
  19. #include "hub.h"
  20. static struct uinstance uinst[USB_MAX_DEVICE];
  21. /**
  22. * This function will allocate an usb device instance from system.
  23. *
  24. * @param parent the hub instance to which the new allocated device attached.
  25. * @param port the hub port.
  26. *
  27. * @return the allocate instance on successful, or RT_NULL on failure.
  28. */
  29. uinst_t rt_usb_alloc_instance(void)
  30. {
  31. int i;
  32. /* lock scheduler */
  33. rt_enter_critical();
  34. for(i=0; i<USB_MAX_DEVICE; i++)
  35. {
  36. /* to find an idle instance handle */
  37. if(uinst[i].status != UINST_STATUS_IDLE) continue;
  38. /* initialize the usb device instance */
  39. rt_memset(&uinst[i], 0, sizeof(struct uinstance));
  40. uinst[i].status = UINST_STATUS_BUSY;
  41. uinst[i].index = i + 1;
  42. uinst[i].address = 0;
  43. uinst[i].max_packet_size = 0x8;
  44. /* unlock scheduler */
  45. rt_exit_critical();
  46. return &uinst[i];
  47. }
  48. /* unlock scheduler */
  49. rt_exit_critical();
  50. return RT_NULL;
  51. }
  52. /**
  53. * This function will attatch an usb device instance to a host controller,
  54. * and do device enumunation process.
  55. *
  56. * @param hcd the host controller driver.
  57. * @param uinst the usb device instance.
  58. *
  59. * @return the error code, RT_EOK on successfully.
  60. */
  61. rt_err_t rt_usb_attatch_instance(uinst_t uinst)
  62. {
  63. int i = 0;
  64. rt_err_t ret = RT_EOK;
  65. struct uconfig_descriptor cfg_desc;
  66. udev_desc_t dev_desc;
  67. uintf_desc_t intf_desc;
  68. ucd_t drv;
  69. RT_ASSERT(uinst != RT_NULL);
  70. rt_memset(&cfg_desc, 0, sizeof(struct uconfig_descriptor));
  71. dev_desc = &uinst->dev_desc;
  72. /* get device descriptor head */
  73. ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, 8);
  74. if(ret != RT_EOK)
  75. {
  76. rt_kprintf("get device descriptor head failed\n");
  77. return ret;
  78. }
  79. /* set device address */
  80. ret = rt_usb_set_address(uinst);
  81. if(ret != RT_EOK)
  82. {
  83. rt_kprintf("set device address failed\n");
  84. return ret;
  85. }
  86. /* set device max packet size */
  87. uinst->max_packet_size = uinst->dev_desc.bMaxPacketSize0;
  88. RT_DEBUG_LOG(RT_DEBUG_USB, ("get device descriptor length %d\n",
  89. dev_desc->bLength));
  90. /* get full device descriptor again */
  91. ret = rt_usb_get_descriptor
  92. (uinst, USB_DESC_TYPE_DEVICE, (void*)dev_desc, dev_desc->bLength);
  93. if(ret != RT_EOK)
  94. {
  95. rt_kprintf("get full device descriptor failed\n");
  96. return ret;
  97. }
  98. /* get configuration descriptor head */
  99. ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION, &cfg_desc,
  100. sizeof(struct uconfig_descriptor));
  101. if(ret != RT_EOK)
  102. {
  103. rt_kprintf("get configuration descriptor head failed\n");
  104. return ret;
  105. }
  106. /* alloc memory for configuration descriptor */
  107. uinst->cfg_desc = (ucfg_desc_t)rt_malloc(cfg_desc.wTotalLength);
  108. rt_memset(uinst->cfg_desc, 0, cfg_desc.wTotalLength);
  109. /* get full configuration descriptor */
  110. ret = rt_usb_get_descriptor(uinst, USB_DESC_TYPE_CONFIGURATION,
  111. uinst->cfg_desc, cfg_desc.wTotalLength);
  112. if(ret != RT_EOK)
  113. {
  114. rt_kprintf("get full configuration descriptor failed\n");
  115. return ret;
  116. }
  117. /* set configuration */
  118. ret = rt_usb_set_configure(uinst, 1);
  119. if(ret != RT_EOK) return ret;
  120. //for(i=0; i<uinst->cfg_desc->bNumInterfaces; i++)
  121. {
  122. /* get interface descriptor through configuration descriptor */
  123. ret = rt_usb_get_interface_descriptor(uinst->cfg_desc, i, &intf_desc);
  124. if(ret != RT_EOK)
  125. {
  126. rt_kprintf("rt_usb_get_interface_descriptor error\n");
  127. return -RT_ERROR;
  128. }
  129. /* find driver by class code found in interface descriptor */
  130. drv = rt_usb_class_driver_find(intf_desc->bInterfaceClass,
  131. intf_desc->bInterfaceSubClass);
  132. if(drv != RT_NULL)
  133. {
  134. /* allocate memory for interface uinst */
  135. uinst->ifinst[i] =
  136. (uifinst_t)rt_malloc(sizeof(struct uifinst));
  137. uinst->ifinst[i]->drv = drv;
  138. uinst->ifinst[i]->uinst = uinst;
  139. uinst->ifinst[i]->intf_desc = intf_desc;
  140. /* open usb class driver */
  141. ret = rt_usb_class_driver_run(drv, (void*)uinst->ifinst[i]);
  142. if(ret != RT_EOK)
  143. {
  144. rt_kprintf("interface %d run class driver error\n", i);
  145. }
  146. }
  147. else
  148. {
  149. rt_kprintf("find usb device driver failed\n");
  150. return -RT_ERROR;
  151. }
  152. }
  153. return RT_EOK;
  154. }
  155. /**
  156. * This function will detach an usb device instance from its host controller,
  157. * and release all resource.
  158. *
  159. * @param uinst the usb device instance.
  160. *
  161. * @return the error code, RT_EOK on successfully.
  162. */
  163. rt_err_t rt_usb_detach_instance(uinst_t uinst)
  164. {
  165. int i = 0;
  166. if(uinst == RT_NULL)
  167. {
  168. rt_kprintf("no usb instance to detach\n");
  169. return -RT_ERROR;
  170. }
  171. /* free configration descriptor */
  172. if(uinst->cfg_desc) rt_free(uinst->cfg_desc);
  173. for(i=0; i<uinst->cfg_desc->bNumInterfaces; i++)
  174. {
  175. if(uinst->ifinst[i] == RT_NULL) continue;
  176. if(uinst->ifinst[i]->drv == RT_NULL) continue;
  177. RT_ASSERT(uinst->ifinst[i]->uinst == uinst);
  178. RT_DEBUG_LOG(RT_DEBUG_USB, ("free interface instance %d\n", i));
  179. rt_usb_class_driver_stop(uinst->ifinst[i]->drv, (void*)uinst->ifinst[i]);
  180. }
  181. rt_memset(uinst, 0, sizeof(struct uinstance));
  182. return RT_EOK;
  183. }
  184. /**
  185. * This function will do USB_REQ_GET_DESCRIPTO' request for the usb device instance,
  186. *
  187. * @param uinst the usb device instance.
  188. * @param type the type of descriptor request.
  189. * @param buffer the data buffer to save requested data
  190. * @param nbytes the size of buffer
  191. *
  192. * @return the error code, RT_EOK on successfully.
  193. */
  194. rt_err_t rt_usb_get_descriptor(uinst_t uinst, rt_uint8_t type, void* buffer,
  195. int nbytes)
  196. {
  197. struct ureqest setup;
  198. int timeout = 100;
  199. RT_ASSERT(uinst != RT_NULL);
  200. setup.request_type = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD |
  201. USB_REQ_TYPE_DEVICE;
  202. setup.request = USB_REQ_GET_DESCRIPTOR;
  203. setup.index = 0;
  204. setup.length = nbytes;
  205. setup.value = type << 8;
  206. if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, buffer, nbytes,
  207. timeout) != nbytes) return -RT_EIO;
  208. else return RT_EOK;
  209. }
  210. /**
  211. * This function will set an address to the usb device.
  212. *
  213. * @param uinst the usb device instance.
  214. *
  215. * @return the error code, RT_EOK on successfully.
  216. */
  217. rt_err_t rt_usb_set_address(uinst_t uinst)
  218. {
  219. struct ureqest setup;
  220. int timeout = 100;
  221. RT_ASSERT(uinst != RT_NULL);
  222. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usb_set_address\n"));
  223. setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
  224. USB_REQ_TYPE_DEVICE;
  225. setup.request = USB_REQ_SET_ADDRESS;
  226. setup.index = 0;
  227. setup.length = 0;
  228. setup.value = uinst->index;
  229. if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
  230. timeout) != 0) return -RT_EIO;
  231. rt_thread_delay(50);
  232. uinst->address = uinst->index;
  233. return RT_EOK;
  234. }
  235. /**
  236. * This function will set a configuration to the usb device.
  237. *
  238. * @param uinst the usb device instance.
  239. * @param config the configuration number.
  240. *
  241. * @return the error code, RT_EOK on successfully.
  242. */
  243. rt_err_t rt_usb_set_configure(uinst_t uinst, int config)
  244. {
  245. struct ureqest setup;
  246. int timeout = 100;
  247. /* check parameter */
  248. RT_ASSERT(uinst != RT_NULL);
  249. setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
  250. USB_REQ_TYPE_DEVICE;
  251. setup.request = USB_REQ_SET_CONFIGURATION;
  252. setup.index = 0;
  253. setup.length = 0;
  254. setup.value = config;
  255. if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
  256. timeout) != 0) return -RT_EIO;
  257. return RT_EOK;
  258. }
  259. /**
  260. * This function will set an interface to the usb device.
  261. *
  262. * @param uinst the usb device instance.
  263. * @param intf the interface number.
  264. *
  265. * @return the error code, RT_EOK on successfully.
  266. */
  267. rt_err_t rt_usb_set_interface(uinst_t uinst, int intf)
  268. {
  269. struct ureqest setup;
  270. int timeout = 100;
  271. /* check parameter */
  272. RT_ASSERT(uinst != RT_NULL);
  273. setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
  274. USB_REQ_TYPE_INTERFACE;
  275. setup.request = USB_REQ_SET_INTERFACE;
  276. setup.index = 0;
  277. setup.length = 0;
  278. setup.value = intf;
  279. if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
  280. timeout) != 0) return -RT_EIO;
  281. return RT_EOK;
  282. }
  283. /**
  284. * This function will clear feature for the endpoint of the usb device.
  285. *
  286. * @param uinst the usb device instance.
  287. * @param endpoint the endpoint number of the usb device.
  288. *
  289. * @return the error code, RT_EOK on successfully.
  290. */
  291. rt_err_t rt_usb_clear_feature(uinst_t uinst, int endpoint, int feature)
  292. {
  293. struct ureqest setup;
  294. int timeout = 100;
  295. /* check parameter */
  296. RT_ASSERT(uinst != RT_NULL);
  297. setup.request_type = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
  298. USB_REQ_TYPE_ENDPOINT;
  299. setup.request = USB_REQ_CLEAR_FEATURE;
  300. setup.index = endpoint;
  301. setup.length = 0;
  302. setup.value = feature;
  303. if(rt_usb_hcd_control_xfer(uinst->hcd, uinst, &setup, RT_NULL, 0,
  304. timeout) != 0) return -RT_EIO;
  305. return RT_EOK;
  306. }
  307. /**
  308. * This function will get an interface descriptor from the configuration descriptor.
  309. *
  310. * @param cfg_desc the point of configuration descriptor structure.
  311. * @param num the number of interface descriptor.
  312. * @intf_desc the point of interface descriptor point.
  313. *
  314. * @return the error code, RT_EOK on successfully.
  315. */
  316. rt_err_t rt_usb_get_interface_descriptor(ucfg_desc_t cfg_desc, int num,
  317. uintf_desc_t* intf_desc)
  318. {
  319. rt_uint32_t ptr, depth = 0;
  320. udesc_t desc;
  321. /* check parameter */
  322. RT_ASSERT(cfg_desc != RT_NULL);
  323. ptr = (rt_uint32_t)cfg_desc + cfg_desc->bLength;
  324. while(ptr < (rt_uint32_t)cfg_desc + cfg_desc->wTotalLength)
  325. {
  326. if(depth++ > 0x20)
  327. {
  328. *intf_desc = RT_NULL;
  329. return -RT_EIO;
  330. }
  331. desc = (udesc_t)ptr;
  332. if(desc->type == USB_DESC_TYPE_INTERFACE)
  333. {
  334. if(((uintf_desc_t)desc)->bInterfaceNumber == num)
  335. {
  336. *intf_desc = (uintf_desc_t)desc;
  337. RT_DEBUG_LOG(RT_DEBUG_USB,
  338. ("rt_usb_get_interface_descriptor: %d\n", num));
  339. return RT_EOK;
  340. }
  341. }
  342. ptr = (rt_uint32_t)desc + desc->bLength;
  343. }
  344. rt_kprintf("rt_usb_get_interface_descriptor %d failed\n", num);
  345. return -RT_EIO;
  346. }
  347. /**
  348. * This function will get an endpoint descriptor from the interface descriptor.
  349. *
  350. * @param intf_desc the point of interface descriptor structure.
  351. * @param num the number of endpoint descriptor.
  352. * @param ep_desc the point of endpoint descriptor point.
  353. *
  354. * @return the error code, RT_EOK on successfully.
  355. */
  356. rt_err_t rt_usb_get_endpoint_descriptor(uintf_desc_t intf_desc, int num,
  357. uep_desc_t* ep_desc)
  358. {
  359. int count = 0, depth = 0;
  360. rt_uint32_t ptr;
  361. udesc_t desc;
  362. /* check parameter */
  363. RT_ASSERT(intf_desc != RT_NULL);
  364. RT_ASSERT(num < intf_desc->bNumEndpoints);
  365. ptr = (rt_uint32_t)intf_desc + intf_desc->bLength;
  366. while(count < intf_desc->bNumEndpoints)
  367. {
  368. if(depth++ > 0x20)
  369. {
  370. *ep_desc = RT_NULL;
  371. return -RT_EIO;
  372. }
  373. desc = (udesc_t)ptr;
  374. if(desc->type == USB_DESC_TYPE_ENDPOINT)
  375. {
  376. if(num == count)
  377. {
  378. *ep_desc = (uep_desc_t)desc;
  379. RT_DEBUG_LOG(RT_DEBUG_USB,
  380. ("rt_usb_get_endpoint_descriptor: %d\n", num));
  381. return RT_EOK;
  382. }
  383. else count++;
  384. }
  385. ptr = (rt_uint32_t)desc + desc->bLength;
  386. }
  387. rt_kprintf("rt_usb_get_endpoint_descriptor %d failed\n", num);
  388. return -RT_EIO;
  389. }