usbd_video.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  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. USB_LOG_INFO("Video set brightness:%d\r\n", wBrightness);
  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_mjpeg_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. }