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