• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }