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 }