usbd_video.c 40 KB

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