usbd_video.c 42 KB

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