usbd_video.c 40 KB

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