usbd_video.c 40 KB

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