usbd_video.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. /*
  2. * Copyright (c) 2022, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbd_core.h"
  7. #include "usbd_video.h"
  8. struct video_entity_info {
  9. uint8_t bDescriptorSubtype;
  10. uint8_t bEntityId;
  11. uint16_t wTerminalType;
  12. };
  13. struct usbd_video_priv {
  14. struct video_probe_and_commit_controls probe;
  15. struct video_probe_and_commit_controls commit;
  16. uint8_t power_mode;
  17. uint8_t error_code;
  18. struct video_entity_info info[3];
  19. uint8_t *ep_buf0;
  20. uint8_t *ep_buf1;
  21. bool ep_buf0_ready;
  22. bool ep_buf1_ready;
  23. uint32_t ep_buf0_len;
  24. uint32_t ep_buf1_len;
  25. uint8_t ep_buf_idx;
  26. bool stream_finish;
  27. uint32_t max_packets;
  28. uint8_t *stream_buf;
  29. uint32_t stream_len;
  30. uint32_t stream_offset;
  31. uint8_t stream_frameid;
  32. uint32_t stream_headerlen;
  33. } g_usbd_video[CONFIG_USBDEV_MAX_BUS];
  34. static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  35. {
  36. uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
  37. (void)busid;
  38. switch (control_selector) {
  39. case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
  40. switch (setup->bRequest) {
  41. case VIDEO_REQUEST_SET_CUR:
  42. break;
  43. case VIDEO_REQUEST_GET_CUR:
  44. break;
  45. case VIDEO_REQUEST_GET_INFO:
  46. break;
  47. default:
  48. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  49. return -1;
  50. }
  51. break;
  52. case VIDEO_VC_REQUEST_ERROR_CODE_CONTROL:
  53. switch (setup->bRequest) {
  54. case VIDEO_REQUEST_GET_CUR:
  55. (*data)[0] = 0x06;
  56. *len = 1;
  57. break;
  58. case VIDEO_REQUEST_GET_INFO:
  59. break;
  60. default:
  61. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  62. return -1;
  63. }
  64. break;
  65. default:
  66. break;
  67. }
  68. return 0;
  69. }
  70. static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  71. {
  72. uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
  73. uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
  74. for (uint8_t i = 0; i < 3; i++) {
  75. struct video_entity_info *entity_info = &g_usbd_video[busid].info[i];
  76. if (entity_info->bEntityId == entity_id) {
  77. switch (entity_info->bDescriptorSubtype) {
  78. case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
  79. break;
  80. case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
  81. if (entity_info->wTerminalType == VIDEO_ITT_CAMERA) {
  82. switch (control_selector) {
  83. case VIDEO_CT_AE_MODE_CONTROL:
  84. switch (setup->bRequest) {
  85. case VIDEO_REQUEST_GET_CUR:
  86. (*data)[0] = 0x08;
  87. *len = 1;
  88. break;
  89. default:
  90. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  91. return -1;
  92. }
  93. break;
  94. case VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
  95. switch (setup->bRequest) {
  96. case VIDEO_REQUEST_GET_CUR: {
  97. uint32_t dwExposureTimeAbsolute = 2500;
  98. memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
  99. *len = 4;
  100. } break;
  101. case VIDEO_REQUEST_GET_MIN: {
  102. uint32_t dwExposureTimeAbsolute = 5; //0.0005sec
  103. memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
  104. *len = 4;
  105. } break;
  106. case VIDEO_REQUEST_GET_MAX: {
  107. uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec
  108. memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
  109. *len = 4;
  110. } break;
  111. case VIDEO_REQUEST_GET_RES: {
  112. uint32_t dwExposureTimeAbsolute = 5; //0.0005sec
  113. memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
  114. *len = 4;
  115. } break;
  116. case VIDEO_REQUEST_GET_INFO:
  117. (*data)[0] = 0x03; //struct video_camera_capabilities
  118. *len = 1;
  119. break;
  120. case VIDEO_REQUEST_GET_DEF: {
  121. uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec
  122. memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
  123. *len = 4;
  124. } break;
  125. default:
  126. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  127. return -1;
  128. }
  129. break;
  130. case VIDEO_CT_FOCUS_ABSOLUTE_CONTROL:
  131. switch (setup->bRequest) {
  132. case VIDEO_REQUEST_GET_CUR: {
  133. uint16_t wFocusAbsolute = 0x0080;
  134. memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
  135. *len = 2;
  136. } break;
  137. case VIDEO_REQUEST_GET_MIN: {
  138. uint16_t wFocusAbsolute = 0;
  139. memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
  140. *len = 2;
  141. } break;
  142. case VIDEO_REQUEST_GET_MAX: {
  143. uint16_t wFocusAbsolute = 0x00ff;
  144. memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
  145. *len = 2;
  146. } break;
  147. case VIDEO_REQUEST_GET_RES: {
  148. uint16_t wFocusAbsolute = 0x0001;
  149. memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
  150. *len = 2;
  151. } break;
  152. case VIDEO_REQUEST_GET_INFO:
  153. (*data)[0] = 0x03; //struct video_camera_capabilities
  154. *len = 1;
  155. break;
  156. case VIDEO_REQUEST_GET_DEF: {
  157. uint16_t wFocusAbsolute = 0x0080;
  158. memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
  159. *len = 2;
  160. } break;
  161. default:
  162. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  163. return -1;
  164. }
  165. break;
  166. case VIDEO_CT_ZOOM_ABSOLUTE_CONTROL:
  167. switch (setup->bRequest) {
  168. case VIDEO_REQUEST_GET_CUR: {
  169. uint16_t wObjectiveFocalLength = 0x0064;
  170. memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
  171. *len = 2;
  172. } break;
  173. case VIDEO_REQUEST_GET_MIN: {
  174. uint16_t wObjectiveFocalLength = 0x0064;
  175. memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
  176. *len = 2;
  177. } break;
  178. case VIDEO_REQUEST_GET_MAX: {
  179. uint16_t wObjectiveFocalLength = 0x00c8;
  180. memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
  181. *len = 2;
  182. } break;
  183. case VIDEO_REQUEST_GET_RES: {
  184. uint16_t wObjectiveFocalLength = 0x0001;
  185. memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
  186. *len = 2;
  187. } break;
  188. case VIDEO_REQUEST_GET_INFO:
  189. (*data)[0] = 0x03; //struct video_camera_capabilities
  190. *len = 1;
  191. break;
  192. case VIDEO_REQUEST_GET_DEF: {
  193. uint16_t wObjectiveFocalLength = 0x0064;
  194. memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
  195. *len = 2;
  196. } break;
  197. default:
  198. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  199. return -1;
  200. }
  201. break;
  202. case VIDEO_CT_ROLL_ABSOLUTE_CONTROL:
  203. switch (setup->bRequest) {
  204. case VIDEO_REQUEST_GET_CUR: {
  205. uint16_t wRollAbsolute = 0x0000;
  206. memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
  207. *len = 2;
  208. } break;
  209. case VIDEO_REQUEST_GET_MIN: {
  210. uint16_t wRollAbsolute = 0x0000;
  211. memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
  212. *len = 2;
  213. } break;
  214. case VIDEO_REQUEST_GET_MAX: {
  215. uint16_t wRollAbsolute = 0x00ff;
  216. memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
  217. *len = 2;
  218. } break;
  219. case VIDEO_REQUEST_GET_RES: {
  220. uint16_t wRollAbsolute = 0x0001;
  221. memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
  222. *len = 2;
  223. } break;
  224. case VIDEO_REQUEST_GET_INFO:
  225. (*data)[0] = 0x03; //struct video_camera_capabilities
  226. *len = 1;
  227. break;
  228. case VIDEO_REQUEST_GET_DEF: {
  229. uint16_t wRollAbsolute = 0x0000;
  230. memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
  231. *len = 2;
  232. } break;
  233. default:
  234. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  235. return -1;
  236. }
  237. break;
  238. case VIDEO_CT_FOCUS_AUTO_CONTROL:
  239. switch (setup->bRequest) {
  240. case VIDEO_REQUEST_GET_CUR: {
  241. uint16_t wFocusAuto = 0x0000;
  242. memcpy(*data, (uint8_t *)&wFocusAuto, 2);
  243. *len = 2;
  244. } break;
  245. default:
  246. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  247. return -1;
  248. }
  249. break;
  250. default:
  251. USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
  252. return -1;
  253. }
  254. } else {
  255. USB_LOG_WRN("Unhandled Video Class wTerminalType 0x%02x\r\n", entity_info->wTerminalType);
  256. return -2;
  257. }
  258. break;
  259. case VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
  260. break;
  261. case VIDEO_VC_SELECTOR_UNIT_DESCRIPTOR_SUBTYPE:
  262. break;
  263. case VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE:
  264. switch (control_selector) {
  265. case VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL:
  266. switch (setup->bRequest) {
  267. case VIDEO_REQUEST_GET_CUR: {
  268. uint16_t wBacklightCompensation = 0x0004;
  269. memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
  270. *len = 2;
  271. } break;
  272. case VIDEO_REQUEST_GET_MIN: {
  273. uint16_t wBacklightCompensation = 0;
  274. memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
  275. *len = 2;
  276. } break;
  277. case VIDEO_REQUEST_GET_MAX: {
  278. uint16_t wBacklightCompensation = 8;
  279. memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
  280. *len = 2;
  281. } break;
  282. case VIDEO_REQUEST_GET_RES: {
  283. uint16_t wBacklightCompensation = 1;
  284. memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
  285. *len = 2;
  286. } break;
  287. case VIDEO_REQUEST_GET_INFO:
  288. (*data)[0] = 0x03; //struct video_camera_capabilities
  289. *len = 1;
  290. break;
  291. case VIDEO_REQUEST_GET_DEF: {
  292. uint16_t wBacklightCompensation = 4;
  293. memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
  294. *len = 2;
  295. } break;
  296. default:
  297. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  298. return -1;
  299. }
  300. break;
  301. case VIDEO_PU_BRIGHTNESS_CONTROL:
  302. switch (setup->bRequest) {
  303. case VIDEO_REQUEST_SET_CUR: {
  304. //uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
  305. } break;
  306. case VIDEO_REQUEST_GET_CUR: {
  307. uint16_t wBrightness = 0x0080;
  308. memcpy(*data, (uint8_t *)&wBrightness, 2);
  309. *len = 2;
  310. } break;
  311. case VIDEO_REQUEST_GET_MIN: {
  312. uint16_t wBrightness = 0x0001;
  313. memcpy(*data, (uint8_t *)&wBrightness, 2);
  314. *len = 2;
  315. } break;
  316. case VIDEO_REQUEST_GET_MAX: {
  317. uint16_t wBrightness = 0x00ff;
  318. memcpy(*data, (uint8_t *)&wBrightness, 2);
  319. *len = 2;
  320. } break;
  321. case VIDEO_REQUEST_GET_RES: {
  322. uint16_t wBrightness = 0x0001;
  323. memcpy(*data, (uint8_t *)&wBrightness, 2);
  324. *len = 2;
  325. } break;
  326. case VIDEO_REQUEST_GET_INFO:
  327. (*data)[0] = 0x03; //struct video_camera_capabilities
  328. *len = 1;
  329. break;
  330. case VIDEO_REQUEST_GET_DEF: {
  331. uint16_t wBrightness = 0x0080;
  332. memcpy(*data, (uint8_t *)&wBrightness, 2);
  333. *len = 2;
  334. } break;
  335. default:
  336. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  337. return -1;
  338. }
  339. break;
  340. case VIDEO_PU_CONTRAST_CONTROL:
  341. switch (setup->bRequest) {
  342. case VIDEO_REQUEST_GET_CUR: {
  343. uint16_t wContrast = 0x0080;
  344. memcpy(*data, (uint8_t *)&wContrast, 2);
  345. *len = 2;
  346. } break;
  347. case VIDEO_REQUEST_GET_MIN: {
  348. uint16_t wContrast = 0x0001;
  349. memcpy(*data, (uint8_t *)&wContrast, 2);
  350. *len = 2;
  351. } break;
  352. case VIDEO_REQUEST_GET_MAX: {
  353. uint16_t wContrast = 0x00ff;
  354. memcpy(*data, (uint8_t *)&wContrast, 2);
  355. *len = 2;
  356. } break;
  357. case VIDEO_REQUEST_GET_RES: {
  358. uint16_t wContrast = 0x0001;
  359. memcpy(*data, (uint8_t *)&wContrast, 2);
  360. *len = 2;
  361. } break;
  362. case VIDEO_REQUEST_GET_INFO:
  363. (*data)[0] = 0x03; //struct video_camera_capabilities
  364. *len = 1;
  365. break;
  366. case VIDEO_REQUEST_GET_DEF: {
  367. uint16_t wContrast = 0x0080;
  368. memcpy(*data, (uint8_t *)&wContrast, 2);
  369. *len = 2;
  370. } break;
  371. default:
  372. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  373. return -1;
  374. }
  375. break;
  376. case VIDEO_PU_HUE_CONTROL:
  377. switch (setup->bRequest) {
  378. case VIDEO_REQUEST_GET_CUR: {
  379. uint16_t wHue = 0x0080;
  380. memcpy(*data, (uint8_t *)&wHue, 2);
  381. *len = 2;
  382. } break;
  383. case VIDEO_REQUEST_GET_MIN: {
  384. uint16_t wHue = 0x0001;
  385. memcpy(*data, (uint8_t *)&wHue, 2);
  386. *len = 2;
  387. } break;
  388. case VIDEO_REQUEST_GET_MAX: {
  389. uint16_t wHue = 0x00ff;
  390. memcpy(*data, (uint8_t *)&wHue, 2);
  391. *len = 2;
  392. } break;
  393. case VIDEO_REQUEST_GET_RES: {
  394. uint16_t wHue = 0x0001;
  395. memcpy(*data, (uint8_t *)&wHue, 2);
  396. *len = 2;
  397. } break;
  398. case VIDEO_REQUEST_GET_INFO:
  399. (*data)[0] = 0x03; //struct video_camera_capabilities
  400. *len = 1;
  401. break;
  402. case VIDEO_REQUEST_GET_DEF: {
  403. uint16_t wHue = 0x0080;
  404. memcpy(*data, (uint8_t *)&wHue, 2);
  405. *len = 2;
  406. } break;
  407. default:
  408. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  409. return -1;
  410. }
  411. break;
  412. case VIDEO_PU_SATURATION_CONTROL:
  413. switch (setup->bRequest) {
  414. case VIDEO_REQUEST_GET_MIN: {
  415. uint16_t wSaturation = 0x0001;
  416. memcpy(*data, (uint8_t *)&wSaturation, 2);
  417. *len = 2;
  418. } break;
  419. case VIDEO_REQUEST_GET_MAX: {
  420. uint16_t wSaturation = 0x00ff;
  421. memcpy(*data, (uint8_t *)&wSaturation, 2);
  422. *len = 2;
  423. } break;
  424. case VIDEO_REQUEST_GET_RES: {
  425. uint16_t wSaturation = 0x0001;
  426. memcpy(*data, (uint8_t *)&wSaturation, 2);
  427. *len = 2;
  428. } break;
  429. case VIDEO_REQUEST_GET_INFO:
  430. (*data)[0] = 0x03; //struct video_camera_capabilities
  431. *len = 1;
  432. break;
  433. case VIDEO_REQUEST_GET_DEF: {
  434. uint16_t wSaturation = 0x0080;
  435. memcpy(*data, (uint8_t *)&wSaturation, 2);
  436. *len = 2;
  437. } break;
  438. default:
  439. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  440. return -1;
  441. }
  442. break;
  443. case VIDEO_PU_SHARPNESS_CONTROL:
  444. switch (setup->bRequest) {
  445. case VIDEO_REQUEST_GET_MIN: {
  446. uint16_t wSharpness = 0x0001;
  447. memcpy(*data, (uint8_t *)&wSharpness, 2);
  448. *len = 2;
  449. } break;
  450. case VIDEO_REQUEST_GET_MAX: {
  451. uint16_t wSharpness = 0x00ff;
  452. memcpy(*data, (uint8_t *)&wSharpness, 2);
  453. *len = 2;
  454. } break;
  455. case VIDEO_REQUEST_GET_RES: {
  456. uint16_t wSharpness = 0x0001;
  457. memcpy(*data, (uint8_t *)&wSharpness, 2);
  458. *len = 2;
  459. } break;
  460. case VIDEO_REQUEST_GET_INFO:
  461. (*data)[0] = 0x03; //struct video_camera_capabilities
  462. *len = 1;
  463. break;
  464. case VIDEO_REQUEST_GET_DEF: {
  465. uint16_t wSharpness = 0x0080;
  466. memcpy(*data, (uint8_t *)&wSharpness, 2);
  467. *len = 2;
  468. } break;
  469. default:
  470. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  471. return -1;
  472. }
  473. break;
  474. case VIDEO_PU_GAIN_CONTROL:
  475. switch (setup->bRequest) {
  476. case VIDEO_REQUEST_GET_MIN: {
  477. uint16_t wGain = 0;
  478. memcpy(*data, (uint8_t *)&wGain, 2);
  479. *len = 2;
  480. } break;
  481. case VIDEO_REQUEST_GET_MAX: {
  482. uint16_t wGain = 255;
  483. memcpy(*data, (uint8_t *)&wGain, 2);
  484. *len = 2;
  485. } break;
  486. case VIDEO_REQUEST_GET_RES: {
  487. uint16_t wGain = 1;
  488. memcpy(*data, (uint8_t *)&wGain, 2);
  489. *len = 2;
  490. } break;
  491. case VIDEO_REQUEST_GET_INFO:
  492. (*data)[0] = 0x03; //struct video_camera_capabilities
  493. *len = 1;
  494. break;
  495. case VIDEO_REQUEST_GET_DEF: {
  496. uint16_t wGain = 255;
  497. memcpy(*data, (uint8_t *)&wGain, 2);
  498. *len = 2;
  499. } break;
  500. default:
  501. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  502. return -1;
  503. }
  504. break;
  505. case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
  506. switch (setup->bRequest) {
  507. case VIDEO_REQUEST_GET_CUR: {
  508. uint16_t wWhiteBalance_Temprature = 417;
  509. memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
  510. *len = 2;
  511. } break;
  512. case VIDEO_REQUEST_GET_MIN: {
  513. uint16_t wWhiteBalance_Temprature = 300;
  514. memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
  515. *len = 2;
  516. } break;
  517. case VIDEO_REQUEST_GET_MAX: {
  518. uint16_t wWhiteBalance_Temprature = 600;
  519. memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
  520. *len = 2;
  521. } break;
  522. case VIDEO_REQUEST_GET_RES: {
  523. uint16_t wWhiteBalance_Temprature = 1;
  524. memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
  525. *len = 2;
  526. } break;
  527. case VIDEO_REQUEST_GET_INFO:
  528. (*data)[0] = 0x03; //struct video_camera_capabilities
  529. *len = 1;
  530. break;
  531. case VIDEO_REQUEST_GET_DEF: {
  532. uint16_t wWhiteBalance_Temprature = 417;
  533. memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
  534. *len = 2;
  535. } break;
  536. default:
  537. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  538. return -1;
  539. }
  540. break;
  541. case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
  542. switch (setup->bRequest) {
  543. case VIDEO_REQUEST_GET_CUR: {
  544. uint16_t wWhiteBalance_Temprature_Auto = 1;
  545. memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature_Auto, 1);
  546. *len = 1;
  547. } break;
  548. default:
  549. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  550. return -1;
  551. }
  552. break;
  553. default:
  554. g_usbd_video[busid].error_code = 0x06;
  555. USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
  556. return -1;
  557. }
  558. break;
  559. case VIDEO_VC_EXTENSION_UNIT_DESCRIPTOR_SUBTYPE:
  560. break;
  561. case VIDEO_VC_ENCODING_UNIT_DESCRIPTOR_SUBTYPE:
  562. break;
  563. default:
  564. break;
  565. }
  566. }
  567. }
  568. return 0;
  569. }
  570. static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  571. {
  572. uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
  573. switch (control_selector) {
  574. case VIDEO_VS_PROBE_CONTROL:
  575. switch (setup->bRequest) {
  576. case VIDEO_REQUEST_SET_CUR:
  577. //memcpy((uint8_t *)&g_usbd_video[busid].probe, *data, setup->wLength);
  578. break;
  579. case VIDEO_REQUEST_GET_CUR:
  580. memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
  581. *len = sizeof(struct video_probe_and_commit_controls);
  582. break;
  583. case VIDEO_REQUEST_GET_MIN:
  584. case VIDEO_REQUEST_GET_MAX:
  585. case VIDEO_REQUEST_GET_RES:
  586. case VIDEO_REQUEST_GET_DEF:
  587. memcpy(*data, (uint8_t *)&g_usbd_video[busid].probe, setup->wLength);
  588. *len = sizeof(struct video_probe_and_commit_controls);
  589. break;
  590. case VIDEO_REQUEST_GET_LEN:
  591. (*data)[0] = sizeof(struct video_probe_and_commit_controls);
  592. *len = 1;
  593. break;
  594. case VIDEO_REQUEST_GET_INFO:
  595. (*data)[0] = 0x03;
  596. *len = 1;
  597. break;
  598. default:
  599. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  600. return -1;
  601. }
  602. break;
  603. case VIDEO_VS_COMMIT_CONTROL:
  604. switch (setup->bRequest) {
  605. case VIDEO_REQUEST_SET_CUR:
  606. //memcpy((uint8_t *)&g_usbd_video[busid].commit, *data, setup->wLength);
  607. break;
  608. case VIDEO_REQUEST_GET_CUR:
  609. memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
  610. *len = sizeof(struct video_probe_and_commit_controls);
  611. break;
  612. case VIDEO_REQUEST_GET_MIN:
  613. case VIDEO_REQUEST_GET_MAX:
  614. case VIDEO_REQUEST_GET_RES:
  615. case VIDEO_REQUEST_GET_DEF:
  616. memcpy(*data, (uint8_t *)&g_usbd_video[busid].commit, setup->wLength);
  617. *len = sizeof(struct video_probe_and_commit_controls);
  618. break;
  619. case VIDEO_REQUEST_GET_LEN:
  620. (*data)[0] = sizeof(struct video_probe_and_commit_controls);
  621. *len = 1;
  622. break;
  623. case VIDEO_REQUEST_GET_INFO:
  624. (*data)[0] = 0x03;
  625. *len = 1;
  626. break;
  627. default:
  628. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  629. return -1;
  630. }
  631. break;
  632. case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
  633. switch (setup->bRequest) {
  634. case VIDEO_REQUEST_GET_CUR:
  635. (*data)[0] = g_usbd_video[busid].error_code;
  636. *len = 1;
  637. break;
  638. case VIDEO_REQUEST_GET_INFO:
  639. (*data)[0] = 0x01;
  640. *len = 1;
  641. break;
  642. default:
  643. USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
  644. return -1;
  645. }
  646. break;
  647. default:
  648. break;
  649. }
  650. return 0;
  651. }
  652. static int video_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
  653. {
  654. USB_LOG_DBG("Video Class request: "
  655. "bRequest 0x%02x\r\n",
  656. setup->bRequest);
  657. uint8_t intf_num = (uint8_t)setup->wIndex;
  658. uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
  659. if (intf_num == 0) { /* Video Control Interface */
  660. if (entity_id == 0) {
  661. return usbd_video_control_request_handler(busid, setup, data, len); /* Interface Control Requests */
  662. } else {
  663. return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
  664. }
  665. } else if (intf_num == 1) { /* Video Stream Inteface */
  666. return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
  667. }
  668. return -1;
  669. }
  670. static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
  671. {
  672. switch (event) {
  673. case USBD_EVENT_RESET:
  674. g_usbd_video[busid].error_code = 0;
  675. g_usbd_video[busid].power_mode = 0;
  676. break;
  677. case USBD_EVENT_SET_INTERFACE: {
  678. struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
  679. if (intf->bAlternateSetting == 1) {
  680. usbd_video_open(busid, intf->bInterfaceNumber);
  681. } else {
  682. usbd_video_close(busid, intf->bInterfaceNumber);
  683. }
  684. }
  685. break;
  686. default:
  687. break;
  688. }
  689. }
  690. static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
  691. {
  692. g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
  693. g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
  694. g_usbd_video[busid].probe.bFormatIndex = 1;
  695. g_usbd_video[busid].probe.bFrameIndex = 1;
  696. g_usbd_video[busid].probe.dwFrameInterval = dwFrameInterval;
  697. g_usbd_video[busid].probe.wKeyFrameRate = 0;
  698. g_usbd_video[busid].probe.wPFrameRate = 0;
  699. g_usbd_video[busid].probe.wCompQuality = 0;
  700. g_usbd_video[busid].probe.wCompWindowSize = 0;
  701. g_usbd_video[busid].probe.wDelay = 0;
  702. g_usbd_video[busid].probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
  703. g_usbd_video[busid].probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
  704. g_usbd_video[busid].probe.dwClockFrequency = 0;
  705. g_usbd_video[busid].probe.bmFramingInfo = 0;
  706. g_usbd_video[busid].probe.bPreferedVersion = 0;
  707. g_usbd_video[busid].probe.bMinVersion = 0;
  708. g_usbd_video[busid].probe.bMaxVersion = 0;
  709. g_usbd_video[busid].commit.hintUnion.bmHint = 0x01;
  710. g_usbd_video[busid].commit.hintUnion1.bmHint = 0;
  711. g_usbd_video[busid].commit.bFormatIndex = 1;
  712. g_usbd_video[busid].commit.bFrameIndex = 1;
  713. g_usbd_video[busid].commit.dwFrameInterval = dwFrameInterval;
  714. g_usbd_video[busid].commit.wKeyFrameRate = 0;
  715. g_usbd_video[busid].commit.wPFrameRate = 0;
  716. g_usbd_video[busid].commit.wCompQuality = 0;
  717. g_usbd_video[busid].commit.wCompWindowSize = 0;
  718. g_usbd_video[busid].commit.wDelay = 0;
  719. g_usbd_video[busid].commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
  720. g_usbd_video[busid].commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
  721. g_usbd_video[busid].commit.dwClockFrequency = 0;
  722. g_usbd_video[busid].commit.bmFramingInfo = 0;
  723. g_usbd_video[busid].commit.bPreferedVersion = 0;
  724. g_usbd_video[busid].commit.bMinVersion = 0;
  725. g_usbd_video[busid].commit.bMaxVersion = 0;
  726. g_usbd_video[busid].stream_frameid = 0;
  727. g_usbd_video[busid].stream_headerlen = 2;
  728. }
  729. static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
  730. {
  731. struct video_payload_header *header;
  732. uint32_t len;
  733. uint32_t offset;
  734. len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
  735. offset = 0;
  736. while (len > 0) {
  737. header = (struct video_payload_header *)&ep_buf[offset];
  738. header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
  739. header->headerInfoUnion.bmheaderInfo = 0;
  740. header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
  741. header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
  742. header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
  743. uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
  744. usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
  745. &g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
  746. len2);
  747. g_usbd_video[busid].stream_offset += len2;
  748. len -= len2;
  749. offset += (len2 + g_usbd_video[busid].stream_headerlen);
  750. if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
  751. header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
  752. }
  753. }
  754. return offset;
  755. }
  756. struct usbd_interface *usbd_video_init_intf(uint8_t busid,
  757. struct usbd_interface *intf,
  758. uint32_t dwFrameInterval,
  759. uint32_t dwMaxVideoFrameSize,
  760. uint32_t dwMaxPayloadTransferSize)
  761. {
  762. intf->class_interface_handler = video_class_interface_request_handler;
  763. intf->class_endpoint_handler = NULL;
  764. intf->vendor_handler = NULL;
  765. intf->notify_handler = video_notify_handler;
  766. g_usbd_video[busid].info[0].bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
  767. g_usbd_video[busid].info[0].bEntityId = 0x01;
  768. g_usbd_video[busid].info[0].wTerminalType = VIDEO_ITT_CAMERA;
  769. g_usbd_video[busid].info[1].bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE;
  770. g_usbd_video[busid].info[1].bEntityId = 0x03;
  771. g_usbd_video[busid].info[1].wTerminalType = 0x00;
  772. g_usbd_video[busid].info[2].bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE;
  773. g_usbd_video[busid].info[2].bEntityId = 0x02;
  774. g_usbd_video[busid].info[2].wTerminalType = 0x00;
  775. usbd_video_probe_and_commit_controls_init(busid, dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
  776. return intf;
  777. }
  778. bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
  779. {
  780. uint32_t remain;
  781. if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */
  782. g_usbd_video[busid].ep_buf0_ready = false;
  783. g_usbd_video[busid].ep_buf_idx = 1;
  784. usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
  785. } else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */
  786. g_usbd_video[busid].ep_buf1_ready = false;
  787. g_usbd_video[busid].ep_buf_idx = 0;
  788. usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
  789. } else {
  790. if (g_usbd_video[busid].stream_finish) {
  791. return true;
  792. }
  793. }
  794. if (!g_usbd_video[busid].ep_buf0_ready) {
  795. remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
  796. if (remain == 0) {
  797. g_usbd_video[busid].stream_frameid ^= 1;
  798. g_usbd_video[busid].stream_finish = true;
  799. } else {
  800. g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
  801. g_usbd_video[busid].ep_buf0_ready = true;
  802. if (!g_usbd_video[busid].ep_buf1_ready) {
  803. g_usbd_video[busid].ep_buf_idx = 0;
  804. usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
  805. }
  806. }
  807. }
  808. if (!g_usbd_video[busid].ep_buf1_ready) {
  809. remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
  810. if (remain == 0) {
  811. g_usbd_video[busid].stream_frameid ^= 1;
  812. g_usbd_video[busid].stream_finish = true;
  813. } else {
  814. g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
  815. g_usbd_video[busid].ep_buf1_ready = true;
  816. }
  817. }
  818. return false;
  819. }
  820. int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
  821. {
  822. if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
  823. return -1;
  824. }
  825. g_usbd_video[busid].ep_buf0 = ep_buf0;
  826. g_usbd_video[busid].ep_buf1 = ep_buf1;
  827. g_usbd_video[busid].ep_buf0_ready = false;
  828. g_usbd_video[busid].ep_buf1_ready = false;
  829. g_usbd_video[busid].ep_buf_idx = 0;
  830. g_usbd_video[busid].stream_finish = false;
  831. g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
  832. g_usbd_video[busid].stream_buf = stream_buf;
  833. g_usbd_video[busid].stream_len = stream_len;
  834. g_usbd_video[busid].stream_offset = 0;
  835. usbd_video_stream_split_transfer(busid, ep);
  836. return 0;
  837. }