core.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250
  1. /*
  2. * File : core.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2012, 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. * 2012-10-01 Yi Qiu first version
  13. */
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. static rt_list_t device_list;
  17. /**
  18. * This function will handle get_device_descriptor request.
  19. *
  20. * @param device the usb device object.
  21. * @param setup the setup request.
  22. *
  23. * @return RT_EOK on successful.
  24. */
  25. static rt_err_t _get_device_descriptor(struct udevice* device, ureq_t setup)
  26. {
  27. rt_size_t size;
  28. /* parameter check */
  29. RT_ASSERT(device != RT_NULL);
  30. RT_ASSERT(setup != RT_NULL);
  31. RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_device_descriptor\n"));
  32. /* device descriptor length should less than USB_DESC_LENGTH_DEVICE*/
  33. size = (setup->length > USB_DESC_LENGTH_DEVICE) ?
  34. USB_DESC_LENGTH_DEVICE : setup->length;
  35. /* send device descriptor to endpoint 0 */
  36. dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&device->dev_desc,
  37. size);
  38. return RT_EOK;
  39. }
  40. /**
  41. * This function will handle get_config_descriptor request.
  42. *
  43. * @param device the usb device object.
  44. * @param setup the setup request.
  45. *
  46. * @return RT_EOK on successful.
  47. */
  48. static rt_err_t _get_config_descriptor(struct udevice* device, ureq_t setup)
  49. {
  50. rt_size_t size;
  51. ucfg_desc_t cfg_desc;
  52. /* parameter check */
  53. RT_ASSERT(device != RT_NULL);
  54. RT_ASSERT(setup != RT_NULL);
  55. RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config_descriptor\n"));
  56. cfg_desc = &device->curr_cfg->cfg_desc;
  57. size = (setup->length > cfg_desc->wTotalLength) ?
  58. cfg_desc->wTotalLength : setup->length;
  59. /* send configuration descriptor to endpoint 0 */
  60. dcd_ep_write(device->dcd, 0, (rt_uint8_t*)cfg_desc, size);
  61. return RT_EOK;
  62. }
  63. /**
  64. * This function will handle get_string_descriptor request.
  65. *
  66. * @param device the usb device object.
  67. * @param setup the setup request.
  68. *
  69. * @return RT_EOK on successful, -RT_ERROR on invalid request.
  70. */
  71. static rt_err_t _get_string_descriptor(struct udevice* device, ureq_t setup)
  72. {
  73. struct ustring_descriptor str_desc;
  74. rt_uint8_t index, i;
  75. rt_uint32_t len;
  76. /* parameter check */
  77. RT_ASSERT(device != RT_NULL);
  78. RT_ASSERT(setup != RT_NULL);
  79. RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_string_descriptor\n"));
  80. str_desc.type = USB_DESC_TYPE_STRING;
  81. index = setup->value & 0xFF;
  82. if(index > USB_STRING_INTERFACE_INDEX)
  83. {
  84. rt_kprintf("unknown string index\n");
  85. dcd_ep0_stall(device->dcd);
  86. return -RT_ERROR;
  87. }
  88. if(index == 0)
  89. {
  90. str_desc.bLength = 4;
  91. str_desc.String[0] = 0x09;
  92. str_desc.String[1] = 0x04;
  93. }
  94. else
  95. {
  96. len = rt_strlen(device->str[index]);
  97. str_desc.bLength = len*2 + 2;
  98. for(i=0; i<len; i++)
  99. {
  100. str_desc.String[i*2] = device->str[index][i];
  101. str_desc.String[i*2 + 1] = 0;
  102. }
  103. }
  104. /* send string descriptor to endpoint 0 */
  105. dcd_ep_write(device->dcd, 0, (rt_uint8_t*)&str_desc,
  106. str_desc.bLength);
  107. return RT_EOK;
  108. }
  109. /**
  110. * This function will handle get_descriptor request.
  111. *
  112. * @param device the usb device object.
  113. * @param setup the setup request.
  114. *
  115. * @return RT_EOK on successful.
  116. */
  117. static rt_err_t _get_descriptor(struct udevice* device, ureq_t setup)
  118. {
  119. /* parameter check */
  120. RT_ASSERT(device != RT_NULL);
  121. RT_ASSERT(setup != RT_NULL);
  122. if(setup->request_type == USB_REQ_TYPE_DIR_IN)
  123. {
  124. switch(setup->value >> 8)
  125. {
  126. case USB_DESC_TYPE_DEVICE:
  127. _get_device_descriptor(device, setup);
  128. break;
  129. case USB_DESC_TYPE_CONFIGURATION:
  130. _get_config_descriptor(device, setup);
  131. break;
  132. case USB_DESC_TYPE_STRING:
  133. _get_string_descriptor(device, setup);
  134. break;
  135. default:
  136. rt_kprintf("unknown descriptor\n");
  137. dcd_ep0_stall(device->dcd);
  138. break;
  139. }
  140. }
  141. else
  142. {
  143. rt_kprintf("request direction error\n");
  144. dcd_ep0_stall(device->dcd);
  145. }
  146. return RT_EOK;
  147. }
  148. /**
  149. * This function will handle get_interface request.
  150. *
  151. * @param device the usb device object.
  152. * @param setup the setup request.
  153. *
  154. * @return RT_EOK on successful.
  155. */
  156. static rt_err_t _get_interface(struct udevice* device, ureq_t setup)
  157. {
  158. rt_uint8_t value;
  159. uintf_t intf;
  160. /* parameter check */
  161. RT_ASSERT(device != RT_NULL);
  162. RT_ASSERT(setup != RT_NULL);
  163. RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_interface\n"));
  164. /* find the specified interface and its alternate setting */
  165. intf = rt_usbd_find_interface(device, setup->index & 0xFF);
  166. value = intf->curr_setting->intf_desc->bAlternateSetting;
  167. /* send the interface alternate setting to endpoint 0*/
  168. dcd_ep_write(device->dcd, 0, &value, 1);
  169. return RT_EOK;
  170. }
  171. /**
  172. * This function will handle set_interface request.
  173. *
  174. * @param device the usb device object.
  175. * @param setup the setup request.
  176. *
  177. * @return RT_EOK on successful.
  178. */
  179. static rt_err_t _set_interface(struct udevice* device, ureq_t setup)
  180. {
  181. uintf_t intf;
  182. uep_t ep;
  183. struct rt_list_node* i;
  184. ualtsetting_t setting;
  185. /* parameter check */
  186. RT_ASSERT(device != RT_NULL);
  187. RT_ASSERT(setup != RT_NULL);
  188. RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_interface\n"));
  189. setup->index & 0xFF;
  190. setup->value & 0xFF;
  191. /* find the specified interface */
  192. intf = rt_usbd_find_interface(device, setup->index & 0xFF);
  193. /* set alternate setting to the interface */
  194. rt_usbd_set_altsetting(intf, setup->value & 0xFF);
  195. setting = intf->curr_setting;
  196. /* start all endpoints of the interface alternate setting */
  197. for(i=setting->ep_list.next; i != &setting->ep_list; i=i->next)
  198. {
  199. ep = (uep_t)rt_list_entry(i, struct uendpoint, list);
  200. dcd_ep_stop(device->dcd, ep);
  201. dcd_ep_run(device->dcd, ep);
  202. }
  203. return RT_EOK;
  204. }
  205. /**
  206. * This function will handle get_config request.
  207. *
  208. * @param device the usb device object.
  209. * @param setup the setup request.
  210. *
  211. * @return RT_EOK on successful.
  212. */
  213. static rt_err_t _get_config(struct udevice* device, ureq_t setup)
  214. {
  215. rt_uint8_t value;
  216. /* parameter check */
  217. RT_ASSERT(device != RT_NULL);
  218. RT_ASSERT(setup != RT_NULL);
  219. RT_ASSERT(device->curr_cfg != RT_NULL);
  220. RT_DEBUG_LOG(RT_DEBUG_USB, ("_get_config\n"));
  221. /* get current configuration */
  222. value = device->curr_cfg->cfg_desc.bConfigurationValue;
  223. /* write the current configuration to endpoint 0 */
  224. dcd_ep_write(device->dcd, 0, &value, 1);
  225. return RT_EOK;
  226. }
  227. /**
  228. * This function will handle set_config request.
  229. *
  230. * @param device the usb device object.
  231. * @param setup the setup request.
  232. *
  233. * @return RT_EOK on successful.
  234. */
  235. static rt_err_t _set_config(struct udevice* device, ureq_t setup)
  236. {
  237. struct rt_list_node *i, *j, *k;
  238. uconfig_t cfg;
  239. uintf_t intf;
  240. ualtsetting_t setting;
  241. uep_t ep;
  242. /* parameter check */
  243. RT_ASSERT(device != RT_NULL);
  244. RT_ASSERT(setup != RT_NULL);
  245. RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_config\n"));
  246. /* set current configuration */
  247. rt_usbd_set_config(device, setup->value);
  248. cfg = device->curr_cfg;
  249. for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next)
  250. {
  251. /* run all classes and their endpoints in the configuration */
  252. uclass_t cls = (uclass_t)rt_list_entry(i, struct uclass, list);
  253. for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
  254. {
  255. intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
  256. setting = intf->curr_setting;
  257. for(k=setting->ep_list.next; k != &setting->ep_list; k=k->next)
  258. {
  259. ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
  260. /* first stop then start endpoint */
  261. dcd_ep_stop(device->dcd, ep);
  262. dcd_ep_run(device->dcd, ep);
  263. }
  264. }
  265. /* after running all endpoints, then run class */
  266. if(cls->ops->run != RT_NULL) cls->ops->run(device);
  267. }
  268. /* issue status stage */
  269. rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
  270. return RT_EOK;
  271. }
  272. /**
  273. * This function will handle set_address request.
  274. *
  275. * @param device the usb device object.
  276. * @param setup the setup request.
  277. *
  278. * @return RT_EOK on successful.
  279. */
  280. static rt_err_t _set_address(struct udevice* device, ureq_t setup)
  281. {
  282. /* parameter check */
  283. RT_ASSERT(device != RT_NULL);
  284. RT_ASSERT(setup != RT_NULL);
  285. RT_DEBUG_LOG(RT_DEBUG_USB, ("_set_address\n"));
  286. /* set address in device control driver */
  287. dcd_set_address(device->dcd, setup->value);
  288. /* issue status stage */
  289. rt_device_control((rt_device_t)device->dcd, CONTROL_SEND_STATUS, RT_NULL);
  290. return RT_EOK;
  291. }
  292. /**
  293. * This function will handle standard request.
  294. *
  295. * @param device the usb device object.
  296. * @param setup the setup request.
  297. *
  298. * @return RT_EOK on successful.
  299. */
  300. static rt_err_t _standard_request(struct udevice* device, ureq_t setup)
  301. {
  302. udcd_t dcd;
  303. rt_uint16_t value = 0;
  304. /* parameter check */
  305. RT_ASSERT(device != RT_NULL);
  306. RT_ASSERT(setup != RT_NULL);
  307. dcd = device->dcd;
  308. switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
  309. {
  310. case USB_REQ_TYPE_DEVICE:
  311. switch(setup->request)
  312. {
  313. case USB_REQ_GET_STATUS:
  314. dcd_ep_write(device->dcd, 0, &value, 2);
  315. break;
  316. case USB_REQ_CLEAR_FEATURE:
  317. dcd_clear_feature(dcd, setup->value);
  318. break;
  319. case USB_REQ_SET_FEATURE:
  320. dcd_set_feature(dcd, setup->value);
  321. break;
  322. case USB_REQ_SET_ADDRESS:
  323. _set_address(device, setup);
  324. break;
  325. case USB_REQ_GET_DESCRIPTOR:
  326. _get_descriptor(device, setup);
  327. break;
  328. case USB_REQ_SET_DESCRIPTOR:
  329. dcd_ep0_stall(dcd);
  330. break;
  331. case USB_REQ_GET_CONFIGURATION:
  332. _get_config(device, setup);
  333. break;
  334. case USB_REQ_SET_CONFIGURATION:
  335. _set_config(device, setup);
  336. break;
  337. default:
  338. rt_kprintf("unknown device request\n");
  339. dcd_ep0_stall(device->dcd);
  340. break;
  341. }
  342. break;
  343. case USB_REQ_TYPE_INTERFACE:
  344. switch(setup->request)
  345. {
  346. case USB_REQ_GET_INTERFACE:
  347. _get_interface(device, setup);
  348. break;
  349. case USB_REQ_SET_INTERFACE:
  350. _set_interface(device, setup);
  351. break;
  352. default:
  353. rt_kprintf("unknown interface request\n");
  354. dcd_ep0_stall(device->dcd);
  355. break;
  356. }
  357. break;
  358. case USB_REQ_TYPE_ENDPOINT:
  359. switch(setup->request)
  360. {
  361. case USB_REQ_GET_STATUS:
  362. /* TODO */
  363. dcd_ep_write(dcd, 0, &value, 2);
  364. break;
  365. case USB_REQ_CLEAR_FEATURE:
  366. dcd_clear_feature(dcd, setup->value);
  367. break;
  368. case USB_REQ_SET_FEATURE:
  369. dcd_set_feature(dcd, setup->value);
  370. break;
  371. case USB_REQ_SYNCH_FRAME:
  372. break;
  373. default:
  374. rt_kprintf("unknown endpoint request\n");
  375. dcd_ep0_stall(device->dcd);
  376. break;
  377. }
  378. break;
  379. case USB_REQ_TYPE_OTHER:
  380. rt_kprintf("unknown other type request\n");
  381. dcd_ep0_stall(device->dcd);
  382. break;
  383. default:
  384. rt_kprintf("unknown type request\n");
  385. dcd_ep0_stall(device->dcd);
  386. break;
  387. }
  388. return RT_EOK;
  389. }
  390. /**
  391. * This function will handle class request.
  392. *
  393. * @param device the usb device object.
  394. * @param setup the setup request.
  395. *
  396. * @return RT_EOK on successful, -RT_ERROR on invalid request.
  397. */
  398. static rt_err_t _class_request(udevice_t device, ureq_t setup)
  399. {
  400. uintf_t intf;
  401. /* parameter check */
  402. RT_ASSERT(device != RT_NULL);
  403. RT_ASSERT(setup != RT_NULL);
  404. /* verify request value */
  405. if(setup->index > device->curr_cfg->cfg_desc.bNumInterfaces)
  406. {
  407. dcd_ep0_stall(device->dcd);
  408. return -RT_ERROR;
  409. }
  410. switch(setup->request_type & USB_REQ_TYPE_RECIPIENT_MASK)
  411. {
  412. case USB_REQ_TYPE_INTERFACE:
  413. intf = rt_usbd_find_interface(device, setup->index & 0xFF);
  414. intf->handler(device, setup);
  415. break;
  416. case USB_REQ_TYPE_ENDPOINT:
  417. break;
  418. default:
  419. rt_kprintf("unknown class request type\n");
  420. dcd_ep0_stall(device->dcd);
  421. break;
  422. }
  423. return RT_EOK;
  424. }
  425. /**
  426. * This function will handle setup request.
  427. *
  428. * @param device the usb device object.
  429. * @param setup the setup request.
  430. *
  431. * @return RT_EOK on successful, -RT_ERROR on invalid request.
  432. */
  433. static rt_err_t _setup_request(udevice_t device, ureq_t setup)
  434. {
  435. /* parameter check */
  436. RT_ASSERT(device != RT_NULL);
  437. RT_ASSERT(setup != RT_NULL);
  438. RT_DEBUG_LOG(RT_DEBUG_USB, ("[\n"));
  439. RT_DEBUG_LOG(RT_DEBUG_USB, ("setup_request_handler 0x%x\n", setup->request_type));
  440. RT_DEBUG_LOG(RT_DEBUG_USB, ("value 0x%x\n", setup->value));
  441. RT_DEBUG_LOG(RT_DEBUG_USB, ("length 0x%x\n", setup->length));
  442. RT_DEBUG_LOG(RT_DEBUG_USB, ("index 0x%x\n", setup->index));
  443. RT_DEBUG_LOG(RT_DEBUG_USB, ("request 0x%x\n", setup->request));
  444. RT_DEBUG_LOG(RT_DEBUG_USB, ("]\n"));
  445. switch((setup->request_type & USB_REQ_TYPE_MASK))
  446. {
  447. case USB_REQ_TYPE_STANDARD:
  448. _standard_request(device, setup);
  449. break;
  450. case USB_REQ_TYPE_CLASS:
  451. _class_request(device, setup);
  452. break;
  453. case USB_REQ_TYPE_VENDOR:
  454. rt_kprintf("vendor type request\n");
  455. break;
  456. default:
  457. rt_kprintf("unknown setup request type\n");
  458. dcd_ep0_stall(device->dcd);
  459. return -RT_ERROR;
  460. }
  461. return RT_EOK;
  462. }
  463. /**
  464. * This function will create an usb device object.
  465. *
  466. * @param ustring the usb string array to contain string descriptor.
  467. *
  468. * @return an usb device object on success, RT_NULL on fail.
  469. */
  470. udevice_t rt_usbd_device_create(const char** ustring)
  471. {
  472. udevice_t udevice;
  473. /* parameter check */
  474. RT_ASSERT(ustring != RT_NULL);
  475. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_create\n"));
  476. /* allocate memory for the object */
  477. udevice = rt_malloc(sizeof(struct udevice));
  478. if(udevice == RT_NULL)
  479. {
  480. rt_kprintf("alloc memery failed\n");
  481. return RT_NULL;
  482. }
  483. rt_memset(udevice, 0, sizeof(struct udevice));
  484. /* set string descriptor array to the device object */
  485. udevice->str = ustring;
  486. /* to initialize configuration list */
  487. rt_list_init(&udevice->cfg_list);
  488. /* insert the device object to device list */
  489. rt_list_insert_after(&device_list, &udevice->list);
  490. return udevice;
  491. }
  492. /**
  493. * This function will set an usb controller driver to a device.
  494. *
  495. * @param device the usb device object.
  496. * @param dcd the usb device controller driver.
  497. *
  498. * @return RT_EOK on successful.
  499. */
  500. rt_err_t rt_usbd_device_set_controller(udevice_t device, udcd_t dcd)
  501. {
  502. /* parameter check */
  503. RT_ASSERT(device != RT_NULL);
  504. RT_ASSERT(dcd != RT_NULL);
  505. /* set usb device controller driver to the device */
  506. device->dcd = dcd;
  507. return RT_EOK;
  508. }
  509. /**
  510. * This function will set an usb device descriptor to a device.
  511. *
  512. * @param device the usb device object.
  513. * @param dev_desc the usb device descriptor.
  514. *
  515. * @return RT_EOK on successful.
  516. */
  517. rt_err_t rt_usbd_device_set_descriptor(udevice_t device, udev_desc_t dev_desc)
  518. {
  519. /* parameter check */
  520. RT_ASSERT(device != RT_NULL);
  521. RT_ASSERT(dev_desc != RT_NULL);
  522. /* copy the usb device descriptor to the device */
  523. rt_memcpy((void *)&device->dev_desc, (void *)dev_desc, USB_DESC_LENGTH_DEVICE);
  524. return RT_EOK;
  525. }
  526. /**
  527. * This function will create an usb configuration object.
  528. *
  529. * @param none.
  530. *
  531. * @return an usb configuration object.
  532. */
  533. uconfig_t rt_usbd_config_create(void)
  534. {
  535. uconfig_t cfg;
  536. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_create\n"));
  537. /* allocate memory for the object */
  538. cfg = rt_malloc(sizeof(struct uconfig));
  539. if(cfg == RT_NULL)
  540. {
  541. rt_kprintf("alloc memery failed\n");
  542. return RT_NULL;
  543. }
  544. rt_memset(cfg, 0, sizeof(struct uconfig));
  545. /* set default value */
  546. cfg->cfg_desc.bLength = USB_DESC_LENGTH_CONFIG;
  547. cfg->cfg_desc.type = USB_DESC_TYPE_CONFIGURATION;
  548. cfg->cfg_desc.wTotalLength = USB_DESC_LENGTH_CONFIG;
  549. cfg->cfg_desc.bmAttributes = 0xC0;
  550. cfg->cfg_desc.MaxPower = 0x32;
  551. /* to initialize class object list */
  552. rt_list_init(&cfg->cls_list);
  553. return cfg;
  554. }
  555. /**
  556. * This function will create an usb interface object.
  557. *
  558. * @param device the usb device object.
  559. * @handler the callback handler of object
  560. *
  561. * @return an usb interface object on success, RT_NULL on fail.
  562. */
  563. uintf_t rt_usbd_interface_create(udevice_t device,
  564. rt_err_t (*handler)(struct udevice*, ureq_t setup))
  565. {
  566. uintf_t intf;
  567. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_create\n"));
  568. /* parameter check */
  569. RT_ASSERT(device != RT_NULL);
  570. /* allocate memory for the object */
  571. intf = (uintf_t)rt_malloc(sizeof(struct uinterface));
  572. if(intf == RT_NULL)
  573. {
  574. rt_kprintf("alloc memery failed\n");
  575. return RT_NULL;
  576. }
  577. intf->intf_num = device->nr_intf;
  578. device->nr_intf++;
  579. intf->handler = handler;
  580. intf->curr_setting = RT_NULL;
  581. /* to initialize the alternate setting object list */
  582. rt_list_init(&intf->setting_list);
  583. return intf;
  584. }
  585. /**
  586. * This function will create an usb alternate setting object.
  587. *
  588. * @param intf_desc the interface descriptor.
  589. * @desc_size the size of the interface descriptor.
  590. *
  591. * @return an usb alternate setting object on success, RT_NULL on fail.
  592. */
  593. ualtsetting_t rt_usbd_altsetting_create(uintf_desc_t intf_desc, rt_size_t desc_size)
  594. {
  595. ualtsetting_t setting;
  596. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_create\n"));
  597. /* parameter check */
  598. RT_ASSERT(intf_desc != RT_NULL);
  599. RT_ASSERT(desc_size > 0);
  600. /* allocate memory for the object */
  601. setting = (ualtsetting_t)rt_malloc(sizeof(struct ualtsetting));
  602. if(setting == RT_NULL)
  603. {
  604. rt_kprintf("alloc memery failed\n");
  605. return RT_NULL;
  606. }
  607. setting->desc_size = desc_size;
  608. setting->intf_desc = intf_desc;
  609. /* to initialize endpoint list */
  610. rt_list_init(&setting->ep_list);
  611. return setting;
  612. }
  613. /**
  614. * This function will create an usb class object.
  615. *
  616. * @param device the usb device object.
  617. * @param dev_desc the device descriptor.
  618. * @param ops the operation set.
  619. *
  620. * @return an usb class object on success, RT_NULL on fail.
  621. */
  622. uclass_t rt_usbd_class_create(udevice_t device, udev_desc_t dev_desc,
  623. uclass_ops_t ops)
  624. {
  625. uclass_t cls;
  626. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_create\n"));
  627. /* parameter check */
  628. RT_ASSERT(device != RT_NULL);
  629. RT_ASSERT(dev_desc != RT_NULL);
  630. /* allocate memory for the object */
  631. cls = (uclass_t)rt_malloc(sizeof(struct uclass));
  632. if(cls == RT_NULL)
  633. {
  634. rt_kprintf("alloc memery failed\n");
  635. return RT_NULL;
  636. }
  637. cls->dev_desc = dev_desc;
  638. cls->ops = ops;
  639. cls->device = device;
  640. /* to initialize interface list */
  641. rt_list_init(&cls->intf_list);
  642. return cls;
  643. }
  644. /**
  645. * This function will create an usb endpoint object.
  646. *
  647. * @param ep_desc the endpoint descriptor.
  648. * @handler the callback handler of object
  649. *
  650. * @return an usb endpoint object on success, RT_NULL on fail.
  651. */
  652. uep_t rt_usbd_endpoint_create(uep_desc_t ep_desc,
  653. rt_err_t (*handler)(struct udevice*, rt_size_t size))
  654. {
  655. uep_t ep;
  656. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_endpoint_create\n"));
  657. /* parameter check */
  658. RT_ASSERT(ep_desc != RT_NULL);
  659. /* allocate memory for the object */
  660. ep = (uep_t)rt_malloc(sizeof(struct uendpoint));
  661. if(ep == RT_NULL)
  662. {
  663. rt_kprintf("alloc memery failed\n");
  664. return RT_NULL;
  665. }
  666. ep->ep_desc = ep_desc;
  667. ep->handler = handler;
  668. /* allocate buffer for endpoint */
  669. ep->buffer = (rt_uint8_t*)rt_malloc(ep_desc->wMaxPacketSize);
  670. return ep;
  671. }
  672. /**
  673. * This function will find an usb device object.
  674. *
  675. * @dcd usd device controller driver.
  676. *
  677. * @return an usb device object on found or RT_NULL on not found.
  678. */
  679. udevice_t rt_usbd_find_device(udcd_t dcd)
  680. {
  681. struct rt_list_node* node;
  682. udevice_t device;
  683. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_device\n"));
  684. /* parameter check */
  685. RT_ASSERT(dcd != RT_NULL);
  686. /* search a device in the the device list */
  687. for (node = device_list.next; node != &device_list; node = node->next)
  688. {
  689. device = (udevice_t)rt_list_entry(node, struct udevice, list);
  690. if(device->dcd == dcd) return device;
  691. }
  692. rt_kprintf("can't find device\n");
  693. return RT_NULL;
  694. }
  695. /**
  696. * This function will find an usb configuration object.
  697. *
  698. * @param device the usb device object.
  699. * @param value the configuration number.
  700. *
  701. * @return an usb configuration object on found or RT_NULL on not found.
  702. */
  703. uconfig_t rt_usbd_find_config(udevice_t device, rt_uint8_t value)
  704. {
  705. struct rt_list_node* node;
  706. uconfig_t cfg = RT_NULL;
  707. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_config\n"));
  708. /* parameter check */
  709. RT_ASSERT(device != RT_NULL);
  710. RT_ASSERT(value <= device->dev_desc.bNumConfigurations);
  711. /* search a configration in the the device */
  712. for (node = device->cfg_list.next; node != &device->cfg_list; node = node->next)
  713. {
  714. cfg = (uconfig_t)rt_list_entry(node, struct udevice, list);
  715. if(cfg->cfg_desc.bConfigurationValue == value) return cfg;
  716. }
  717. rt_kprintf("can't find configuration %d\n", value);
  718. return RT_NULL;
  719. }
  720. /**
  721. * This function will find an usb interface object.
  722. *
  723. * @param device the usb device object.
  724. * @param value the interface number.
  725. *
  726. * @return an usb configuration object on found or RT_NULL on not found.
  727. */
  728. uintf_t rt_usbd_find_interface(udevice_t device, rt_uint8_t value)
  729. {
  730. uep_t ep;
  731. struct rt_list_node *i, *j;
  732. uclass_t cls;
  733. uintf_t intf;
  734. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_interface\n"));
  735. /* parameter check */
  736. RT_ASSERT(device != RT_NULL);
  737. RT_ASSERT(value < device->nr_intf);
  738. /* search an interface in the current configuration */
  739. for (i=device->curr_cfg->cls_list.next;
  740. i!=&device->curr_cfg->cls_list; i=i->next)
  741. {
  742. cls = (uclass_t)rt_list_entry(i, struct uclass, list);
  743. for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
  744. {
  745. intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
  746. if(intf->intf_num == value)
  747. return intf;
  748. }
  749. }
  750. rt_kprintf("can't find interface %d\n", value);
  751. return RT_NULL;
  752. }
  753. /**
  754. * This function will find an usb interface alternate setting object.
  755. *
  756. * @param device the usb device object.
  757. * @param value the alternate setting number.
  758. *
  759. * @return an usb interface alternate setting object on found or RT_NULL on not found.
  760. */
  761. ualtsetting_t rt_usbd_find_altsetting(uintf_t intf, rt_uint8_t value)
  762. {
  763. struct rt_list_node *i;
  764. ualtsetting_t setting;
  765. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_find_altsetting\n"));
  766. /* parameter check */
  767. RT_ASSERT(intf != RT_NULL);
  768. if(intf->curr_setting != RT_NULL)
  769. {
  770. /* if the value equal to the current alternate setting, then do not search */
  771. if(intf->curr_setting->intf_desc->bAlternateSetting == value)
  772. return intf->curr_setting;
  773. }
  774. /* search a setting in the alternate setting list */
  775. for(i=intf->setting_list.next; i!=&intf->setting_list; i=i->next)
  776. {
  777. setting =(ualtsetting_t)rt_list_entry(i, struct ualtsetting, list);
  778. if(setting->intf_desc->bAlternateSetting == value)
  779. return setting;
  780. }
  781. rt_kprintf("can't find alternate setting %d\n", value);
  782. return RT_NULL;
  783. }
  784. /**
  785. * This function will find an usb endpoint object.
  786. *
  787. * @param device the usb device object.
  788. * @param ep_addr endpoint address.
  789. *
  790. * @return an usb endpoint object on found or RT_NULL on not found.
  791. */
  792. uep_t rt_usbd_find_endpoint(udevice_t device, rt_uint8_t ep_addr)
  793. {
  794. uep_t ep;
  795. struct rt_list_node *i, *j, *k;
  796. uclass_t cls;
  797. uintf_t intf;
  798. /* parameter check */
  799. RT_ASSERT(device != RT_NULL);
  800. /* search a endpoint in the current configuration */
  801. for (i=device->curr_cfg->cls_list.next;
  802. i!=&device->curr_cfg->cls_list; i=i->next)
  803. {
  804. cls = (uclass_t)rt_list_entry(i, struct uclass, list);
  805. for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
  806. {
  807. intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
  808. for(k=intf->curr_setting->ep_list.next;
  809. k!=&intf->curr_setting->ep_list; k=k->next)
  810. {
  811. ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
  812. if(ep->ep_desc->bEndpointAddress == ep_addr)
  813. return ep;
  814. }
  815. }
  816. }
  817. rt_kprintf("can't find endpoint 0x%x\n", ep_addr);
  818. return RT_NULL;
  819. }
  820. /**
  821. * This function will add a configuration to an usb device.
  822. *
  823. * @param device the usb device object.
  824. * @param cfg the configuration object.
  825. *
  826. * @return RT_EOK.
  827. */
  828. rt_err_t rt_usbd_device_add_config(udevice_t device, uconfig_t cfg)
  829. {
  830. struct rt_list_node *i, *j, *k;
  831. uclass_t cls;
  832. uintf_t intf;
  833. uep_t ep;
  834. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_device_add_config\n"));
  835. /* parameter check */
  836. RT_ASSERT(device != RT_NULL);
  837. RT_ASSERT(cfg != RT_NULL);
  838. /* set configuration number to the configuration descriptor */
  839. cfg->cfg_desc.bConfigurationValue = device->dev_desc.bNumConfigurations + 1;
  840. device->dev_desc.bNumConfigurations++;
  841. for (i=cfg->cls_list.next; i!=&cfg->cls_list; i=i->next)
  842. {
  843. cls = (uclass_t)rt_list_entry(i, struct uclass, list);
  844. for(j=cls->intf_list.next; j!=&cls->intf_list; j=j->next)
  845. {
  846. intf = (uintf_t)rt_list_entry(j, struct uinterface, list);
  847. cfg->cfg_desc.bNumInterfaces++;
  848. /* allocate address for every endpoint in the interface alternate setting */
  849. for(k=intf->curr_setting->ep_list.next;
  850. k!=&intf->curr_setting->ep_list; k=k->next)
  851. {
  852. ep = (uep_t)rt_list_entry(k, struct uendpoint, list);
  853. dcd_ep_alloc(device->dcd, ep);
  854. }
  855. /* construct complete configuration descriptor */
  856. rt_memcpy((void*)&cfg->cfg_desc.data[cfg->cfg_desc.wTotalLength -
  857. USB_DESC_LENGTH_CONFIG], (void*)intf->curr_setting->intf_desc,
  858. intf->curr_setting->desc_size);
  859. cfg->cfg_desc.wTotalLength += intf->curr_setting->desc_size;
  860. }
  861. }
  862. /* insert the configuration to the list */
  863. rt_list_insert_after(&device->cfg_list, &cfg->list);
  864. return RT_EOK;
  865. }
  866. /**
  867. * This function will add a class to a configuration.
  868. *
  869. * @param cfg the configuration object.
  870. * @param cls the class object.
  871. *
  872. * @return RT_EOK.
  873. */
  874. rt_err_t rt_usbd_config_add_class(uconfig_t cfg, uclass_t cls)
  875. {
  876. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_config_add_class\n"));
  877. /* parameter check */
  878. RT_ASSERT(cfg != RT_NULL);
  879. RT_ASSERT(cls != RT_NULL);
  880. /* insert the class to the list */
  881. rt_list_insert_after(&cfg->cls_list, &cls->list);
  882. return RT_EOK;
  883. }
  884. /**
  885. * This function will add an interface to a class.
  886. *
  887. * @param cls the class object.
  888. * @param intf the interface object.
  889. *
  890. * @return RT_EOK.
  891. */
  892. rt_err_t rt_usbd_class_add_interface(uclass_t cls, uintf_t intf)
  893. {
  894. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_class_add_interface\n"));
  895. /* parameter check */
  896. RT_ASSERT(cls != RT_NULL);
  897. RT_ASSERT(intf != RT_NULL);
  898. /* insert the interface to the list */
  899. rt_list_insert_after(&cls->intf_list, &intf->list);
  900. return RT_EOK;
  901. }
  902. /**
  903. * This function will add an alternate setting to an interface.
  904. *
  905. * @param intf the interface object.
  906. * @param setting the alternate setting object.
  907. *
  908. * @return RT_EOK.
  909. */
  910. rt_err_t rt_usbd_interface_add_altsetting(uintf_t intf, ualtsetting_t setting)
  911. {
  912. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_interface_add_altsetting\n"));
  913. /* parameter check */
  914. RT_ASSERT(intf != RT_NULL);
  915. RT_ASSERT(setting != RT_NULL);
  916. setting->intf_desc->bInterfaceNumber = intf->intf_num;
  917. /* insert the alternate setting to the list */
  918. rt_list_insert_after(&intf->setting_list, &setting->list);
  919. return RT_EOK;
  920. }
  921. /**
  922. * This function will add an endpoint to an alternate setting.
  923. *
  924. * @param setting the alternate setting object.
  925. * @param ep the endpoint object.
  926. *
  927. * @return RT_EOK.
  928. */
  929. rt_err_t rt_usbd_altsetting_add_endpoint(ualtsetting_t setting, uep_t ep)
  930. {
  931. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_altsetting_add_endpoint\n"));
  932. /* parameter check */
  933. RT_ASSERT(setting != RT_NULL);
  934. RT_ASSERT(ep != RT_NULL);
  935. /* insert the endpoint to the list */
  936. rt_list_insert_after(&setting->ep_list, &ep->list);
  937. return RT_EOK;
  938. }
  939. /**
  940. * This function will set an alternate setting for an interface.
  941. *
  942. * @param intf_desc the interface descriptor.
  943. * @param value the alternate setting number.
  944. *
  945. * @return RT_EOK.
  946. */
  947. rt_err_t rt_usbd_set_altsetting(uintf_t intf, rt_uint8_t value)
  948. {
  949. ualtsetting_t setting;
  950. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_altsetting\n"));
  951. /* parameter check */
  952. RT_ASSERT(intf != RT_NULL);
  953. RT_ASSERT(setting != RT_NULL);
  954. /* find an alternate setting */
  955. setting = rt_usbd_find_altsetting(intf, value);
  956. /* set as current alternate setting */
  957. intf->curr_setting = setting;
  958. return RT_EOK;
  959. }
  960. /**
  961. * This function will set a configuration for an usb device.
  962. *
  963. * @param device the usb device object.
  964. * @param value the configuration number.
  965. *
  966. * @return RT_EOK.
  967. */
  968. rt_err_t rt_usbd_set_config(udevice_t device, rt_uint8_t value)
  969. {
  970. uconfig_t cfg;
  971. RT_DEBUG_LOG(RT_DEBUG_USB, ("rt_usbd_set_config\n"));
  972. /* parameter check */
  973. RT_ASSERT(device != RT_NULL);
  974. RT_ASSERT(value <= device->dev_desc.bNumConfigurations);
  975. /* find a configuration */
  976. cfg = rt_usbd_find_config(device, value);
  977. /* set as current configuration */
  978. device->curr_cfg = cfg;
  979. return RT_TRUE;
  980. }
  981. static struct rt_messagequeue *usb_mq;
  982. /**
  983. * This function is the main entry of usb device thread, it is in charge of
  984. * processing all messages received from the usb message buffer.
  985. *
  986. * @param parameter the parameter of the usb device thread.
  987. *
  988. * @return none.
  989. */
  990. static void rt_usbd_thread_entry(void* parameter)
  991. {
  992. while(1)
  993. {
  994. struct udev_msg msg;
  995. udevice_t device;
  996. uep_t ep;
  997. /* receive message */
  998. if(rt_mq_recv(usb_mq, &msg, sizeof(struct udev_msg), RT_WAITING_FOREVER)
  999. != RT_EOK ) continue;
  1000. //RT_DEBUG_LOG(RT_DEBUG_USB, ("msg type %d\n", msg.type));
  1001. switch (msg.type)
  1002. {
  1003. case USB_MSG_SETUP_NOTIFY:
  1004. device = rt_usbd_find_device(msg.content.setup_msg.dcd);
  1005. if(device != RT_NULL)
  1006. _setup_request(device, (ureq_t)msg.content.setup_msg.packet);
  1007. else
  1008. rt_kprintf("invalid usb device\n");
  1009. break;
  1010. case USB_MSG_DATA_NOTIFY:
  1011. ep = rt_usbd_find_endpoint(device, msg.content.ep_msg.ep_addr);
  1012. if(ep != RT_NULL)
  1013. ep->handler(device, msg.content.ep_msg.size);
  1014. else
  1015. rt_kprintf("invalid endpoint\n");
  1016. break;
  1017. default:
  1018. break;
  1019. }
  1020. }
  1021. }
  1022. /**
  1023. * This function will post an message to usb message queue,
  1024. *
  1025. * @param msg the message to be posted
  1026. * @param size the size of the message .
  1027. *
  1028. * @return the error code, RT_EOK on successfully.
  1029. */
  1030. rt_err_t rt_usbd_post_event(struct udev_msg* msg, rt_size_t size)
  1031. {
  1032. RT_ASSERT(msg != RT_NULL);
  1033. /* send message to usb message queue */
  1034. return rt_mq_send(usb_mq, (void*)msg, size);
  1035. }
  1036. /**
  1037. * This function will initialize usb device thread.
  1038. *
  1039. * @return none.
  1040. *
  1041. */
  1042. rt_err_t rt_usbd_core_init(void)
  1043. {
  1044. rt_thread_t thread;
  1045. rt_list_init(&device_list);
  1046. /* create an usb message queue */
  1047. usb_mq = rt_mq_create("usbd", 32, 16, RT_IPC_FLAG_FIFO);
  1048. /* create usb device thread */
  1049. thread = rt_thread_create("usbd", rt_usbd_thread_entry, RT_NULL,
  1050. 2048, 8, 20);
  1051. if(thread != RT_NULL)
  1052. {
  1053. /* startup usb device thread */
  1054. rt_thread_startup(thread);
  1055. }
  1056. return RT_EOK;
  1057. }