fusb_dev.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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_dev.c
  15. * Date: 2022-02-11 13:33:11
  16. * LastEditTime: 2022-02-18 09:18:45
  17. * Description:  This files is for USB device function implementation
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.0 Zhugengyu 2022/2/7 init commit
  23. */
  24. #include <string.h>
  25. #include "fdebug.h"
  26. #include "fusb_private.h"
  27. #define FUSB_DEBUG_TAG "FUSB-DEV"
  28. #define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  29. #define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  30. #define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  31. #define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
  32. #define FUSB_DR_DESC FUsbGenerateReqType(FUSB_REQ_DEVICE_TO_HOST, FUSB_REQ_TYPE_STANDARD, FUSB_REQ_RECP_DEV)
  33. #define FUSB_SKIP_BYTES(desc, bytes) ((FUsbDescriptor *) ((u8 *) (desc) + (bytes)))
  34. #define FUSB_CONFIG_DESC_SIZE 512 /* best guess */
  35. static void FUsbNopDevDestory(FUsbDev *dev)
  36. {
  37. FUsbNopDevInit(dev);
  38. dev->address = FUSB_NO_DEV_ADDR;
  39. dev->hub = FUSB_NO_HUB;
  40. dev->port = FUSB_NO_PORT;
  41. }
  42. static void FUsbNopDevPoll(FUsbDev *dev)
  43. {
  44. return;
  45. }
  46. /**
  47. * @name: FUsbNopDevInit
  48. * @msg: 默认的USB设备初始化函数
  49. * @return {*}
  50. * @param {FUsbDev} *dev, USB设备实例
  51. */
  52. void FUsbNopDevInit(FUsbDev *dev)
  53. {
  54. dev->descriptor = NULL;
  55. dev->configuration = NULL;
  56. dev->destroy = FUsbNopDevDestory;
  57. dev->poll = FUsbNopDevPoll;
  58. }
  59. static inline boolean FUsbParserIsValid(const FUsbConfigParser *parser)
  60. {
  61. FASSERT(parser);
  62. return parser->is_valid;
  63. }
  64. static FError FUsbParserDescriptor(FUsbConfigParser *parser)
  65. {
  66. FASSERT(parser && parser->buf);
  67. const FUsbDescriptor *cur_pos = parser->buf;
  68. const FUsbDescriptor *desc_end;
  69. FUsbDescriptorType last_desc_type = FUSB_DESC_TYPE_NONE;
  70. FUsbDescriptorType desc_type;
  71. u8 desc_len, exp_len, alt_len;
  72. FError ret = FUSB_SUCCESS;
  73. while (FUSB_SKIP_BYTES(cur_pos, FUSB_DESCRIPTOR_HEADER_SIZE) < parser->end_pos)
  74. {
  75. /* get length and type of descriptor */
  76. desc_len = cur_pos->header.len;
  77. desc_type = cur_pos->header.type;
  78. desc_end = FUSB_SKIP_BYTES(cur_pos, desc_len);
  79. if (desc_end > parser->end_pos)
  80. {
  81. FUSB_ERROR("Parse descriptor out of boundary !!!");
  82. parser->err_pos = cur_pos;
  83. ret = FUSB_ERR_DESC_PARSE_ERR;
  84. goto err_handle;
  85. }
  86. exp_len = 0;
  87. alt_len = 0;
  88. switch (desc_type)
  89. {
  90. case FUSB_DESC_TYPE_CONFIG:
  91. if (FUSB_DESC_TYPE_NONE != last_desc_type)
  92. {
  93. FUSB_ERROR("Configuration descriptor must be the first !!!");
  94. parser->err_pos = cur_pos;
  95. ret = FUSB_ERR_DESC_PARSE_ERR;
  96. goto err_handle;
  97. }
  98. exp_len = sizeof(FUsbConfigurationDescriptor);
  99. break;
  100. case FUSB_DESC_TYPE_INTERFACE:
  101. if (FUSB_DESC_TYPE_NONE == last_desc_type)
  102. {
  103. FUSB_ERROR("Interface descriptor must not be the first !!!");
  104. parser->err_pos = cur_pos;
  105. ret = FUSB_ERR_DESC_PARSE_ERR;
  106. goto err_handle;
  107. }
  108. exp_len = sizeof(FUsbInterfaceDescriptor);
  109. break;
  110. case FUSB_DESC_TYPE_ENDPOINT:
  111. if ((FUSB_DESC_TYPE_NONE == last_desc_type) ||
  112. (FUSB_DESC_TYPE_CONFIG == last_desc_type))
  113. {
  114. FUSB_ERROR("Endpoint descriptor must follow interface descriptor !!!");
  115. parser->err_pos = cur_pos;
  116. ret = FUSB_ERR_DESC_PARSE_ERR;
  117. goto err_handle;
  118. }
  119. break;
  120. default:
  121. FUSB_DEBUG("Descriptor %d not handled !!!", desc_type);
  122. break;
  123. }
  124. if (((exp_len != 0) && (desc_len != exp_len)) &&
  125. ((alt_len == 0) || (desc_len != alt_len)))
  126. {
  127. FUSB_ERROR("Descriptor %d invalid !!!", desc_type);
  128. parser->err_pos = cur_pos;
  129. ret = FUSB_ERR_DESC_PARSE_ERR;
  130. goto err_handle;
  131. }
  132. last_desc_type = desc_type;
  133. cur_pos = desc_end;
  134. }
  135. if (cur_pos != parser->end_pos)
  136. {
  137. parser->err_pos = cur_pos;
  138. ret = FUSB_ERR_DESC_PARSE_ERR;
  139. goto err_handle;
  140. }
  141. err_handle:
  142. if (FUSB_SUCCESS == ret)
  143. {
  144. parser->is_valid = TRUE;
  145. }
  146. return ret;
  147. }
  148. /**
  149. * @name: FUsbSetupConfigParser
  150. * @msg: 配置USB配置描述符解析器
  151. * @return {*}
  152. * @param {FUsbDev} *dev, USB设备实例
  153. * @param {void} *buf, 配置描述符缓冲区
  154. * @param {u32} buf_len, 配置描述符缓冲区长度
  155. */
  156. FError FUsbSetupConfigParser(FUsbDev *dev, const void *buf, u32 buf_len)
  157. {
  158. FASSERT(dev && buf && (buf_len > 0));
  159. const FUsbConfigurationDescriptor *config_desc;
  160. FUsbConfigParser *parser = &dev->config_parser;
  161. memset(parser, 0, sizeof(*parser));
  162. parser->buf = buf;
  163. parser->buf_len = buf_len;
  164. parser->is_valid = FALSE;
  165. parser->end_pos = FUSB_SKIP_BYTES(parser->buf, parser->buf_len);
  166. parser->next_pos = parser->buf;
  167. parser->cur_desc = NULL;
  168. parser->err_pos = parser->buf;
  169. if ((parser->buf_len < sizeof(u32)) || (parser->buf_len > FUSB_CONFIG_DESC_SIZE))
  170. {
  171. FUSB_ERROR("Invalid buffer length !!!");
  172. return FUSB_ERR_INVALID_DATA;
  173. }
  174. /* input buffer must start with config desc */
  175. config_desc = (FUsbConfigurationDescriptor *)parser->buf;
  176. if ((config_desc->bLength != sizeof(FUsbConfigurationDescriptor)) ||
  177. (config_desc->bDescriptorType != FUSB_DESC_TYPE_CONFIG) ||
  178. (config_desc->wTotalLength > parser->buf_len))
  179. {
  180. FUSB_ERROR("Invalid configuration descriptor !!!");
  181. return FUSB_ERR_INVALID_DATA;
  182. }
  183. /* adjust end position */
  184. if (config_desc->wTotalLength < parser->buf_len)
  185. {
  186. parser->end_pos = FUSB_SKIP_BYTES(parser->buf, config_desc->wTotalLength);
  187. }
  188. return FUsbParserDescriptor(parser);
  189. }
  190. /**
  191. * @name: FUsbRevokeConfigParser
  192. * @msg: 去初始化USB配置描述符解析器
  193. * @return {*}
  194. * @param {FUsbDev} *dev, USB设备实例
  195. */
  196. void FUsbRevokeConfigParser(FUsbDev *dev)
  197. {
  198. FASSERT(dev);
  199. memset(&dev->config_parser, 0, sizeof(dev->config_parser));
  200. return;
  201. }
  202. /**
  203. * @name: FUsbGetDescriptorFromParser
  204. * @msg: 从配置描述符解析器中获取指定类型的描述符(端点描述符/接口描述符)
  205. * @return {const FUsbDescriptor *} 获取的描述符
  206. * @param {FUsbConfigParser} *parser, 配置描述符解析器
  207. * @param {FUsbDescriptorType} type, 获取描述符的类型
  208. */
  209. const FUsbDescriptor *FUsbGetDescriptorFromParser(FUsbConfigParser *parser, FUsbDescriptorType type)
  210. {
  211. FASSERT(parser);
  212. if (!FUsbParserIsValid(parser))
  213. {
  214. FUSB_ERROR("Config parse is not valid !!!");
  215. return NULL;
  216. }
  217. const FUsbDescriptor *result = NULL;
  218. FUsbDescriptorType desc_type;
  219. u8 desc_len;
  220. const FUsbDescriptor *desc_end;
  221. /* travesal all descriptors */
  222. while (parser->next_pos < parser->end_pos)
  223. {
  224. desc_len = parser->next_pos->header.len;
  225. desc_type = parser->next_pos->header.type;
  226. desc_end = FUSB_SKIP_BYTES(parser->next_pos, desc_len);
  227. if (desc_end > parser->end_pos)
  228. break;
  229. if ((FUSB_DESC_TYPE_ENDPOINT == type) &&
  230. (FUSB_DESC_TYPE_INTERFACE == desc_type))
  231. break; /* there is no chance to find endpoint desc after interface desc */
  232. if (type == desc_type)
  233. {
  234. /* target desc found !!! */
  235. result = parser->next_pos;
  236. parser->next_pos = desc_end;
  237. break;
  238. }
  239. parser->next_pos = desc_end;/* check next one */
  240. }
  241. if (NULL != result)
  242. {
  243. parser->err_pos = result;
  244. }
  245. parser->cur_desc = result;
  246. return result;
  247. }
  248. /**
  249. * @name: FUsbSetupStringParser
  250. * @msg: 初始化字符串描述符解析器
  251. * @return {*}
  252. * @param {FUsbDev} *dev, USB设备实例
  253. */
  254. void FUsbSetupStringParser(FUsbDev *dev)
  255. {
  256. FASSERT(dev);
  257. FUsbStringParser *parser = &dev->string_parser;
  258. if (NULL != parser->usb_str)
  259. {
  260. FUSB_WARN("String descriptor exists, might cause memory leakage !!!");
  261. }
  262. parser->usb_str = NULL;
  263. memset(parser->str_buf, 0, sizeof(parser->str_buf));
  264. return;
  265. }
  266. /**
  267. * @name: FUsbRevokeStringParser
  268. * @msg: 去初始化字符串描述符解析器
  269. * @return {*}
  270. * @param {FUsbDev} *dev, USB设备实例
  271. */
  272. void FUsbRevokeStringParser(FUsbDev *dev)
  273. {
  274. FASSERT(dev);
  275. FUsbStringParser *parser = &dev->string_parser;
  276. FASSERT(dev->controller && dev->controller->usb);
  277. FUsb *instance = dev->controller->usb;
  278. if (NULL != parser->usb_str)
  279. {
  280. FUSB_FREE(instance, parser->usb_str);
  281. parser->usb_str = NULL;
  282. }
  283. return;
  284. }
  285. /**
  286. * @name: FUsbSearchStringDescriptor
  287. * @msg: 检索字符串描述符,保存在FUsbStringParser结构中
  288. * @return {*}
  289. * @param {FUsb} *instance, USB实例
  290. * @param {FUsbDev} *dev, USB设备实例
  291. * @param {u8} id, 要获取字符串描述符的ID
  292. */
  293. FError FUsbSearchStringDescriptor(FUsb *instance, FUsbDev *dev, u8 id)
  294. {
  295. FASSERT(instance && dev);
  296. FUsbStringParser *parser = &dev->string_parser;
  297. const FUsbStringDescriptor *usb_str = NULL;
  298. u8 total_len;
  299. u8 char_num;
  300. u16 character;
  301. /* re-malloc usb string desc buffer with length 4 */
  302. if (NULL != parser->usb_str)
  303. {
  304. FUSB_FREE(instance, parser->usb_str);
  305. parser->usb_str = NULL;
  306. }
  307. parser->usb_str = FUSB_ALLOCATE(instance, FUSB_USBSTR_MIN_LEN, FUSB_DEFAULT_ALIGN);
  308. if (NULL == parser->usb_str)
  309. return FUSB_ERR_ALLOCATE_FAIL;
  310. /* get header of string for the full length */
  311. if (FUsbGetStringDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_STRING, id, FUSB_DEFAULT_LANG_ID,
  312. parser->usb_str, FUSB_USBSTR_MIN_LEN) < 0)
  313. {
  314. FUSB_ERROR("Parse string descriptor failed (len: %d) !!!", FUSB_USBSTR_MIN_LEN);
  315. return FUSB_ERR_DESC_PARSE_ERR;
  316. }
  317. /* check if string descriptor header is valid */
  318. total_len = parser->usb_str->len;
  319. if ((total_len < FUSB_DESCRIPTOR_HEADER_SIZE) ||
  320. ((total_len & 1) != 0) ||
  321. (parser->usb_str->type != FUSB_DESC_TYPE_STRING))
  322. {
  323. FUSB_ERROR("Get invalid string descriptor (len: %d) !!!", FUSB_USBSTR_MIN_LEN);
  324. return FUSB_ERR_DESC_PARSE_ERR;
  325. }
  326. /* return if no need to get more */
  327. if (total_len <= FUSB_USBSTR_MIN_LEN)
  328. return FUSB_SUCCESS;
  329. /* re-malloc usb string desc buffer with full length */
  330. FASSERT(parser->usb_str);
  331. FUSB_FREE(instance, parser->usb_str);
  332. parser->usb_str = NULL;
  333. parser->usb_str = FUSB_ALLOCATE(instance, total_len, FUSB_DEFAULT_ALIGN);
  334. if (NULL == parser->usb_str)
  335. return FUSB_ERR_ALLOCATE_FAIL;
  336. /* get the whole string descriptor */
  337. if (FUsbGetStringDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_STRING, id, FUSB_DEFAULT_LANG_ID,
  338. parser->usb_str, total_len) < 0)
  339. {
  340. FUSB_ERROR("Parse string descriptor failed (len: %d)!!!", total_len);
  341. return FUSB_ERR_DESC_PARSE_ERR;
  342. }
  343. if ((parser->usb_str->len < FUSB_DESCRIPTOR_HEADER_SIZE) ||
  344. ((parser->usb_str->len & 1) != 0) ||
  345. (parser->usb_str->type != FUSB_DESC_TYPE_STRING))
  346. {
  347. FUSB_ERROR("Get invalid string descriptor (len: %d) !!!", total_len);
  348. return FUSB_ERR_DESC_PARSE_ERR;
  349. }
  350. /* convert into ASCII string */
  351. usb_str = parser->usb_str;
  352. char_num = (usb_str->len - FUSB_DESCRIPTOR_HEADER_SIZE) / 2; /* in 16-bit way */
  353. if (char_num >= FUSB_STRDESC_BUF_MAX - 1)
  354. {
  355. return FUSB_ERR_NOT_SUPPORT;
  356. }
  357. for (u8 i = 0; i < char_num; i++)
  358. {
  359. character = usb_str->string[i];
  360. if (character < ' ' /* 0x20 */
  361. || character > '~') /* 0x7E */
  362. {
  363. character = '_';
  364. }
  365. parser->str_buf[i] = (char)character;
  366. }
  367. parser->str_buf[char_num] = '\0';
  368. return FUSB_SUCCESS;
  369. }
  370. /**
  371. * @name: FUsbGetString
  372. * @msg: 获取刚刚检索到的字符串描述符内容
  373. * @return {const char *}, 字符串描述符中的内容
  374. * @param {FUsbDev} *dev, USB设备实例
  375. */
  376. const char *FUsbGetString(const FUsbDev *const dev)
  377. {
  378. FASSERT(dev);
  379. return (const char *)dev->string_parser.str_buf;
  380. }