fusb.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fusb.c
  15. * Date: 2022-02-11 13:33:11
  16. * LastEditTime: 2022-02-18 09:22:06
  17. * Description:  This file is for implmentation of USB user API
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.0 zhugengyu 2022/2/8 init commit
  23. */
  24. #include <string.h>
  25. #include "fdebug.h"
  26. #include "fsleep.h"
  27. #include "fusb_private.h"
  28. #include "fxhci.h"
  29. #define FUSB_DEBUG_TAG "FUSB"
  30. #define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  31. #define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  32. #define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  33. #define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  34. #define FUSB_DR_DESC FUsbGenerateReqType(FUSB_REQ_DEVICE_TO_HOST, FUSB_REQ_TYPE_STANDARD, FUSB_REQ_RECP_DEV)
  35. /*
  36. * Certain Lexar / Micron USB 2.0 disks will fail the FUsbGetDescriptor(FUSB_DESC_TYPE_CONFIG)
  37. * call due to timing issues. Work around this by making extra attempts on
  38. * failure.
  39. */
  40. #define FUSB_GET_DESCRIPTOR_RETRIES 3
  41. /**
  42. * @name: FUsbCfgInitialize
  43. * @msg: 初始化USB实例
  44. * @return {FError} 初始化错误码
  45. * @param {FUsb} *instance, USB实例
  46. * @param {const FUsbConfig} *input_config, USB输入配置
  47. * @note 在PCIE模式下,USB Hc实例在PCIE总线发现控制器后创建
  48. */
  49. FError FUsbCfgInitialize(FUsb *instance, const FUsbConfig *input_config)
  50. {
  51. FASSERT(instance && input_config);
  52. FError ret = FUSB_SUCCESS;
  53. if (input_config != &instance->config)
  54. {
  55. instance->config = *input_config;
  56. }
  57. instance->hc = NULL; /* non usb host attached */
  58. /* create usb hc instance, which will be add as the head of hc list */
  59. if (NULL == FXhciHcInit(instance, instance->config.base_addr))
  60. {
  61. ret = FUSB_ERR_ALLOCATE_FAIL;
  62. }
  63. if (FUSB_SUCCESS == ret)
  64. {
  65. instance->is_ready = FT_COMPONENT_IS_READY;
  66. }
  67. return ret;
  68. }
  69. /**
  70. * @name: FUsbDeInitialize
  71. * @msg: 去初始化USB实例
  72. * @return {*}
  73. * @param {FUsb} *instance, USB实例
  74. */
  75. void FUsbDeInitialize(FUsb *instance)
  76. {
  77. FASSERT(instance);
  78. if (FT_COMPONENT_IS_READY != instance->is_ready)
  79. {
  80. FUSB_ERROR("USB not ready !!!");
  81. return;
  82. }
  83. instance->is_ready = 0;
  84. return;
  85. }
  86. /**
  87. * @name: FUsbPoll
  88. * @msg: 轮询所有的USB控制器连接的所有设备, 更新设备拓扑
  89. * @return {*}
  90. * @param {FUsb} *instance, USB实例
  91. */
  92. void FUsbPoll(FUsb *instance)
  93. {
  94. FASSERT(instance);
  95. if (FT_COMPONENT_IS_READY != instance->is_ready)
  96. {
  97. FUSB_ERROR("USB not ready !!!");
  98. return;
  99. }
  100. if (FUsbPollPrepare)
  101. {
  102. FUsbPollPrepare(instance);
  103. }
  104. FUsbHc *controller = instance->hc;
  105. if (controller != NULL)
  106. {
  107. int i;
  108. for (i = 0; i < FUSB_MAX_DEV_NUM; i++)
  109. {
  110. if (controller->devices[i] != NULL)
  111. {
  112. controller->devices[i]->poll(controller->devices[i]);
  113. }
  114. }
  115. }
  116. return;
  117. }
  118. /**
  119. * @name: FUsbExit
  120. * @msg: 关闭所有的USB控制器,移除所有连接的设备
  121. * @return {*}
  122. * @param {FUsb} *instance, USB实例
  123. */
  124. void FUsbExit(FUsb *instance)
  125. {
  126. FASSERT(instance);
  127. if (FT_COMPONENT_IS_READY != instance->is_ready)
  128. {
  129. FUSB_ERROR("USB not ready !!!");
  130. return;
  131. }
  132. if (FUsbExitPrepare)
  133. {
  134. FUsbExitPrepare(instance);
  135. }
  136. FUsbHc *controller = instance->hc;
  137. if (controller != NULL)
  138. {
  139. FASSERT(controller->shutdown);
  140. controller->shutdown(controller);
  141. FUSB_FREE(instance, instance->hc);
  142. instance->hc = NULL;
  143. }
  144. return;
  145. }
  146. /**
  147. * @name: FUsbMempAllocate
  148. * @msg: 从USB内存池分配一块内存,并清零分配的空间
  149. * @return {void *} 分配的内存空间,如果失败返回NULL
  150. * @param {FUsb} *instance, USB实例
  151. * @param {size_t} size, 请求分配的字节数
  152. * @param {size_t} align, 分配空间的对齐方式,起始地址按align字节对齐
  153. */
  154. void *FUsbMempAllocate(FUsb *instance, size_t size, size_t align)
  155. {
  156. FASSERT(instance);
  157. void *result = NULL;
  158. FUsbMemAllocator *allocator = &(instance->config.allocator);
  159. if (allocator->malloc_align)
  160. {
  161. result = allocator->malloc_align(size, align);
  162. }
  163. return result;
  164. }
  165. /**
  166. * @name: FUsbMempFree
  167. * @msg: 释放从USB内存池分配的空间
  168. * @return {*}
  169. * @param {FUsb} *instance, USB实例
  170. * @param {void} *ptr, 待释放空间的首地址
  171. */
  172. void FUsbMempFree(FUsb *instance, void *ptr)
  173. {
  174. FASSERT(instance);
  175. FUsbMemAllocator *allocator = &(instance->config.allocator);
  176. if ((NULL != ptr) && (allocator->free))
  177. {
  178. allocator->free(ptr);
  179. }
  180. return;
  181. }
  182. #ifdef FMEMP_TAG_DEBUG
  183. void *FUsbMempAllocateTag(FUsb *instance, size_t size, size_t align, const char *file, unsigned long line, const char *msg)
  184. {
  185. FASSERT(instance);
  186. void *result = NULL;
  187. FMemp *memp = &instance->memp;
  188. if (FUSB_DEFAULT_ALIGN == align)
  189. {
  190. result = FMempCallocTag(memp, 1, size, file, line, msg);
  191. }
  192. else
  193. {
  194. result = FMempMallocAlignTag(memp, size, align, file, line, msg);
  195. if (NULL != result)
  196. {
  197. memset(result, 0, size);
  198. }
  199. }
  200. return result;
  201. }
  202. void FUsbMempFreeTag(FUsb *instance, void *ptr)
  203. {
  204. FASSERT(instance);
  205. if (NULL != ptr)
  206. {
  207. FMempFreeTag(&instance->memp, ptr);
  208. }
  209. return;
  210. }
  211. #endif
  212. /**
  213. * @name: FUsbAllocateHc
  214. * @msg: 创建USB控制器实例,添加到USB实例的Hc链表中
  215. * @return {*}
  216. * @param {FUsb} *instance, USB实例
  217. */
  218. FUsbHc *FUsbAllocateHc(FUsb *instance)
  219. {
  220. FASSERT(instance);
  221. FUsbHc *controller = FUSB_ALLOCATE(instance, sizeof(FUsbHc), FUSB_DEFAULT_ALIGN);
  222. instance->hc = controller;
  223. return controller;
  224. }
  225. /**
  226. * @name: FUsbDetachHc
  227. * @msg: 删除USB控制器实例,从USB实例的Hc链表中删去
  228. * @return {*}
  229. * @param {FUsbHc} *controller, USB控制器实例
  230. */
  231. void FUsbDetachHc(FUsbHc *controller)
  232. {
  233. if (controller == NULL)
  234. {
  235. return;
  236. }
  237. FUsb *instance = controller->usb;
  238. FUsbDetachDev(controller, 0); /* tear down root hub tree */
  239. return;
  240. }
  241. /**
  242. * @name: FUsbFindValidInitFunc
  243. * @msg: 寻找特定USB设备的初始化函数
  244. * @return {*}
  245. * @param {FUsb} *instance, USB实例
  246. * @param {FUsbDevIndex} *index, 特定USB设备的索引
  247. */
  248. static FUsbDevInitHandler FUsbFindValidInitFunc(FUsb *instance, const FUsbDevIndex *index)
  249. {
  250. FASSERT(instance);
  251. u32 loop;
  252. FUsbDevInitFunc *func;
  253. FUsbDevInitHandler handler = NULL;
  254. for (loop = 0; loop < instance->dev_init_num; loop++)
  255. {
  256. func = &instance->dev_init[loop];
  257. if ((index->category == func->index.category) &&
  258. (index->class == func->index.class) &&
  259. (index->sub_class == func->index.sub_class) &&
  260. (index->protocol == func->index.protocol))
  261. {
  262. handler = func->handler;
  263. }
  264. }
  265. return handler;
  266. }
  267. /**
  268. * @name: FUsbAssignDevInitFunc
  269. * @msg: 指定特定USB设备的初始化函数,供创建USB设备实例时使用
  270. * @return {FError} 处理返回错误码
  271. * @param {FUsb} *instance, USB实例
  272. * @param {FUsbDevIndex} *index, 特定USB设备的索引
  273. * @param {FUsbDevInitHandler} handler, 特定USB设备的初始化函数
  274. */
  275. FError FUsbAssignDevInitFunc(FUsb *instance, const FUsbDevIndex *index, FUsbDevInitHandler handler)
  276. {
  277. FASSERT(instance && index && handler);
  278. if (FUSB_MAX_DEV_TYPE_NUM == instance->dev_init_num)
  279. {
  280. return FUSB_ERR_INVALID_PARA;
  281. }
  282. if (NULL != FUsbFindValidInitFunc(instance, index))
  283. {
  284. FUSB_WARN("Will remove device init for class 0x%x", index->class);
  285. }
  286. instance->dev_init[instance->dev_init_num].index = *index;
  287. instance->dev_init[instance->dev_init_num].handler = handler;
  288. instance->dev_init_num++;
  289. return FUSB_SUCCESS;
  290. }
  291. /**
  292. * @name: FUsbInitDevEntry
  293. * @msg: 初始化USB设备
  294. * @return {*}
  295. * @param {FUsbHc} *controller, USB Hc
  296. * @param {int} slot_id,slot号
  297. */
  298. FUsbDev *FUsbInitDevEntry(FUsbHc *controller, int slot_id)
  299. {
  300. FASSERT(controller && controller->usb);
  301. FASSERT(FUSB_SLOT_ID_VALID(slot_id));
  302. FUsb *instace = controller->usb;
  303. FUsbDev *dev = FUSB_ALLOCATE(instace, sizeof(FUsbDev), FUSB_DEFAULT_ALIGN);
  304. if (NULL == dev)
  305. {
  306. FUSB_ERROR("No memory to allocate device structure .");
  307. return NULL;
  308. }
  309. if (controller->devices[slot_id] != NULL)
  310. {
  311. FUSB_WARN("Warning: device %d reassigned? ", slot_id);
  312. }
  313. controller->devices[slot_id] = dev;
  314. dev->controller = controller;
  315. dev->address = FUSB_NO_DEV_ADDR;
  316. dev->hub = FUSB_NO_HUB;
  317. dev->port = FUSB_NO_PORT;
  318. dev->init = FUsbNopDevInit;
  319. dev->init(controller->devices[slot_id]);
  320. return dev;
  321. }
  322. /**
  323. * @name: FUsbGetAllDevEntries
  324. * @msg: 获取USB控制器上连接的所有USB设备实例
  325. * @return {size_t} 实际获取的USB设备实例数目
  326. * @param {FUsbHc} *controller, USB控制器实例
  327. * @param {FUsbDev} *devs, 放置USB设备实例的缓冲区
  328. * @param {size_t} max_dev_num, 最多可以获取的USB设备实例数目
  329. */
  330. size_t FUsbGetAllDevEntries(FUsbHc *controller, FUsbDev *devs[], size_t max_dev_num)
  331. {
  332. FASSERT(controller && devs && max_dev_num > 0);
  333. size_t loop;
  334. size_t num = 0;
  335. /* loop over all dev address in case there are holes */
  336. for (loop = 0; loop < FUSB_MAX_DEV_NUM; loop++)
  337. {
  338. if (NULL != controller->devices[loop])
  339. {
  340. devs[num] = controller->devices[loop];
  341. num++;
  342. /* get at most max_dev_num device entry before exit */
  343. if (num >= max_dev_num)
  344. {
  345. break;
  346. }
  347. }
  348. }
  349. return num;
  350. }
  351. /**
  352. * @name: FUsbDecodeMaxPacketSz0
  353. * @msg: 根据USB设备速度,选择最大包长度
  354. * @return {*} 输出最大包长度
  355. * @param {FUsbSpeed} speed, USB设备速度类型
  356. * @param {u8} bMaxPacketSize0, 输入最大包长度
  357. */
  358. int FUsbDecodeMaxPacketSz0(FUsbSpeed speed, u8 bMaxPacketSize0)
  359. {
  360. switch (speed)
  361. {
  362. case FUSB_LOW_SPEED:
  363. if (bMaxPacketSize0 != 8)
  364. {
  365. FUSB_ERROR("Invalid MPS0: 0x%02x ", bMaxPacketSize0);
  366. bMaxPacketSize0 = 8;
  367. }
  368. return bMaxPacketSize0;
  369. case FUSB_FULL_SPEED:
  370. switch (bMaxPacketSize0)
  371. {
  372. case 8:
  373. case 16:
  374. case 32:
  375. case 64:
  376. return bMaxPacketSize0;
  377. default:
  378. FUSB_ERROR("Invalid MPS0: 0x%02x ", bMaxPacketSize0);
  379. return 8;
  380. }
  381. case FUSB_HIGH_SPEED:
  382. if (bMaxPacketSize0 != 64)
  383. {
  384. FUSB_ERROR("Invalid MPS0: 0x%02x ", bMaxPacketSize0);
  385. bMaxPacketSize0 = 64;
  386. }
  387. return bMaxPacketSize0;
  388. case FUSB_SUPER_SPEED:
  389. /* Intentional fallthrough */
  390. case FUSB_SUPER_SPEED_PLUS:
  391. if (bMaxPacketSize0 != 9)
  392. {
  393. FUSB_ERROR("Invalid MPS0: 0x%02x ", bMaxPacketSize0);
  394. bMaxPacketSize0 = 9;
  395. }
  396. return 1 << bMaxPacketSize0;
  397. default:
  398. return 8;
  399. }
  400. }
  401. /**
  402. * @name: FUsbSetFeature
  403. * @msg: 标准USB主机请求,使能设备/接口/端点的某个特性
  404. * @return {FUsbTransCode} 控制传输的返回值,小于0表示失败,大于0表示成功传输的字节数目
  405. * @param {FUsbDev} *dev, USB设备实例
  406. * @param {int} endp, 设备号(0x00)/接口号/端点号
  407. * @param {int} feature, 待使能的特性
  408. * @param {int} rtype, 请求类型,由FUsbGenerateReqType生成
  409. */
  410. FUsbTransCode FUsbSetFeature(FUsbDev *dev, int endp, int feature, int rtype)
  411. {
  412. FASSERT(dev && dev->controller && dev->controller->control);
  413. FUsbDevReq dr;
  414. dr.bmRequestType = rtype;
  415. dr.data_dir = FUSB_REQ_HOST_TO_DEVICE;
  416. dr.bRequest = FUSB_SET_FEATURE;
  417. dr.wValue = feature;
  418. dr.wIndex = endp;
  419. dr.wLength = 0;
  420. return dev->controller->control(dev, FUSB_OUT, sizeof(dr), &dr, 0, NULL);
  421. }
  422. /**
  423. * @name: FUsbGetStatus
  424. * @msg: 标准USB主机请求,获取设备/接口/端点的状态
  425. * @return {FUsbTransCode} 控制传输的返回值,小于0表示失败,大于0表示成功传输的字节数目
  426. * @param {FUsbDev} *dev, USB设备实例
  427. * @param {int} intf,设备号(0x00)/接口号/端点号
  428. * @param {int} rtype, 请求类型,由FUsbGenerateReqType生成
  429. * @param {int} len, Data Stage的数据长度
  430. * @param {void} *data, Data Stage的数据缓冲区
  431. */
  432. FUsbTransCode FUsbGetStatus(FUsbDev *dev, int intf, int rtype, int len, void *data)
  433. {
  434. FASSERT(dev && dev->controller && dev->controller->control);
  435. FUsbDevReq dr;
  436. dr.bmRequestType = rtype;
  437. dr.data_dir = FUSB_REQ_DEVICE_TO_HOST;
  438. dr.bRequest = FUSB_GET_STATUS;
  439. dr.wValue = 0;
  440. dr.wIndex = intf;
  441. dr.wLength = len;
  442. return dev->controller->control(dev, FUSB_IN, sizeof(dr), &dr, len, data);
  443. }
  444. /**
  445. * @name: FUsbGetDescriptor
  446. * @msg: 标准USB主机请求,获取指定描述符
  447. * @return {FUsbTransCode} 控制传输的返回值,小于0表示失败,大于0表示成功传输的字节数目
  448. * @param {FUsbDev} *dev, USB设备实例
  449. * @param {int} rtype, 请求类型,由FUsbGenerateReqType生成
  450. * @param {FUsbDescriptorType} desc_type, 描述符类型
  451. * @param {int} desc_idx, 描述符索引
  452. * @param {void} *data, Data Stage的数据缓冲区
  453. * @param {size_t} len, Data Stage的数据长度
  454. */
  455. FUsbTransCode FUsbGetDescriptor(FUsbDev *dev, int rtype, FUsbDescriptorType desc_type, int desc_idx, void *data,
  456. size_t len)
  457. {
  458. FASSERT(dev && dev->controller && dev->controller->control);
  459. FUsbDevReq dr;
  460. int fail_tries = 0;
  461. FUsbTransCode ret = FUSB_CC_ZERO_BYTES;
  462. while (fail_tries++ < FUSB_GET_DESCRIPTOR_RETRIES)
  463. {
  464. dr.bmRequestType = rtype;
  465. dr.bRequest = FUSB_GET_DESCRIPTOR;
  466. dr.wValue = desc_type << 8 | desc_idx;
  467. dr.wIndex = 0;
  468. dr.wLength = len;
  469. ret = dev->controller->control(dev, FUSB_IN,
  470. sizeof(dr), &dr, len, data);
  471. if (ret == (int)len)
  472. {
  473. break;
  474. }
  475. fsleep_microsec(10);
  476. }
  477. return ret;
  478. }
  479. /**
  480. * @name: FUsbGetStringDescriptor
  481. * @msg: USB主机请求,获取字符串描述符
  482. * @return {int} 控制传输的返回值,小于0表示失败,大于0表示成功传输的字节数目
  483. * @param {FUsbDev} *dev, USB设备实例
  484. * @param {int} rtype, 请求类型,由FUsbGenerateReqType生成
  485. * @param {int} desc_type, 描述符类型
  486. * @param {int} desc_idx, 描述符索引
  487. * @param {int} lang_id, 语言类型
  488. * @param {void} *data, Data Stage的数据缓冲区
  489. * @param {size_t} len, Data Stage的数据长度
  490. */
  491. FUsbTransCode FUsbGetStringDescriptor(FUsbDev *dev, int rtype, FUsbDescriptorType desc_type, int desc_idx, int lang_id, void *data, size_t len)
  492. {
  493. FASSERT(dev && dev->controller && dev->controller->control);
  494. FUsbDevReq dr;
  495. int fail_tries = 0;
  496. FUsbTransCode ret = FUSB_CC_ZERO_BYTES;
  497. while (fail_tries++ < FUSB_GET_DESCRIPTOR_RETRIES)
  498. {
  499. dr.bmRequestType = rtype;
  500. dr.bRequest = FUSB_GET_DESCRIPTOR;
  501. dr.wValue = desc_type << 8 | desc_idx;
  502. dr.wIndex = lang_id;
  503. dr.wLength = len;
  504. ret = dev->controller->control(dev, FUSB_IN, sizeof(dr), &dr, len, data);
  505. if (ret == (int)len)
  506. {
  507. break;
  508. }
  509. fsleep_microsec(10);
  510. }
  511. return ret;
  512. }
  513. /**
  514. * @name: FUsbSetConfiguration
  515. * @msg: 标准USB主机请求,设置配置值
  516. * @return {FUsbTransCode} 控制传输的返回值,小于0表示失败,大于0表示成功传输的字节数目
  517. * @param {FUsbDev} *dev, USB设备实例
  518. */
  519. FUsbTransCode FUsbSetConfiguration(FUsbDev *dev)
  520. {
  521. FASSERT(dev && dev->controller && dev->controller->control);
  522. FUsbDevReq dr;
  523. dr.bmRequestType = 0;
  524. dr.bRequest = FUSB_SET_CONFIGURATION;
  525. dr.wValue = dev->configuration->bConfigurationValue;
  526. dr.wIndex = 0;
  527. dr.wLength = 0;
  528. return dev->controller->control(dev, FUSB_OUT, sizeof(dr), &dr, 0, NULL);
  529. }
  530. /**
  531. * @name: FUsbClearFeature
  532. * @msg: 标准USB主机请求,去使能设备/接口/端点的某个特性
  533. * @return {FUsbTransCode} 控制传输的返回值,小于0表示失败,大于0表示成功传输的字节数目
  534. * @param {FUsbDev} *dev, USB设备实例
  535. * @param {int} endp, 设备号(0x00)/接口号/端点号
  536. * @param {int} feature,待去除的特性
  537. * @param {int} rtype, 请求类型,由FUsbGenerateReqType生成
  538. */
  539. FUsbTransCode FUsbClearFeature(FUsbDev *dev, int endp, int feature, int rtype)
  540. {
  541. FASSERT(dev && dev->controller && dev->controller->control);
  542. FUsbDevReq dr;
  543. dr.bmRequestType = rtype;
  544. dr.data_dir = FUSB_REQ_HOST_TO_DEVICE;
  545. dr.bRequest = FUSB_CLEAR_FEATURE;
  546. dr.wValue = feature;
  547. dr.wIndex = endp;
  548. dr.wLength = 0;
  549. return dev->controller->control(dev, FUSB_OUT, sizeof(dr), &dr, 0, NULL) < 0;
  550. }
  551. /**
  552. * @name: FUsbSpeedtoDefaultMaxPacketSz
  553. * @msg: 根据设备速度获取最大包长度
  554. * @return {int} 最大包长度
  555. * @param {FUsbSpeed} speed, 设备速度类型
  556. */
  557. int FUsbSpeedtoDefaultMaxPacketSz(FUsbSpeed speed)
  558. {
  559. switch (speed)
  560. {
  561. case FUSB_LOW_SPEED:
  562. return 8;
  563. case FUSB_FULL_SPEED:
  564. case FUSB_HIGH_SPEED:
  565. return 64;
  566. case FUSB_SUPER_SPEED:
  567. /* Intentional fallthrough */
  568. case FUSB_SUPER_SPEED_PLUS:
  569. default:
  570. return 512;
  571. }
  572. }
  573. /**
  574. * @name: FUsbDecodeInterval
  575. * @msg: 获取USB传输间隔时间
  576. * @return {int} 传输间隔时间, 0表示失败
  577. * @param {FUsbSpeed} speed, USB设备速度类型
  578. * @param {FUsbEpType} type, 端点类型
  579. * @param {unsigned char} bInterval, 设置的间隔时间
  580. */
  581. static int FUsbDecodeInterval(FUsbSpeed speed, const FUsbEpType type, const unsigned char bInterval)
  582. {
  583. /* Normalize bInterval to log2 of microframes */
  584. #define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1)
  585. switch (speed)
  586. {
  587. case FUSB_LOW_SPEED:
  588. switch (type)
  589. {
  590. case FUSB_ISOCHRONOUS_EP:
  591. case FUSB_INTERRUPT_EP:
  592. return LOG2(bInterval) + 3;
  593. default:
  594. return 0;
  595. }
  596. case FUSB_FULL_SPEED:
  597. switch (type)
  598. {
  599. case FUSB_ISOCHRONOUS_EP:
  600. return (bInterval - 1) + 3;
  601. case FUSB_INTERRUPT_EP:
  602. return LOG2(bInterval) + 3;
  603. default:
  604. return 0;
  605. }
  606. case FUSB_HIGH_SPEED:
  607. switch (type)
  608. {
  609. case FUSB_ISOCHRONOUS_EP:
  610. case FUSB_INTERRUPT_EP:
  611. return bInterval - 1;
  612. default:
  613. return LOG2(bInterval);
  614. }
  615. case FUSB_SUPER_SPEED:
  616. /* Intentional fallthrough */
  617. case FUSB_SUPER_SPEED_PLUS:
  618. switch (type)
  619. {
  620. case FUSB_ISOCHRONOUS_EP:
  621. case FUSB_INTERRUPT_EP:
  622. return bInterval - 1;
  623. default:
  624. return 0;
  625. }
  626. default:
  627. return 0;
  628. }
  629. #undef LOG2
  630. }
  631. /**
  632. * @name: FUsbSetAddress
  633. * @msg: 获取USB设备的描述符信息,根据USB设备类型完成配置和初始化
  634. * @return {FUsbDevAddr} 为USB设备分配的地址,-1表示USB设备初始化失败
  635. * @param {FUsbHc} *controller, USB控制器实例
  636. * @param {FUsbSpeed} speed, USB设备速度类型
  637. * @param {int} hubport, USB设备连接的Hub端口号
  638. * @param {int} hubaddr, USB设备连接Hub的地址
  639. */
  640. static FUsbDevAddr FUsbSetAddress(FUsbHc *controller, FUsbSpeed speed, int hubport, int hubaddr)
  641. {
  642. FASSERT(controller);
  643. FUsbDev *dev = controller->set_address(controller, speed,
  644. hubport, hubaddr);
  645. FUsbDevIndex index;
  646. FUsbDevInitHandler init_handler = NULL;
  647. FUsb *instace = controller->usb;
  648. FASSERT(instace);
  649. if (NULL == dev)
  650. {
  651. FUSB_INFO("Set address failed.");
  652. return FUSB_NO_DEV_ADDR;
  653. }
  654. FASSERT(NULL == dev->descriptor);
  655. dev->descriptor = FUSB_ALLOCATE(instace, sizeof(*dev->descriptor), FUSB_DEFAULT_ALIGN);
  656. if ((NULL == dev->descriptor) || FUsbGetDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_DEVICE, 0,
  657. dev->descriptor, sizeof(*dev->descriptor)) != sizeof(*dev->descriptor))
  658. {
  659. FUSB_INFO("FUsbGetDescriptor(FUSB_DESC_TYPE_DEVICE) failed.");
  660. FUsbDetachDev(controller, dev->address);
  661. return FUSB_NO_DEV_ADDR;
  662. }
  663. FUSB_INFO("Found device (0x%04x:0x%04x, USB %x.%x, MPS0: %d) ",
  664. dev->descriptor->idVendor, dev->descriptor->idProduct,
  665. dev->descriptor->bcdUSB >> 8, dev->descriptor->bcdUSB & 0xff,
  666. dev->endpoints[0].maxpacketsize);
  667. FUSB_INFO("Device has %d configurations.",
  668. dev->descriptor->bNumConfigurations);
  669. if (dev->descriptor->bNumConfigurations == 0)
  670. {
  671. /* device isn't usable */
  672. FUSB_INFO("No usable configuration!");
  673. FUsbDetachDev(controller, dev->address);
  674. return FUSB_NO_DEV_ADDR;
  675. }
  676. u16 buf[2];
  677. if (FUsbGetDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_CONFIG, 0, buf, sizeof(buf)) != sizeof(buf))
  678. {
  679. FUSB_INFO("First FUsbGetDescriptor(FUSB_DESC_TYPE_CONFIG) failed.");
  680. FUsbDetachDev(controller, dev->address);
  681. return FUSB_NO_DEV_ADDR;
  682. }
  683. /* workaround for some USB devices: wait until they're ready, or
  684. * they send a NAK when they're not allowed to do. 1ms is enough */
  685. fsleep_millisec(1);
  686. FASSERT(NULL == dev->configuration);
  687. dev->configuration = FUSB_ALLOCATE(instace, buf[1], FUSB_DEFAULT_ALIGN);
  688. if (NULL == dev->configuration)
  689. {
  690. FUSB_INFO("Could not allocate %d bytes for FUSB_DESC_TYPE_CONFIG.", buf[1]);
  691. FUsbDetachDev(controller, dev->address);
  692. return FUSB_NO_DEV_ADDR;
  693. }
  694. if (FUsbGetDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_CONFIG, 0, dev->configuration,
  695. buf[1]) != buf[1])
  696. {
  697. FUSB_INFO("FUsbGetDescriptor(FUSB_DESC_TYPE_CONFIG) failed.");
  698. FUsbDetachDev(controller, dev->address);
  699. return FUSB_NO_DEV_ADDR;
  700. }
  701. FUsbConfigurationDescriptor *cd = dev->configuration;
  702. if (cd->wTotalLength != buf[1])
  703. {
  704. FUSB_INFO("Configuration descriptor size changed, aborting.");
  705. FUsbDetachDev(controller, dev->address);
  706. return FUSB_NO_DEV_ADDR;
  707. }
  708. /*
  709. * If the device is not well known (ifnum == -1), we use the first
  710. * interface we encounter, as there was no need to implement something
  711. * else for the time being. If you need it, see the SetInterface and
  712. * GetInterface functions in the USB specification and set it yourself.
  713. */
  714. FUSB_INFO("Device has %x interfaces.", cd->bNumInterfaces);
  715. u8 *end = (void *)dev->configuration + cd->wTotalLength;
  716. FUsbInterfaceDescriptor *intf;
  717. u8 *ptr;
  718. /* Find our interface (or the first good one if we don't know) */
  719. for (ptr = (void *)dev->configuration + sizeof(*cd);; ptr += ptr[0])
  720. {
  721. if (ptr + 2 > end || !ptr[0] || ptr + ptr[0] > end)
  722. {
  723. FUSB_INFO("Couldn't find usable FUSB_DESC_TYPE_INTERFACE.");
  724. FUsbDetachDev(controller, dev->address);
  725. return FUSB_NO_DEV_ADDR;
  726. }
  727. if (ptr[1] != FUSB_DESC_TYPE_INTERFACE)
  728. {
  729. continue;
  730. }
  731. intf = (void *)ptr;
  732. if (intf->bLength != sizeof(*intf))
  733. {
  734. FUSB_INFO("Skipping broken FUSB_DESC_TYPE_INTERFACE.");
  735. continue;
  736. }
  737. FUSB_INFO("Interface %d: class 0x%x, sub 0x%x. proto 0x%x.",
  738. intf->bInterfaceNumber, intf->bInterfaceClass,
  739. intf->bInterfaceSubClass, intf->bInterfaceProtocol);
  740. ptr += sizeof(*intf);
  741. break;
  742. }
  743. /* Gather up all endpoints belonging to this interface */
  744. dev->num_endp = 1;
  745. for (; ptr + 2 <= end && ptr[0] && ptr + ptr[0] <= end; ptr += ptr[0])
  746. {
  747. if (ptr[1] == FUSB_DESC_TYPE_INTERFACE || ptr[1] == FUSB_DESC_TYPE_CONFIG ||
  748. (size_t)dev->num_endp >= ARRAY_SIZE(dev->endpoints))
  749. {
  750. break;
  751. }
  752. if (ptr[1] != FUSB_DESC_TYPE_ENDPOINT)
  753. {
  754. continue;
  755. }
  756. FUsbEndpointDescriptor *desc = (void *)ptr;
  757. static const char *transfertypes[4] =
  758. {
  759. "control", "isochronous", "bulk", "interrupt"
  760. };
  761. FUSB_INFO(" #Endpoint %d (%s), max packet size %x, type %s ",
  762. desc->bEndpointAddress & 0x7f,
  763. (desc->bEndpointAddress & 0x80) ? "in" : "out",
  764. desc->wMaxPacketSize,
  765. transfertypes[desc->bmAttributes & 0x3]);
  766. FUsbEndpoint *ep = &dev->endpoints[dev->num_endp++];
  767. ep->dev = dev;
  768. ep->endpoint = desc->bEndpointAddress;
  769. ep->toggle = 0;
  770. ep->maxpacketsize = desc->wMaxPacketSize;
  771. ep->direction = (desc->bEndpointAddress & 0x80) ? FUSB_IN : FUSB_OUT;
  772. ep->type = desc->bmAttributes & 0x3;
  773. ep->interval = FUsbDecodeInterval(dev->speed, ep->type,
  774. desc->bInterval);
  775. }
  776. if ((controller->finish_device_config &&
  777. controller->finish_device_config(dev)) ||
  778. FUsbSetConfiguration(dev) < 0)
  779. {
  780. FUSB_INFO("Could not finalize device configuration. ");
  781. FUsbDetachDev(controller, dev->address);
  782. return FUSB_NO_DEV_ADDR;
  783. }
  784. int class = dev->descriptor->bDeviceClass;
  785. if (class == 0)
  786. {
  787. class = intf->bInterfaceClass;
  788. }
  789. switch (class)
  790. {
  791. case FUSB_AUDIO_DEVICE:
  792. FUSB_INFO("Audio Class ");
  793. break;
  794. case FUSB_COMM_DEVICE:
  795. FUSB_INFO("Communication Class ");
  796. break;
  797. case FUSB_HID_DEVICE:
  798. FUSB_INFO("HID Class ");
  799. break;
  800. case FUSB_PHYSICAL_DEVICE:
  801. FUSB_INFO("Physical Class");
  802. break;
  803. case FUSB_IMAGE_DEVICE:
  804. FUSB_INFO("Camera Class ");
  805. break;
  806. case FUSB_PRINTER_DEVICE:
  807. FUSB_INFO("Printer Class");
  808. break;
  809. case FUSB_MASS_STORAGE_DEVICE:
  810. FUSB_INFO("Mass Storage Class ");
  811. break;
  812. case FUSB_HUB_DEVICE:
  813. FUSB_INFO("Hub Class ");
  814. break;
  815. default:
  816. FUSB_ERROR("Unsupported Class %x ", class);
  817. break;
  818. }
  819. index.category = FUSB_STANDARD_INTERFACE;
  820. index.class = class;
  821. index.sub_class = intf->bInterfaceSubClass;
  822. index.protocol = intf->bInterfaceProtocol;
  823. FUSB_INFO("Class: 0x%x sub-class: 0x%x, protocol: 0x%x.",
  824. index.class, index.sub_class, index.protocol);
  825. init_handler = FUsbFindValidInitFunc(instace, &index);
  826. if (NULL != init_handler)
  827. {
  828. dev->init = init_handler;
  829. dev->class = (FUsbDevClass)class;
  830. }
  831. else
  832. {
  833. FUSB_WARN("Init function for the device not found, use generic one instead !!!");
  834. dev->init = FUsbGenericDevInit;
  835. }
  836. return dev->address;
  837. }
  838. /**
  839. * @name: FUsbDetachDev
  840. * @msg: 从USB主机移除指定USB设备(USB设备驱动使用)
  841. * @return {*}
  842. * @param {FUsbHc} *controller, USB控制器实例
  843. * @param {int} devno, USB设备索引
  844. * @note Should be called by the hub drivers whenever a physical detach occurs
  845. * and can be called by USB class drivers if they are unsatisfied with a
  846. * malfunctioning device.
  847. */
  848. void FUsbDetachDev(FUsbHc *controller, int devno)
  849. {
  850. FUsb *instace = controller->usb;
  851. /* check if device exists, as we may have
  852. been called yet by the USB class driver */
  853. if (controller->devices[devno])
  854. {
  855. controller->devices[devno]->destroy(controller->devices[devno]);
  856. if (controller->destroy_device)
  857. {
  858. controller->destroy_device(controller, devno);
  859. }
  860. FUSB_FREE(instace, controller->devices[devno]->descriptor);
  861. controller->devices[devno]->descriptor = NULL;
  862. FUSB_FREE(instace, controller->devices[devno]->configuration);
  863. controller->devices[devno]->configuration = NULL;
  864. /* Tear down the device itself *after* destroy_device()
  865. * has had a chance to interrogate it. */
  866. FUSB_FREE(instace, controller->devices[devno]);
  867. controller->devices[devno] = NULL;
  868. }
  869. return;
  870. }
  871. /**
  872. * @name: FUsbAttachDev
  873. * @msg: 向USB主机添加USB设备(USB设备驱动使用)
  874. * @return {FUsbDevAddr} 分配的USB设备地址
  875. * @param {FUsbHc} *controller, USB控制器实例
  876. * @param {int} hubaddress, Hub地址
  877. * @param {int} port, 连接的Port
  878. * @param {FUsbSpeed} speed, USB设备的设置速度类型
  879. */
  880. FUsbDevAddr FUsbAttachDev(FUsbHc *controller, int hubaddress, int port, FUsbSpeed speed)
  881. {
  882. static const char *speeds[] = {"FULL", "LOW", "HIGH", "SUPER", "ULTRA-SUPER"};
  883. FUSB_INFO("%s-Speed Device ", ((size_t)speed < sizeof(speeds) / sizeof(char *))
  884. ? speeds[speed]
  885. : "Unkonwn");
  886. FUsbDevAddr newdev = FUsbSetAddress(controller, speed, port, hubaddress);
  887. if (newdev == FUSB_NO_DEV_ADDR)
  888. {
  889. return FUSB_NO_DEV_ADDR;
  890. }
  891. FUsbDev *newdev_t = controller->devices[newdev];
  892. /* determine responsible driver - current done in set_address */
  893. newdev_t->init(newdev_t);
  894. /* init() may have called FUsbDetachDev() yet, so check */
  895. return controller->devices[newdev] ? newdev : FUSB_NO_DEV_ADDR;
  896. }
  897. /**
  898. * @name: FUsbGenericDestory
  899. * @msg: 一般USB设备去初始化函数
  900. * @return {*}
  901. * @param {FUsbDev} *dev, USB设备实例
  902. */
  903. static void FUsbGenericDestory(FUsbDev *dev)
  904. {
  905. if (FUsbGenericRemove)
  906. {
  907. FUsbGenericRemove(dev);
  908. }
  909. return;
  910. }
  911. /**
  912. * @name: FUsbGenericDevInit
  913. * @msg: 默认的USB设备初始化函数
  914. * @return {*}
  915. * @param {FUsbDev} *dev, USB设备实例
  916. */
  917. void FUsbGenericDevInit(FUsbDev *dev)
  918. {
  919. dev->data = NULL;
  920. dev->destroy = FUsbGenericDestory;
  921. if (FUsbGenericCreate)
  922. {
  923. FUsbGenericCreate(dev);
  924. }
  925. if (dev->data == NULL)
  926. {
  927. FUSB_INFO("Detaching device not used by payload.");
  928. FUsbDetachDev(dev->controller, dev->address);
  929. }
  930. return;
  931. }