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