1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_device_config.h"
10 #include "usb.h"
11 #include "usb_device.h"
12 
13 #include "usb_device_class.h"
14 
15 #if ((defined(USB_DEVICE_CONFIG_VIDEO)) && (USB_DEVICE_CONFIG_VIDEO > 0U))
16 #include "usb_device_video.h"
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 
26 static usb_status_t USB_DeviceVideoAllocateHandle(usb_device_video_struct_t **handle);
27 static usb_status_t USB_DeviceVideoFreeHandle(usb_device_video_struct_t *handle);
28 static usb_status_t USB_DeviceVideoControlIn(usb_device_handle handle,
29                                              usb_device_endpoint_callback_message_struct_t *message,
30                                              void *callbackParam);
31 static usb_status_t USB_DeviceVideoStreamIn(usb_device_handle handle,
32                                             usb_device_endpoint_callback_message_struct_t *message,
33                                             void *callbackParam);
34 static usb_status_t USB_DeviceVideoStreamOut(usb_device_handle handle,
35                                              usb_device_endpoint_callback_message_struct_t *message,
36                                              void *callbackParam);
37 static usb_status_t USB_DeviceVideoStreamEndpointsInit(usb_device_video_struct_t *videoHandle);
38 static usb_status_t USB_DeviceVideoStreamEndpointsDeinit(usb_device_video_struct_t *videoHandle);
39 static usb_status_t USB_DeviceVideoControlEndpointsInit(usb_device_video_struct_t *videoHandle);
40 static usb_status_t USB_DeviceVideoControlEndpointsDeinit(usb_device_video_struct_t *videoHandle);
41 
42 static usb_status_t USB_DeviceVideoVcPowerModeControl(usb_device_video_struct_t *videoHandle,
43                                                       usb_device_control_request_struct_t *controlRequest);
44 static usb_status_t USB_DeviceVideoVcInterfaceRequest(usb_device_video_struct_t *videoHandle,
45                                                       usb_device_control_request_struct_t *controlRequest);
46 static usb_status_t USB_DeviceVideoVcCameraTerminalRequest(usb_device_video_struct_t *videoHandle,
47                                                            usb_device_control_request_struct_t *controlRequest);
48 static usb_status_t USB_DeviceVideoVcProcessingUnitRequest(usb_device_video_struct_t *videoHandle,
49                                                            usb_device_control_request_struct_t *controlRequest);
50 static usb_status_t USB_DeviceVideoVcRequest(usb_device_video_struct_t *videoHandle,
51                                              usb_device_control_request_struct_t *controlRequest);
52 static usb_status_t USB_DeviceVideoVsProbeRequest(usb_device_video_struct_t *videoHandle,
53                                                   usb_device_control_request_struct_t *controlRequest);
54 static usb_status_t USB_DeviceVideoVsCommitRequest(usb_device_video_struct_t *videoHandle,
55                                                    usb_device_control_request_struct_t *controlRequest);
56 static usb_status_t USB_DeviceVideoVsStillProbeRequest(usb_device_video_struct_t *videoHandle,
57                                                        usb_device_control_request_struct_t *controlRequest);
58 static usb_status_t USB_DeviceVideoVsStillCommitRequest(usb_device_video_struct_t *videoHandle,
59                                                         usb_device_control_request_struct_t *controlRequest);
60 static usb_status_t USB_DeviceVideoVsStillImageTriggerRequest(usb_device_video_struct_t *videoHandle,
61                                                               usb_device_control_request_struct_t *controlRequest);
62 static usb_status_t USB_DeviceVideoVsRequest(usb_device_video_struct_t *videoHandle,
63                                              usb_device_control_request_struct_t *controlRequest);
64 
65 /*******************************************************************************
66  * Variables
67  ******************************************************************************/
68 
USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE)69 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_video_struct_t
70     s_UsbDeviceVideoHandle[USB_DEVICE_CONFIG_VIDEO];
71 
72 /*******************************************************************************
73  * Code
74  ******************************************************************************/
75 
76 /*!
77  * @brief Allocate a device video class handle.
78  *
79  * This function allocates a device video class handle.
80  *
81  * @param handle          It is out parameter, is used to return pointer of the device video class handle to the caller.
82  *
83  * @retval kStatus_USB_Success              Get a device video class handle successfully.
84  * @retval kStatus_USB_Busy                 Cannot allocate a device video class handle.
85  */
86 static usb_status_t USB_DeviceVideoAllocateHandle(usb_device_video_struct_t **handle)
87 {
88     uint32_t count;
89     OSA_SR_ALLOC();
90 
91     OSA_ENTER_CRITICAL();
92     for (count = 0U; count < USB_DEVICE_CONFIG_VIDEO; count++)
93     {
94         if (NULL == s_UsbDeviceVideoHandle[count].handle)
95         {
96             *handle = &s_UsbDeviceVideoHandle[count];
97             OSA_EXIT_CRITICAL();
98             return kStatus_USB_Success;
99         }
100     }
101     OSA_EXIT_CRITICAL();
102     return kStatus_USB_Busy;
103 }
104 
105 /*!
106  * @brief Free a device video class handle.
107  *
108  * This function frees a device video class handle.
109  *
110  * @param handle          The device video class handle.
111  *
112  * @retval kStatus_USB_Success              Free device video class handle successfully.
113  */
USB_DeviceVideoFreeHandle(usb_device_video_struct_t * handle)114 static usb_status_t USB_DeviceVideoFreeHandle(usb_device_video_struct_t *handle)
115 {
116     OSA_SR_ALLOC();
117 
118     OSA_ENTER_CRITICAL();
119     handle->handle           = NULL;
120     handle->configStruct     = (usb_device_class_config_struct_t *)NULL;
121     handle->configuration    = 0U;
122     handle->controlAlternate = 0U;
123     handle->streamAlternate  = 0U;
124     OSA_EXIT_CRITICAL();
125     return kStatus_USB_Success;
126 }
127 
128 /*!
129  * @brief Interrupt IN endpoint callback function.
130  *
131  * This callback function is used to notify uplayer the transfser result of a transfer.
132  * This callback pointer is passed when the interrupt IN pipe initialized.
133  *
134  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
135  * @param message         The result of the interrupt IN pipe transfer.
136  * @param callbackParam  The parameter for this callback. It is same with
137  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the video class handle.
138  *
139  * @return A USB error code or kStatus_USB_Success.
140  */
USB_DeviceVideoControlIn(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)141 static usb_status_t USB_DeviceVideoControlIn(usb_device_handle handle,
142                                              usb_device_endpoint_callback_message_struct_t *message,
143                                              void *callbackParam)
144 {
145     usb_device_video_struct_t *videoHandle;
146     usb_status_t error = kStatus_USB_Error;
147 
148     /* Get the video class handle */
149     videoHandle = (usb_device_video_struct_t *)callbackParam;
150 
151     if (NULL == videoHandle)
152     {
153         return kStatus_USB_InvalidHandle;
154     }
155 
156     if ((NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
157     {
158         /* Notify the application control data sent by calling the video class callback.
159         ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
160         it is from the second parameter of classInit */
161         error = videoHandle->configStruct->classCallback((class_handle_t)videoHandle,
162                                                          kUSB_DeviceVideoEventControlSendResponse, message);
163     }
164 
165     return error;
166 }
167 
168 /*!
169  * @brief ISO IN endpoint callback function.
170  *
171  * This callback function is used to notify uplayer the transfser result of a transfer.
172  * This callback pointer is passed when the ISO IN pipe initialized.
173  *
174  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
175  * @param message         The result of the ISO IN pipe transfer.
176  * @param callbackParam  The parameter for this callback. It is same with
177  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the video class handle.
178  *
179  * @return A USB error code or kStatus_USB_Success.
180  */
USB_DeviceVideoStreamIn(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)181 static usb_status_t USB_DeviceVideoStreamIn(usb_device_handle handle,
182                                             usb_device_endpoint_callback_message_struct_t *message,
183                                             void *callbackParam)
184 {
185     usb_device_video_struct_t *videoHandle;
186     usb_status_t error = kStatus_USB_Error;
187 
188     /* Get the video class handle */
189     videoHandle = (usb_device_video_struct_t *)callbackParam;
190 
191     if (NULL == videoHandle)
192     {
193         return kStatus_USB_InvalidHandle;
194     }
195     videoHandle->streamInPipeBusy = 0U;
196     if ((NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
197     {
198         /* Notify the application stream data sent by calling the video class callback.
199         ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
200         it is from the second parameter of classInit */
201         error = videoHandle->configStruct->classCallback((class_handle_t)videoHandle,
202                                                          kUSB_DeviceVideoEventStreamSendResponse, message);
203     }
204 
205     return error;
206 }
207 
208 /*!
209  * @brief ISO OUT endpoint callback function.
210  *
211  * This callback function is used to notify uplayer the transfser result of a transfer.
212  * This callback pointer is passed when the ISO OUT pipe initialized.
213  *
214  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
215  * @param message         The result of the ISO OUT pipe transfer.
216  * @param callbackParam  The parameter for this callback. It is same with
217  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the video class handle.
218  *
219  * @return A USB error code or kStatus_USB_Success.
220  */
USB_DeviceVideoStreamOut(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)221 static usb_status_t USB_DeviceVideoStreamOut(usb_device_handle handle,
222                                              usb_device_endpoint_callback_message_struct_t *message,
223                                              void *callbackParam)
224 {
225     usb_device_video_struct_t *videoHandle;
226     usb_status_t error = kStatus_USB_Error;
227 
228     /* Get the video class handle */
229     videoHandle = (usb_device_video_struct_t *)callbackParam;
230 
231     if (NULL == videoHandle)
232     {
233         return kStatus_USB_InvalidHandle;
234     }
235     videoHandle->streamOutPipeBusy = 0U;
236     if ((NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
237     {
238         /* Notify the application stream data sent by calling the video class callback.
239         ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
240         it is from the second parameter of classInit */
241         error = videoHandle->configStruct->classCallback((class_handle_t)videoHandle,
242                                                          kUSB_DeviceVideoEventStreamRecvResponse, message);
243     }
244 
245     return error;
246 }
247 
248 /*!
249  * @brief Initialize the stream endpoints of the video class.
250  *
251  * This callback function is used to initialize the stream endpoints of the video class.
252  *
253  * @param videoHandle          The device video class handle. It equals the value returned from
254  * usb_device_class_config_struct_t::classHandle.
255  *
256  * @return A USB error code or kStatus_USB_Success.
257  */
USB_DeviceVideoStreamEndpointsInit(usb_device_video_struct_t * videoHandle)258 static usb_status_t USB_DeviceVideoStreamEndpointsInit(usb_device_video_struct_t *videoHandle)
259 {
260     usb_device_interface_list_t *interfaceList;
261     usb_device_interface_struct_t *interface = (usb_device_interface_struct_t *)NULL;
262     usb_status_t status                      = kStatus_USB_Error;
263 
264     /* Check the configuration is valid or not. */
265     if (0U == videoHandle->configuration)
266     {
267         return status;
268     }
269 
270     if (videoHandle->configuration > videoHandle->configStruct->classInfomation->configurations)
271     {
272         return status;
273     }
274 
275     /* Get the interface list of the new configuration. */
276     if (NULL == videoHandle->configStruct->classInfomation->interfaceList)
277     {
278         return status;
279     }
280     interfaceList = &videoHandle->configStruct->classInfomation->interfaceList[videoHandle->configuration - 1U];
281 
282     /* Find stream interface by using the alternate setting of the interface. */
283     for (uint32_t count = 0U; count < interfaceList->count; count++)
284     {
285         if ((USB_DEVICE_VIDEO_CC_VIDEO == interfaceList->interfaces[count].classCode) &&
286             (USB_DEVICE_VIDEO_SC_VIDEOSTREAMING == interfaceList->interfaces[count].subclassCode))
287         {
288             for (uint32_t index = 0U; index < interfaceList->interfaces[count].count; index++)
289             {
290                 if (interfaceList->interfaces[count].interface[index].alternateSetting == videoHandle->streamAlternate)
291                 {
292                     interface = &interfaceList->interfaces[count].interface[index];
293                     break;
294                 }
295             }
296             videoHandle->streamInterfaceNumber = interfaceList->interfaces[count].interfaceNumber;
297             break;
298         }
299     }
300     if (NULL == interface)
301     {
302         /* Return status if the stream interface is not found. */
303         return status;
304     }
305 
306     /* Keep new stream interface handle. */
307     videoHandle->streamInterfaceHandle = interface;
308 
309     /* Initialize the endpoints of the new interface. */
310     for (uint32_t count = 0U; count < interface->endpointList.count; count++)
311     {
312         usb_device_endpoint_init_struct_t epInitStruct;
313         usb_device_endpoint_callback_struct_t epCallback;
314         epInitStruct.zlt             = 0U;
315         epInitStruct.interval        = interface->endpointList.endpoint[count].interval;
316         epInitStruct.endpointAddress = interface->endpointList.endpoint[count].endpointAddress;
317         epInitStruct.maxPacketSize   = interface->endpointList.endpoint[count].maxPacketSize;
318         epInitStruct.transferType    = interface->endpointList.endpoint[count].transferType;
319 
320         if ((USB_ENDPOINT_ISOCHRONOUS == (epInitStruct.transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK)) &&
321             (USB_IN == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
322                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)))
323         {
324             epCallback.callbackFn = USB_DeviceVideoStreamIn;
325         }
326         else if ((USB_ENDPOINT_ISOCHRONOUS ==
327                   (epInitStruct.transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK)) &&
328                  (USB_OUT == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
329                               USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)))
330         {
331             epCallback.callbackFn = USB_DeviceVideoStreamOut;
332         }
333         else
334         {
335             continue;
336         }
337         epCallback.callbackParam = videoHandle;
338 
339         status = USB_DeviceInitEndpoint(videoHandle->handle, &epInitStruct, &epCallback);
340     }
341     return status;
342 }
343 
344 /*!
345  * @brief De-initialize the stream endpoints of the video class.
346  *
347  * This callback function is used to de-initialize the stream endpoints of the video class.
348  *
349  * @param videoHandle          The device video class handle. It equals the value returned from
350  * usb_device_class_config_struct_t::classHandle.
351  *
352  * @return A USB error code or kStatus_USB_Success.
353  */
USB_DeviceVideoStreamEndpointsDeinit(usb_device_video_struct_t * videoHandle)354 static usb_status_t USB_DeviceVideoStreamEndpointsDeinit(usb_device_video_struct_t *videoHandle)
355 {
356     usb_status_t status = kStatus_USB_Error;
357 
358     if (NULL == videoHandle->streamInterfaceHandle)
359     {
360         return status;
361     }
362     /* De-initialize all stream endpoints of the interface */
363     for (uint32_t count = 0U; count < videoHandle->streamInterfaceHandle->endpointList.count; count++)
364     {
365         status = USB_DeviceDeinitEndpoint(
366             videoHandle->handle, videoHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress);
367     }
368     videoHandle->streamInterfaceHandle = NULL;
369     return status;
370 }
371 
372 /*!
373  * @brief Initialize the control endpoints of the video class.
374  *
375  * This callback function is used to initialize the control endpoints of the video class.
376  *
377  * @param videoHandle          The device video class handle. It equals the value returned from
378  * usb_device_class_config_struct_t::classHandle.
379  *
380  * @return A USB error code or kStatus_USB_Success.
381  */
USB_DeviceVideoControlEndpointsInit(usb_device_video_struct_t * videoHandle)382 static usb_status_t USB_DeviceVideoControlEndpointsInit(usb_device_video_struct_t *videoHandle)
383 {
384     usb_device_interface_list_t *interfaceList;
385     usb_device_interface_struct_t *interface = (usb_device_interface_struct_t *)NULL;
386     usb_status_t status                      = kStatus_USB_Error;
387 
388     /* Check the configuration is valid or not. */
389     if (0U == videoHandle->configuration)
390     {
391         return status;
392     }
393 
394     if (videoHandle->configuration > videoHandle->configStruct->classInfomation->configurations)
395     {
396         return status;
397     }
398 
399     /* Get the control interface list of the new configuration. */
400     if (NULL == videoHandle->configStruct->classInfomation->interfaceList)
401     {
402         return status;
403     }
404     interfaceList = &videoHandle->configStruct->classInfomation->interfaceList[videoHandle->configuration - 1U];
405 
406     /* Find control interface by using the alternate setting of the interface. */
407     for (uint32_t count = 0U; count < interfaceList->count; count++)
408     {
409         if ((USB_DEVICE_VIDEO_CC_VIDEO == interfaceList->interfaces[count].classCode) &&
410             (USB_DEVICE_VIDEO_SC_VIDEOCONTROL == interfaceList->interfaces[count].subclassCode))
411         {
412             for (uint32_t index = 0U; index < interfaceList->interfaces[count].count; index++)
413             {
414                 if (interfaceList->interfaces[count].interface[index].alternateSetting == videoHandle->controlAlternate)
415                 {
416                     interface = &interfaceList->interfaces[count].interface[index];
417                     break;
418                 }
419             }
420             videoHandle->controlInterfaceNumber = interfaceList->interfaces[count].interfaceNumber;
421             break;
422         }
423     }
424     if (NULL == interface)
425     {
426         /* Return status if the control interface is not found. */
427         return status;
428     }
429     /* Keep new control interface handle. */
430     videoHandle->controlInterfaceHandle = interface;
431 
432     /* Initialize the control endpoints of the new interface. */
433     for (uint32_t count = 0U; count < interface->endpointList.count; count++)
434     {
435         usb_device_endpoint_init_struct_t epInitStruct;
436         usb_device_endpoint_callback_struct_t epCallback;
437         epInitStruct.zlt             = 0U;
438         epInitStruct.endpointAddress = interface->endpointList.endpoint[count].endpointAddress;
439         epInitStruct.maxPacketSize   = interface->endpointList.endpoint[count].maxPacketSize;
440         epInitStruct.transferType    = interface->endpointList.endpoint[count].transferType;
441 
442         if ((USB_ENDPOINT_INTERRUPT == (epInitStruct.transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK)) &&
443             (USB_IN == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
444                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)))
445         {
446             epCallback.callbackFn = USB_DeviceVideoControlIn;
447         }
448         else
449         {
450             continue;
451         }
452         epCallback.callbackParam = videoHandle;
453 
454         status = USB_DeviceInitEndpoint(videoHandle->handle, &epInitStruct, &epCallback);
455     }
456     return status;
457 }
458 
459 /*!
460  * @brief De-initialize the control endpoints of the video class.
461  *
462  * This callback function is used to de-initialize the control endpoints of the video class.
463  *
464  * @param videoHandle          The device video class handle. It equals the value returned from
465  * usb_device_class_config_struct_t::classHandle.
466  *
467  * @return A USB error code or kStatus_USB_Success.
468  */
USB_DeviceVideoControlEndpointsDeinit(usb_device_video_struct_t * videoHandle)469 static usb_status_t USB_DeviceVideoControlEndpointsDeinit(usb_device_video_struct_t *videoHandle)
470 {
471     usb_status_t status = kStatus_USB_Error;
472 
473     if (NULL == videoHandle->controlInterfaceHandle)
474     {
475         return status;
476     }
477     /* De-initialize all control endpoints of the interface */
478     for (uint32_t count = 0U; count < videoHandle->controlInterfaceHandle->endpointList.count; count++)
479     {
480         status = USB_DeviceDeinitEndpoint(
481             videoHandle->handle, videoHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress);
482     }
483     videoHandle->controlInterfaceHandle = NULL;
484     return status;
485 }
486 
487 /*!
488  * @brief Handle the video device vc power modex control request.
489  *
490  * This callback function is used to handle the video device vc power modex control request.
491  *
492  * @param videoHandle          The device video class handle. It equals the value returned from
493  * usb_device_class_config_struct_t::classHandle.
494  * @param controlRequest       The pointer of the control request structure.
495  *
496  * @return A USB error code or kStatus_USB_Success.
497  */
USB_DeviceVideoVcPowerModeControl(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)498 static usb_status_t USB_DeviceVideoVcPowerModeControl(usb_device_video_struct_t *videoHandle,
499                                                       usb_device_control_request_struct_t *controlRequest)
500 {
501     usb_status_t status = kStatus_USB_InvalidRequest;
502     uint32_t command    = 0U;
503     uint32_t length     = 1U;
504 
505     switch (controlRequest->setup->bRequest)
506     {
507         case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
508             command = USB_DEVICE_VIDEO_SET_CUR_VC_POWER_MODE_CONTROL;
509             break;
510         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
511             command = USB_DEVICE_VIDEO_GET_CUR_VC_POWER_MODE_CONTROL;
512             break;
513         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
514             command = USB_DEVICE_VIDEO_GET_INFO_VC_POWER_MODE_CONTROL;
515             break;
516         default:
517             /*no action*/
518             break;
519     }
520     if ((0U != command) && (NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
521     {
522         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
523         it is from the second parameter of classInit */
524         status = videoHandle->configStruct->classCallback((class_handle_t)videoHandle, command, controlRequest);
525         if (controlRequest->length > length)
526         {
527             status = kStatus_USB_InvalidRequest;
528         }
529     }
530     return status;
531 }
532 
533 /*!
534  * @brief Handle the video device control interface class-specific request.
535  *
536  * This callback function is used to handle the video device control pipe class-specific request.
537  *
538  * @param videoHandle          The device video class handle. It equals the value returned from
539  * usb_device_class_config_struct_t::classHandle.
540  * @param controlRequest       The pointer of the control request structure.
541  *
542  * @return A USB error code or kStatus_USB_Success.
543  */
USB_DeviceVideoVcInterfaceRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)544 static usb_status_t USB_DeviceVideoVcInterfaceRequest(usb_device_video_struct_t *videoHandle,
545                                                       usb_device_control_request_struct_t *controlRequest)
546 {
547     usb_status_t status = kStatus_USB_InvalidRequest;
548     uint8_t cs          = (uint8_t)((controlRequest->setup->wValue >> 0x08U) & 0xFFU);
549 
550     if (USB_DEVICE_VIDEO_VC_VIDEO_POWER_MODE_CONTROL == cs)
551     {
552         /* handle the video device vc power modex control request */
553         status = USB_DeviceVideoVcPowerModeControl(videoHandle, controlRequest);
554     }
555     else if (USB_DEVICE_VIDEO_VC_REQUEST_ERROR_CODE_CONTROL == cs)
556     {
557     }
558     else
559     {
560         /*no action*/
561     }
562     return status;
563 }
564 
565 /*!
566  * @brief Handle the video device camera terminal control request.
567  *
568  * This callback function is used to handle the video device camera terminal control request.
569  *
570  * @param videoHandle          The device video class handle. It equals the value returned from
571  * usb_device_class_config_struct_t::classHandle.
572  * @param controlRequest       The pointer of the control request structure.
573  *
574  * @return A USB error code or kStatus_USB_Success.
575  */
USB_DeviceVideoVcCameraTerminalRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)576 static usb_status_t USB_DeviceVideoVcCameraTerminalRequest(usb_device_video_struct_t *videoHandle,
577                                                            usb_device_control_request_struct_t *controlRequest)
578 {
579     usb_status_t status = kStatus_USB_InvalidRequest;
580     uint8_t cs          = (uint8_t)((controlRequest->setup->wValue >> 0x08U) & 0xFFU);
581 
582     switch (cs)
583     {
584         case USB_DEVICE_VIDEO_CT_SCANNING_MODE_CONTROL:
585             break;
586         case USB_DEVICE_VIDEO_CT_AE_MODE_CONTROL:
587             break;
588         case USB_DEVICE_VIDEO_CT_AE_PRIORITY_CONTROL:
589             break;
590         case USB_DEVICE_VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
591             break;
592         case USB_DEVICE_VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL:
593             break;
594         case USB_DEVICE_VIDEO_CT_FOCUS_ABSOLUTE_CONTROL:
595             break;
596         case USB_DEVICE_VIDEO_CT_FOCUS_RELATIVE_CONTROL:
597             break;
598         case USB_DEVICE_VIDEO_CT_FOCUS_AUTO_CONTROL:
599             break;
600         case USB_DEVICE_VIDEO_CT_IRIS_ABSOLUTE_CONTROL:
601             break;
602         case USB_DEVICE_VIDEO_CT_IRIS_RELATIVE_CONTROL:
603             break;
604         case USB_DEVICE_VIDEO_CT_ZOOM_ABSOLUTE_CONTROL:
605             break;
606         case USB_DEVICE_VIDEO_CT_ZOOM_RELATIVE_CONTROL:
607             break;
608         case USB_DEVICE_VIDEO_CT_PANTILT_ABSOLUTE_CONTROL:
609             break;
610         case USB_DEVICE_VIDEO_CT_PANTILT_RELATIVE_CONTROL:
611             break;
612         case USB_DEVICE_VIDEO_CT_ROLL_ABSOLUTE_CONTROL:
613             break;
614         case USB_DEVICE_VIDEO_CT_ROLL_RELATIVE_CONTROL:
615             break;
616         case USB_DEVICE_VIDEO_CT_PRIVACY_CONTROL:
617             break;
618         case USB_DEVICE_VIDEO_CT_FOCUS_SIMPLE_CONTROL:
619             break;
620         case USB_DEVICE_VIDEO_CT_WINDOW_CONTROL:
621             break;
622         case USB_DEVICE_VIDEO_CT_REGION_OF_INTEREST_CONTROL:
623             break;
624         default:
625             /*no action*/
626             break;
627     }
628     return status;
629 }
630 
631 /*!
632  * @brief Handle the video device processing uint control request.
633  *
634  * This callback function is used to handle the video device processing uint control request.
635  *
636  * @param videoHandle          The device video class handle. It equals the value returned from
637  * usb_device_class_config_struct_t::classHandle.
638  * @param controlRequest       The pointer of the control request structure.
639  *
640  * @return A USB error code or kStatus_USB_Success.
641  */
USB_DeviceVideoVcProcessingUnitRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)642 static usb_status_t USB_DeviceVideoVcProcessingUnitRequest(usb_device_video_struct_t *videoHandle,
643                                                            usb_device_control_request_struct_t *controlRequest)
644 {
645     usb_status_t status = kStatus_USB_InvalidRequest;
646     uint8_t cs          = (uint8_t)((controlRequest->setup->wValue >> 0x08U) & 0xFFU);
647 
648     switch (cs)
649     {
650         case USB_DEVICE_VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL:
651             break;
652         case USB_DEVICE_VIDEO_PU_BRIGHTNESS_CONTROL:
653             break;
654         case USB_DEVICE_VIDEO_PU_CONTRAST_CONTROL:
655             break;
656         case USB_DEVICE_VIDEO_PU_GAIN_CONTROL:
657             break;
658         case USB_DEVICE_VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL:
659             break;
660         case USB_DEVICE_VIDEO_PU_HUE_CONTROL:
661             break;
662         case USB_DEVICE_VIDEO_PU_SATURATION_CONTROL:
663             break;
664         case USB_DEVICE_VIDEO_PU_SHARPNESS_CONTROL:
665             break;
666         case USB_DEVICE_VIDEO_PU_GAMMA_CONTROL:
667             break;
668         case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
669             break;
670         case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
671             break;
672         case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL:
673             break;
674         case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
675             break;
676         case USB_DEVICE_VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL:
677             break;
678         case USB_DEVICE_VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
679             break;
680         case USB_DEVICE_VIDEO_PU_HUE_AUTO_CONTROL:
681             break;
682         case USB_DEVICE_VIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL:
683             break;
684         case USB_DEVICE_VIDEO_PU_ANALOG_LOCK_STATUS_CONTROL:
685             break;
686         case USB_DEVICE_VIDEO_PU_CONTRAST_AUTO_CONTROL:
687             break;
688         default:
689             /*no action*/
690             break;
691     }
692 
693     return status;
694 }
695 
696 /*!
697  * @brief Handle the video device control request.
698  *
699  * This callback function is used to handle the video device control request,
700  * including the control interface, uint or terminal control.
701  *
702  * @param videoHandle          The device video class handle. It equals the value returned from
703  * usb_device_class_config_struct_t::classHandle.
704  * @param controlRequest       The pointer of the control request structure.
705  *
706  * @return A USB error code or kStatus_USB_Success.
707  */
USB_DeviceVideoVcRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)708 static usb_status_t USB_DeviceVideoVcRequest(usb_device_video_struct_t *videoHandle,
709                                              usb_device_control_request_struct_t *controlRequest)
710 {
711     usb_device_video_entities_struct_t *entity_list;
712     usb_status_t status = kStatus_USB_InvalidRequest;
713     uint8_t entityId    = (uint8_t)(controlRequest->setup->wIndex >> 0x08U);
714 
715     if (NULL == videoHandle->controlInterfaceHandle)
716     {
717         return status;
718     }
719 
720     /* Get the video class-specific information. */
721     entity_list = (usb_device_video_entities_struct_t *)videoHandle->controlInterfaceHandle->classSpecific;
722 
723     if (0U == entityId)
724     {
725         /* Handle the video control interface request. */
726         status = USB_DeviceVideoVcInterfaceRequest(videoHandle, controlRequest);
727     }
728     else
729     {
730         for (uint32_t i = 0U; i < entity_list->count; i++)
731         {
732             if (entityId == entity_list->entity[i].entityId)
733             {
734                 switch (entity_list->entity[i].entityType)
735                 {
736                     case USB_DESCRIPTOR_SUBTYPE_VIDEO_VC_INPUT_TERMINAL:
737                         if (USB_DEVICE_VIDEO_ITT_CAMERA == entity_list->entity[i].terminalType)
738                         {
739                             /* Handle the video camera terminal control request. */
740                             status = USB_DeviceVideoVcCameraTerminalRequest(videoHandle, controlRequest);
741                         }
742                         break;
743                     case USB_DESCRIPTOR_SUBTYPE_VIDEO_VC_OUTPUT_TERMINAL:
744                         break;
745                     case USB_DESCRIPTOR_SUBTYPE_VIDEO_VC_SELECTOR_UNIT:
746                         break;
747                     case USB_DESCRIPTOR_SUBTYPE_VIDEO_VC_PROCESSING_UNIT:
748                         /* Handle the video processing uint control request. */
749                         status = USB_DeviceVideoVcProcessingUnitRequest(videoHandle, controlRequest);
750                         break;
751                     case USB_DESCRIPTOR_SUBTYPE_VIDEO_VC_EXTENSION_UNIT:
752                         break;
753                     case USB_DESCRIPTOR_SUBTYPE_VIDEO_VC_ENCODING_UNIT:
754                         break;
755                     default:
756                         /*no action*/
757                         break;
758                 }
759             }
760         }
761     }
762     return status;
763 }
764 
765 /*!
766  * @brief Handle the video device probe control request.
767  *
768  * This callback function is used to handle the video device probe control request,
769  *
770  * @param videoHandle          The device video class handle. It equals the value returned from
771  * usb_device_class_config_struct_t::classHandle.
772  * @param controlRequest       The pointer of the control request structure.
773  *
774  * @return A USB error code or kStatus_USB_Success.
775  */
USB_DeviceVideoVsProbeRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)776 static usb_status_t USB_DeviceVideoVsProbeRequest(usb_device_video_struct_t *videoHandle,
777                                                   usb_device_control_request_struct_t *controlRequest)
778 {
779     usb_status_t status = kStatus_USB_InvalidRequest;
780     uint32_t command    = 0U;
781     uint32_t length     = sizeof(usb_device_video_probe_and_commit_controls_struct_t);
782 
783     switch (controlRequest->setup->bRequest)
784     {
785         case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
786             command = USB_DEVICE_VIDEO_SET_CUR_VS_PROBE_CONTROL;
787             break;
788         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
789             command = USB_DEVICE_VIDEO_GET_CUR_VS_PROBE_CONTROL;
790             break;
791         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN:
792             command = USB_DEVICE_VIDEO_GET_MIN_VS_PROBE_CONTROL;
793             break;
794         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX:
795             command = USB_DEVICE_VIDEO_GET_MAX_VS_PROBE_CONTROL;
796             break;
797         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES:
798             command = USB_DEVICE_VIDEO_GET_RES_VS_PROBE_CONTROL;
799             break;
800         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
801             command = USB_DEVICE_VIDEO_GET_LEN_VS_PROBE_CONTROL;
802             length  = 1U;
803             break;
804         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
805             command = USB_DEVICE_VIDEO_GET_INFO_VS_PROBE_CONTROL;
806             length  = 1U;
807             break;
808         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF:
809             command = USB_DEVICE_VIDEO_GET_DEF_VS_PROBE_CONTROL;
810             break;
811         default:
812             /*no action*/
813             break;
814     }
815     if ((0U != command) && (NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
816     {
817         /*ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
818   it is from the second parameter of classInit*/
819         status = videoHandle->configStruct->classCallback((class_handle_t)videoHandle, command, controlRequest);
820         if (controlRequest->length > length)
821         {
822             status = kStatus_USB_InvalidRequest;
823         }
824     }
825     return status;
826 }
827 
828 /*!
829  * @brief Handle the video device commit control request.
830  *
831  * This callback function is used to handle the video device commit control request,
832  *
833  * @param videoHandle          The device video class handle. It equals the value returned from
834  * usb_device_class_config_struct_t::classHandle.
835  * @param controlRequest       The pointer of the control request structure.
836  *
837  * @return A USB error code or kStatus_USB_Success.
838  */
USB_DeviceVideoVsCommitRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)839 static usb_status_t USB_DeviceVideoVsCommitRequest(usb_device_video_struct_t *videoHandle,
840                                                    usb_device_control_request_struct_t *controlRequest)
841 {
842     usb_status_t status = kStatus_USB_InvalidRequest;
843     uint32_t command    = 0U;
844     uint32_t length     = sizeof(usb_device_video_probe_and_commit_controls_struct_t);
845 
846     switch (controlRequest->setup->bRequest)
847     {
848         case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
849             command = USB_DEVICE_VIDEO_SET_CUR_VS_COMMIT_CONTROL;
850             break;
851         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
852             command = USB_DEVICE_VIDEO_GET_CUR_VS_COMMIT_CONTROL;
853             break;
854         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
855             command = USB_DEVICE_VIDEO_GET_LEN_VS_COMMIT_CONTROL;
856             length  = 1U;
857             break;
858         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
859             command = USB_DEVICE_VIDEO_GET_INFO_VS_COMMIT_CONTROL;
860             length  = 1U;
861             break;
862         default:
863             /*no action*/
864             break;
865     }
866     if ((0U != command) && (NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
867     {
868         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
869         it is from the second parameter of classInit */
870         status = videoHandle->configStruct->classCallback((class_handle_t)videoHandle, command, controlRequest);
871         if (controlRequest->length > length)
872         {
873             status = kStatus_USB_InvalidRequest;
874         }
875     }
876     return status;
877 }
878 
879 /*!
880  * @brief Handle the video device still probe control request.
881  *
882  * This callback function is used to handle the video device still probe control request,
883  *
884  * @param videoHandle          The device video class handle. It equals the value returned from
885  * usb_device_class_config_struct_t::classHandle.
886  * @param controlRequest       The pointer of the control request structure.
887  *
888  * @return A USB error code or kStatus_USB_Success.
889  */
USB_DeviceVideoVsStillProbeRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)890 static usb_status_t USB_DeviceVideoVsStillProbeRequest(usb_device_video_struct_t *videoHandle,
891                                                        usb_device_control_request_struct_t *controlRequest)
892 {
893     usb_status_t status = kStatus_USB_InvalidRequest;
894     uint32_t command    = 0U;
895     uint32_t length     = sizeof(usb_device_video_still_probe_and_commit_controls_struct_t);
896 
897     switch (controlRequest->setup->bRequest)
898     {
899         case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
900             command = USB_DEVICE_VIDEO_SET_CUR_VS_STILL_PROBE_CONTROL;
901             break;
902         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
903             command = USB_DEVICE_VIDEO_GET_CUR_VS_STILL_PROBE_CONTROL;
904             break;
905         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN:
906             command = USB_DEVICE_VIDEO_GET_MIN_VS_STILL_PROBE_CONTROL;
907             break;
908         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX:
909             command = USB_DEVICE_VIDEO_GET_MAX_VS_STILL_PROBE_CONTROL;
910             break;
911         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
912             command = USB_DEVICE_VIDEO_GET_LEN_VS_STILL_PROBE_CONTROL;
913             length  = 1U;
914             break;
915         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
916             command = USB_DEVICE_VIDEO_GET_INFO_VS_STILL_PROBE_CONTROL;
917             length  = 1U;
918             break;
919         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF:
920             command = USB_DEVICE_VIDEO_GET_DEF_VS_STILL_PROBE_CONTROL;
921             break;
922         default:
923             /*no action*/
924             break;
925     }
926     if ((0U != command) && (NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
927     {
928         /*ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
929   it is from the second parameter of classInit*/
930         status = videoHandle->configStruct->classCallback((class_handle_t)videoHandle, command, controlRequest);
931         if (controlRequest->length > length)
932         {
933             status = kStatus_USB_InvalidRequest;
934         }
935     }
936     return status;
937 }
938 
939 /*!
940  * @brief Handle the video device still commit control request.
941  *
942  * This callback function is used to handle the video device still commit control request,
943  *
944  * @param videoHandle          The device video class handle. It equals the value returned from
945  * usb_device_class_config_struct_t::classHandle.
946  * @param controlRequest       The pointer of the control request structure.
947  *
948  * @return A USB error code or kStatus_USB_Success.
949  */
USB_DeviceVideoVsStillCommitRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)950 static usb_status_t USB_DeviceVideoVsStillCommitRequest(usb_device_video_struct_t *videoHandle,
951                                                         usb_device_control_request_struct_t *controlRequest)
952 {
953     usb_status_t status = kStatus_USB_InvalidRequest;
954     uint32_t command    = 0U;
955     uint32_t length     = sizeof(usb_device_video_still_probe_and_commit_controls_struct_t);
956 
957     switch (controlRequest->setup->bRequest)
958     {
959         case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
960             command = USB_DEVICE_VIDEO_SET_CUR_VS_STILL_COMMIT_CONTROL;
961             break;
962         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
963             command = USB_DEVICE_VIDEO_GET_CUR_VS_STILL_COMMIT_CONTROL;
964             break;
965         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
966             command = USB_DEVICE_VIDEO_GET_LEN_VS_STILL_COMMIT_CONTROL;
967             length  = 1U;
968             break;
969         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
970             command = USB_DEVICE_VIDEO_GET_INFO_VS_STILL_COMMIT_CONTROL;
971             length  = 1U;
972             break;
973         default:
974             /*no action*/
975             break;
976     }
977     if ((0U != command) && (NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
978     {
979         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
980         it is from the second parameter of classInit */
981         status = videoHandle->configStruct->classCallback((class_handle_t)videoHandle, command, controlRequest);
982         if (controlRequest->length > length)
983         {
984             status = kStatus_USB_InvalidRequest;
985         }
986     }
987     return status;
988 }
989 
990 /*!
991  * @brief Handle the video device still image trigger control request.
992  *
993  * This callback function is used to handle the video device still image trigger control request,
994  *
995  * @param videoHandle          The device video class handle. It equals the value returned from
996  * usb_device_class_config_struct_t::classHandle.
997  * @param controlRequest       The pointer of the control request structure.
998  *
999  * @return A USB error code or kStatus_USB_Success.
1000  */
USB_DeviceVideoVsStillImageTriggerRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)1001 static usb_status_t USB_DeviceVideoVsStillImageTriggerRequest(usb_device_video_struct_t *videoHandle,
1002                                                               usb_device_control_request_struct_t *controlRequest)
1003 {
1004     usb_status_t status = kStatus_USB_InvalidRequest;
1005     uint32_t command    = 0U;
1006     uint32_t length     = 1U;
1007 
1008     switch (controlRequest->setup->bRequest)
1009     {
1010         case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
1011             command = USB_DEVICE_VIDEO_SET_CUR_VS_STILL_IMAGE_TRIGGER_CONTROL;
1012             break;
1013         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
1014             command = USB_DEVICE_VIDEO_GET_CUR_VS_STILL_IMAGE_TRIGGER_CONTROL;
1015             break;
1016         case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
1017             command = USB_DEVICE_VIDEO_GET_INFO_VS_STILL_IMAGE_TRIGGER_CONTROL;
1018             break;
1019         default:
1020             /*no action*/
1021             break;
1022     }
1023     if ((0U != command) && (NULL != videoHandle->configStruct) && (NULL != videoHandle->configStruct->classCallback))
1024     {
1025         /* ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1026         it is from the second parameter of classInit */
1027         status = videoHandle->configStruct->classCallback((class_handle_t)videoHandle, command, controlRequest);
1028         if (controlRequest->length > length)
1029         {
1030             status = kStatus_USB_InvalidRequest;
1031         }
1032     }
1033     return status;
1034 }
1035 
1036 /*!
1037  * @brief Handle the video device stream interface control request.
1038  *
1039  * This callback function is used to handle the video devicestream interface controll request,
1040  *
1041  * @param videoHandle          The device video class handle. It equals the value returned from
1042  * usb_device_class_config_struct_t::classHandle.
1043  * @param controlRequest       The pointer of the control request structure.
1044  *
1045  * @return A USB error code or kStatus_USB_Success.
1046  */
USB_DeviceVideoVsRequest(usb_device_video_struct_t * videoHandle,usb_device_control_request_struct_t * controlRequest)1047 static usb_status_t USB_DeviceVideoVsRequest(usb_device_video_struct_t *videoHandle,
1048                                              usb_device_control_request_struct_t *controlRequest)
1049 {
1050     usb_status_t status = kStatus_USB_InvalidRequest;
1051     uint8_t cs          = (uint8_t)((controlRequest->setup->wValue >> 0x08U) & 0xFFU);
1052 
1053     switch (cs)
1054     {
1055         case USB_DEVICE_VIDEO_VS_PROBE_CONTROL:
1056             /* Handle device video probe control request. */
1057             status = USB_DeviceVideoVsProbeRequest(videoHandle, controlRequest);
1058             break;
1059         case USB_DEVICE_VIDEO_VS_COMMIT_CONTROL:
1060             /* Handle device video commit control request. */
1061             status = USB_DeviceVideoVsCommitRequest(videoHandle, controlRequest);
1062             break;
1063         case USB_DEVICE_VIDEO_VS_STILL_PROBE_CONTROL:
1064             /* Handle device video still probe control request. */
1065             status = USB_DeviceVideoVsStillProbeRequest(videoHandle, controlRequest);
1066             break;
1067         case USB_DEVICE_VIDEO_VS_STILL_COMMIT_CONTROL:
1068             /* Handle device video still commit control request. */
1069             status = USB_DeviceVideoVsStillCommitRequest(videoHandle, controlRequest);
1070             break;
1071         case USB_DEVICE_VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL:
1072             /* Handle device video still image trigger control request. */
1073             status = USB_DeviceVideoVsStillImageTriggerRequest(videoHandle, controlRequest);
1074             break;
1075         case USB_DEVICE_VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
1076             break;
1077         case USB_DEVICE_VIDEO_VS_GENERATE_KEY_FRAME_CONTROL:
1078             break;
1079         case USB_DEVICE_VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL:
1080             break;
1081         case USB_DEVICE_VIDEO_VS_SYNCH_DELAY_CONTROL:
1082             break;
1083         default:
1084             /*no action*/
1085             break;
1086     }
1087 
1088     return status;
1089 }
1090 
1091 /*!
1092  * @brief Handle the event passed to the video class.
1093  *
1094  * This function handles the event passed to the video class.
1095  *
1096  * @param handle          The video class handle, got from the usb_device_class_config_struct_t::classHandle.
1097  * @param event           The event codes. Please refer to the enumeration usb_device_class_event_t.
1098  * @param param           The param type is determined by the event code.
1099  *
1100  * @return A USB error code or kStatus_USB_Success.
1101  * @retval kStatus_USB_Success              Free device handle successfully.
1102  * @retval kStatus_USB_InvalidParameter     The device handle not be found.
1103  * @retval kStatus_USB_InvalidRequest       The request is invalid, and the control pipe will be stalled by the caller.
1104  */
USB_DeviceVideoEvent(void * handle,uint32_t event,void * param)1105 usb_status_t USB_DeviceVideoEvent(void *handle, uint32_t event, void *param)
1106 {
1107     usb_device_video_struct_t *videoHandle;
1108     ;
1109     usb_status_t error = kStatus_USB_Error;
1110     uint16_t interfaceAlternate;
1111     uint8_t *temp8;
1112     uint8_t alternate;
1113     usb_device_class_event_t eventCode = (usb_device_class_event_t)event;
1114     if ((NULL == param) || (NULL == handle))
1115     {
1116         return kStatus_USB_InvalidHandle;
1117     }
1118 
1119     /* Get the video class handle. */
1120     videoHandle = (usb_device_video_struct_t *)handle;
1121 
1122     switch (eventCode)
1123     {
1124         case kUSB_DeviceClassEventDeviceReset:
1125             /* Bus reset, clear the configuration. */
1126             videoHandle->configuration     = 0U;
1127             videoHandle->streamOutPipeBusy = 0U;
1128             videoHandle->streamInPipeBusy  = 0U;
1129             error                          = kStatus_USB_Success;
1130             break;
1131         case kUSB_DeviceClassEventSetConfiguration:
1132             /* Get the new configuration. */
1133             temp8 = ((uint8_t *)param);
1134             if (NULL == videoHandle->configStruct)
1135             {
1136                 break;
1137             }
1138             if (*temp8 == videoHandle->configuration)
1139             {
1140                 error = kStatus_USB_Success;
1141                 break;
1142             }
1143             /* De-initialize the endpoints when current configuration is none zero. */
1144             if (0U != videoHandle->configuration)
1145             {
1146 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1147                 if ((kStatus_USB_Success != USB_DeviceVideoControlEndpointsDeinit(videoHandle)) ||
1148                     (kStatus_USB_Success != USB_DeviceVideoStreamEndpointsDeinit(videoHandle)))
1149                 {
1150                     return kStatus_USB_Error;
1151                 }
1152 #else
1153                 (void)USB_DeviceVideoControlEndpointsDeinit(videoHandle);
1154                 (void)USB_DeviceVideoStreamEndpointsDeinit(videoHandle);
1155 #endif
1156             }
1157             /* Save new configuration. */
1158             videoHandle->configuration = *temp8;
1159             /* Clear the alternate setting value. */
1160             videoHandle->controlAlternate = 0U;
1161             /* Clear the alternate setting value. */
1162             videoHandle->streamAlternate        = 0U;
1163             videoHandle->controlInterfaceHandle = NULL;
1164             videoHandle->streamInterfaceHandle  = NULL;
1165             /* Initialize the control endpoints of the new current configuration by using the alternate setting 0. */
1166             error = USB_DeviceVideoControlEndpointsInit(videoHandle);
1167             /*for cvoerity unused value*/
1168             if (kStatus_USB_Success != error)
1169             {
1170 #ifdef DEBUG
1171                 usb_echo("kUSB_DeviceClassEventSetConfiguration, USB_DeviceInitEndpoint fail\r\n");
1172 #endif
1173             }
1174             /* Initialize the stream endpoints of the new current configuration by using the alternate setting 0. */
1175             error = USB_DeviceVideoStreamEndpointsInit(videoHandle);
1176             break;
1177         case kUSB_DeviceClassEventSetInterface:
1178             if (NULL == videoHandle->configStruct)
1179             {
1180                 break;
1181             }
1182             /* Get the new alternate setting of the interface */
1183             interfaceAlternate = *((uint16_t *)param);
1184             /* Get the alternate setting value */
1185             alternate = (uint8_t)(interfaceAlternate & 0xFFU);
1186 
1187             /* Whether the interface belongs to the class. */
1188             if (videoHandle->controlInterfaceNumber == ((uint8_t)(interfaceAlternate >> 8U)))
1189             {
1190                 /* When the interface is control interface. */
1191                 /* Only handle new alternate setting. */
1192                 if (alternate == videoHandle->controlAlternate)
1193                 {
1194                     error = kStatus_USB_Success;
1195                     break;
1196                 }
1197                 /* De-initialize old endpoints */
1198 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1199                 if (kStatus_USB_Success != USB_DeviceVideoControlEndpointsDeinit(videoHandle))
1200                 {
1201                     return kStatus_USB_Error;
1202                 }
1203 #else
1204                 (void)USB_DeviceVideoControlEndpointsDeinit(videoHandle);
1205 #endif
1206                 videoHandle->controlAlternate = alternate;
1207                 /* Initialize new endpoints */
1208                 error = USB_DeviceVideoControlEndpointsInit(videoHandle);
1209             }
1210             else if (videoHandle->streamInterfaceNumber == ((uint8_t)(interfaceAlternate >> 8U)))
1211             {
1212                 /* When the interface is stream interface. */
1213                 /* Only handle new alternate setting. */
1214                 if (alternate == videoHandle->streamAlternate)
1215                 {
1216                     error = kStatus_USB_Success;
1217                     break;
1218                 }
1219                 /* De-initialize old endpoints */
1220                 error                        = USB_DeviceVideoStreamEndpointsDeinit(videoHandle);
1221                 videoHandle->streamAlternate = alternate;
1222                 /* Initialize new endpoints */
1223                 error = USB_DeviceVideoStreamEndpointsInit(videoHandle);
1224             }
1225             else
1226             {
1227                 /*no action*/
1228             }
1229             break;
1230         case kUSB_DeviceClassEventSetEndpointHalt:
1231             if (NULL == videoHandle->configStruct)
1232             {
1233                 break;
1234             }
1235             /* Get the endpoint address */
1236             temp8 = ((uint8_t *)param);
1237             if (NULL != videoHandle->controlInterfaceHandle)
1238             {
1239                 for (uint32_t count = 0U; count < videoHandle->controlInterfaceHandle->endpointList.count; count++)
1240                 {
1241                     if (*temp8 == videoHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1242                     {
1243                         /* Only stall the endpoint belongs to control interface of the class */
1244                         error = USB_DeviceStallEndpoint(videoHandle->handle, *temp8);
1245                     }
1246                 }
1247             }
1248             if (NULL != videoHandle->streamInterfaceHandle)
1249             {
1250                 for (uint32_t count = 0U; count < videoHandle->streamInterfaceHandle->endpointList.count; count++)
1251                 {
1252                     if (*temp8 == videoHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1253                     {
1254                         /* Only stall the endpoint belongs to stream interface of the class */
1255                         error = USB_DeviceStallEndpoint(videoHandle->handle, *temp8);
1256                     }
1257                 }
1258             }
1259             break;
1260         case kUSB_DeviceClassEventClearEndpointHalt:
1261             if (NULL == videoHandle->configStruct)
1262             {
1263                 break;
1264             }
1265             /* Get the endpoint address */
1266             temp8 = ((uint8_t *)param);
1267             if (NULL != videoHandle->controlInterfaceHandle)
1268             {
1269                 for (uint32_t count = 0U; count < videoHandle->controlInterfaceHandle->endpointList.count; count++)
1270                 {
1271                     if (*temp8 == videoHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1272                     {
1273                         /* Only un-stall the endpoint belongs to control interface of the class */
1274                         error = USB_DeviceUnstallEndpoint(videoHandle->handle, *temp8);
1275                     }
1276                 }
1277             }
1278             if (NULL != videoHandle->streamInterfaceHandle)
1279             {
1280                 for (uint32_t count = 0U; count < videoHandle->streamInterfaceHandle->endpointList.count; count++)
1281                 {
1282                     if (*temp8 == videoHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1283                     {
1284                         /* Only un-stall the endpoint belongs to stream interface of the class */
1285                         error = USB_DeviceUnstallEndpoint(videoHandle->handle, *temp8);
1286                     }
1287                 }
1288             }
1289             break;
1290         case kUSB_DeviceClassEventClassRequest:
1291         {
1292             /* Handle the video class specific request. */
1293             usb_device_control_request_struct_t *controlRequest = (usb_device_control_request_struct_t *)param;
1294             uint8_t interface_index                             = (uint8_t)controlRequest->setup->wIndex;
1295             uint8_t process;
1296 
1297             if ((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) !=
1298                 USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
1299             {
1300                 break;
1301             }
1302 
1303             if ((videoHandle->controlInterfaceNumber != interface_index) &&
1304                 (videoHandle->streamInterfaceNumber != interface_index))
1305             {
1306                 break;
1307             }
1308 
1309             process = 0U;
1310             error   = kStatus_USB_InvalidRequest;
1311             switch (controlRequest->setup->bRequest)
1312             {
1313                 /* Set */
1314                 case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
1315                 case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR_ALL:
1316                     if (controlRequest->setup->bmRequestType == USB_DEVICE_VIDEO_SET_REQUEST_INTERFACE)
1317                     {
1318                         if (0U != controlRequest->isSetup)
1319                         {
1320                             /* Get the buffer to receive the data sent from the host. */
1321                             if ((NULL != videoHandle->configStruct) &&
1322                                 (NULL != videoHandle->configStruct->classCallback))
1323                             {
1324                                 /*ClassCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1325                                                   it is from the second parameter of classInit*/
1326                                 error = videoHandle->configStruct->classCallback(
1327                                     (class_handle_t)videoHandle, kUSB_DeviceVideoEventClassRequestBuffer,
1328                                     controlRequest);
1329                             }
1330                         }
1331                         else
1332                         {
1333                             process = 1;
1334                         }
1335                     }
1336                     break;
1337                 /* Get */
1338                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
1339                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN:
1340                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX:
1341                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES:
1342                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
1343                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
1344                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF:
1345                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR_ALL:
1346                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN_ALL:
1347                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX_ALL:
1348                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES_ALL:
1349                 case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF_ALL:
1350                     if (controlRequest->setup->bmRequestType == USB_DEVICE_VIDEO_GET_REQUEST_INTERFACE)
1351                     {
1352                         process = 1;
1353                     }
1354                     break;
1355                 default:
1356                     /* no action */
1357                     break;
1358             }
1359             if (process != 0U)
1360             {
1361                 if (videoHandle->controlInterfaceNumber == interface_index)
1362                 {
1363                     error = USB_DeviceVideoVcRequest(videoHandle, controlRequest);
1364                 }
1365                 else if (videoHandle->streamInterfaceNumber == interface_index)
1366                 {
1367                     error = USB_DeviceVideoVsRequest(videoHandle, controlRequest);
1368                 }
1369                 else
1370                 {
1371                     /*no action*/
1372                 }
1373             }
1374         }
1375         break;
1376         default:
1377             /*no action*/
1378             break;
1379     }
1380     return error;
1381 }
1382 
1383 /*!
1384  * @brief Initialize the video class.
1385  *
1386  * This function is used to initialize the video class.
1387  *
1388  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
1389  * @param config          The class configuration information.
1390  * @param handle          It is out parameter, is used to return pointer of the video class handle to the caller.
1391  *
1392  * @return A USB error code or kStatus_USB_Success.
1393  */
USB_DeviceVideoInit(uint8_t controllerId,usb_device_class_config_struct_t * config,class_handle_t * handle)1394 usb_status_t USB_DeviceVideoInit(uint8_t controllerId, usb_device_class_config_struct_t *config, class_handle_t *handle)
1395 {
1396     usb_device_video_struct_t *videoHandle;
1397     usb_status_t error;
1398 
1399     /* Allocate a video class handle. */
1400     error = USB_DeviceVideoAllocateHandle(&videoHandle);
1401 
1402     if (kStatus_USB_Success != error)
1403     {
1404         return error;
1405     }
1406 
1407     /* Get the device handle according to the controller id. */
1408     error = USB_DeviceClassGetDeviceHandle(controllerId, &videoHandle->handle);
1409 
1410     if (kStatus_USB_Success != error)
1411     {
1412         return error;
1413     }
1414 
1415     if (NULL == videoHandle->handle)
1416     {
1417         return kStatus_USB_InvalidHandle;
1418     }
1419     /* Save the configuration of the class. */
1420     videoHandle->configStruct = config;
1421     /* Clear the configuration value. */
1422     videoHandle->configuration    = 0U;
1423     videoHandle->streamAlternate  = 0xffU;
1424     videoHandle->controlAlternate = 0xffU;
1425 
1426     *handle = (class_handle_t)videoHandle;
1427     return error;
1428 }
1429 
1430 /*!
1431  * @brief De-initialize the device video class.
1432  *
1433  * The function de-initializes the device video class.
1434  *
1435  * @param handle The ccid class handle got from usb_device_class_config_struct_t::classHandle.
1436  *
1437  * @return A USB error code or kStatus_USB_Success.
1438  */
USB_DeviceVideoDeinit(class_handle_t handle)1439 usb_status_t USB_DeviceVideoDeinit(class_handle_t handle)
1440 {
1441     usb_device_video_struct_t *videoHandle;
1442     usb_status_t error;
1443 
1444     videoHandle = (usb_device_video_struct_t *)handle;
1445 
1446     if (NULL == videoHandle)
1447     {
1448         return kStatus_USB_InvalidHandle;
1449     }
1450     /* De-initialzie the stream endpoints. */
1451     error = USB_DeviceVideoStreamEndpointsDeinit(videoHandle);
1452     if (kStatus_USB_Success != error)
1453     {
1454 #ifdef DEBUG
1455         usb_echo("USB_DeviceVideoStreamEndpointsDeinit fail\r\n");
1456 #endif
1457     }
1458     /* De-initialzie the control endpoints. */
1459 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
1460     if (kStatus_USB_Success != USB_DeviceVideoControlEndpointsDeinit(videoHandle))
1461     {
1462         return kStatus_USB_Error;
1463     }
1464 #else
1465     (void)USB_DeviceVideoControlEndpointsDeinit(videoHandle);
1466 #endif
1467     /* Free the video class handle. */
1468     error = USB_DeviceVideoFreeHandle(videoHandle);
1469     return error;
1470 }
1471 
1472 /*!
1473  * @brief Send data through a specified endpoint.
1474  *
1475  * The function is used to send data through a specified endpoint.
1476  * The function calls USB_DeviceSendRequest internally.
1477  *
1478  * @param handle The video class handle got from usb_device_class_config_struct_t::classHandle.
1479  * @param endpointAddress Endpoint index.
1480  * @param buffer The memory address to hold the data need to be sent.
1481  * @param length The data length need to be sent.
1482  *
1483  * @return A USB error code or kStatus_USB_Success.
1484  *
1485  * @note The return value just means if the sending request is successful or not; the transfer done is notified by
1486  * USB_DeviceVideoStreamIn or USB_DeviceVideoControlIn.
1487  * Currently, only one transfer request can be supported for one specific endpoint.
1488  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1489  * should implement a queue in the application level.
1490  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1491  * callback).
1492  */
USB_DeviceVideoSend(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)1493 usb_status_t USB_DeviceVideoSend(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
1494 {
1495     usb_device_video_struct_t *videoHandle;
1496     usb_status_t error;
1497 
1498     if (NULL == handle)
1499     {
1500         return kStatus_USB_InvalidHandle;
1501     }
1502     videoHandle = (usb_device_video_struct_t *)handle;
1503 
1504     if (0U != videoHandle->streamInPipeBusy)
1505     {
1506         return kStatus_USB_Busy;
1507     }
1508     videoHandle->streamInPipeBusy = 1U;
1509 
1510     error = USB_DeviceSendRequest(videoHandle->handle, ep, buffer, length);
1511     if (kStatus_USB_Success != error)
1512     {
1513         videoHandle->streamInPipeBusy = 0U;
1514     }
1515     return error;
1516 }
1517 
1518 /*!
1519  * @brief Receive data through a specified endpoint.
1520  *
1521  * The function is used to receive data through a specified endpoint.
1522  * The function calls USB_DeviceRecvRequest internally.
1523  *
1524  * @param handle The video class handle got from usb_device_class_config_struct_t::classHandle.
1525  * @param endpointAddress Endpoint index.
1526  * @param buffer The memory address to save the received data.
1527  * @param length The data length want to be received.
1528  *
1529  * @return A USB error code or kStatus_USB_Success.
1530  *
1531  * @note The return value just means if the receiving request is successful or not; the transfer done is notified by
1532  * USB_DeviceVideoStreamOut.
1533  * Currently, only one transfer request can be supported for one specific endpoint.
1534  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
1535  * should implement a queue in the application level.
1536  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
1537  * callback).
1538  */
USB_DeviceVideoRecv(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)1539 usb_status_t USB_DeviceVideoRecv(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
1540 {
1541     usb_device_video_struct_t *videoHandle;
1542     usb_status_t error;
1543 
1544     if (NULL == handle)
1545     {
1546         return kStatus_USB_InvalidHandle;
1547     }
1548     videoHandle = (usb_device_video_struct_t *)handle;
1549 
1550     if (0U != videoHandle->streamOutPipeBusy)
1551     {
1552         return kStatus_USB_Busy;
1553     }
1554     videoHandle->streamOutPipeBusy = 1U;
1555 
1556     error = USB_DeviceRecvRequest(videoHandle->handle, ep, buffer, length);
1557     if (kStatus_USB_Success != error)
1558     {
1559         videoHandle->streamOutPipeBusy = 0U;
1560     }
1561     return error;
1562 }
1563 
1564 #endif
1565