1 /*
2  * Copyright 2019 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "usb_host_config.h"
9 #if ((defined USB_HOST_CONFIG_VIDEO) && (USB_HOST_CONFIG_VIDEO))
10 #include "usb_host.h"
11 #include "usb_host_video.h"
12 
13 /*******************************************************************************
14  * Variables
15  ******************************************************************************/
16 
17 /*******************************************************************************
18  * Prototypes
19  ******************************************************************************/
20 
21 /*!
22  * @brief open video control interface.
23  *
24  * @param videoInstance     video instance pointer.
25  *
26  * @return kStatus_USB_Success or error codes.
27  */
28 static usb_status_t USB_HostVideoControlOpenInterface(usb_host_video_instance_struct_t *videoInstance);
29 
30 /*!
31  * @brief open video stream interface.
32  *
33  * @param videoInstance     video instance pointer.
34  *
35  * @return kStatus_USB_Success or error codes.
36  */
37 static usb_status_t USB_HostVideoStreamOpenInterface(usb_host_video_instance_struct_t *videoInstance);
38 
39 /*!
40  * @brief video control pipe transfer callback.
41  *
42  * @param param       callback parameter.
43  * @param transfer    callback transfer.
44  * @param status      transfer status.
45  */
46 static void USB_HostVideoSetControlInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
47 
48 /*!
49  * @brief video set interface callback, open pipes.
50  *
51  * @param param       callback parameter.
52  * @param transfer    callback transfer.
53  * @param status      transfer status.
54  */
55 static void USB_HostVideoSetStreamInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
56 
57 /*!
58  * @brief video control command transfer callback.
59  *
60  * @param param       callback parameter.
61  * @param transfer    callback transfer.
62  * @param status      transfer status.
63  */
64 static void USB_HostVideoControlCommandCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
65 
66 /*!
67  * @brief video stream iso in pipe transfer callback.
68  *
69  * @param param       callback parameter.
70  * @param transfer    callback transfer.
71  * @param status      transfer status.
72  */
73 static void USB_HostVideoStreamIsoInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
74 
75 /*!
76  * @brief video send control transfer common code.
77  *
78  * @param classHandle     the class handle.
79  * @param typeRequest     setup packet request type.
80  * @param request         setup packet request value.
81  * @param wvalue          setup packet wvalue value.
82  * @param windex          setup packet index value.
83  * @param wlength         setup packet wlength value.
84  * @param data            data buffer pointer will be transfer.
85  * @param callbackFn      this callback is called after this function completes.
86  * @param callbackParam   the first parameter in the callback function.
87  *
88  * @return An error code or kStatus_USB_Success.
89  */
90 static usb_status_t USB_HostVideoControl(usb_host_class_handle classHandle,
91                                          uint8_t typeRequest,
92                                          uint8_t request,
93                                          uint16_t wvalue,
94                                          uint16_t windex,
95                                          uint16_t wlength,
96                                          uint8_t *data,
97                                          transfer_callback_t callbackFn,
98                                          void *callbackParam);
99 
100 /*******************************************************************************
101  * Code
102  ******************************************************************************/
103 /*!
104  * @brief open video control interface.
105  *
106  * @param videoInstance     video instance pointer.
107  *
108  * @return kStatus_USB_Success or error codes.
109  */
USB_HostVideoControlOpenInterface(usb_host_video_instance_struct_t * videoInstance)110 static usb_status_t USB_HostVideoControlOpenInterface(usb_host_video_instance_struct_t *videoInstance)
111 {
112     usb_status_t status;
113     uint8_t ep_index = 0U;
114     usb_host_pipe_init_t pipe_init;
115     usb_descriptor_endpoint_t *ep_desc = NULL;
116     usb_host_interface_t *interface_ptr;
117     void *temp;
118     if (videoInstance->interruptPipe != NULL)
119     {
120         status = USB_HostClosePipe(videoInstance->hostHandle, videoInstance->interruptPipe);
121 
122         if (status != kStatus_USB_Success)
123         {
124 #ifdef HOST_ECHO
125             usb_echo("error when close pipe\r\n");
126 #endif
127         }
128         videoInstance->interruptPipe = NULL;
129     }
130 
131     /* open interface pipes */
132     temp          = (void *)videoInstance->controlIntfHandle;
133     interface_ptr = (usb_host_interface_t *)temp;
134     for (ep_index = 0U; ep_index < interface_ptr->epCount; ++ep_index)
135     {
136         ep_desc = interface_ptr->epList[ep_index].epDesc;
137         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
138              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
139             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
140         {
141             pipe_init.devInstance     = videoInstance->deviceHandle;
142             pipe_init.pipeType        = USB_ENDPOINT_INTERRUPT;
143             pipe_init.direction       = USB_IN;
144             pipe_init.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
145             pipe_init.interval        = ep_desc->bInterval;
146             pipe_init.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
147                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
148             pipe_init.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
149                                                    USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
150             pipe_init.nakCount        = USB_HOST_CONFIG_MAX_NAK;
151 
152             videoInstance->interruptInPacketSize = pipe_init.maxPacketSize;
153             videoInstance->interruptInEpNum      = pipe_init.endpointAddress;
154             status = USB_HostOpenPipe(videoInstance->hostHandle, &videoInstance->interruptPipe, &pipe_init);
155             if (status != kStatus_USB_Success)
156             {
157 #ifdef HOST_ECHO
158                 usb_echo("usb_host_video_control_set_interface fail to open pipe\r\n");
159 #endif
160                 return kStatus_USB_Error;
161             }
162         }
163         else
164         {
165         }
166     }
167 
168     return kStatus_USB_Success;
169 }
170 
171 /*!
172  * @brief open video stream interface.
173  *
174  * @param videoInstance     video instance pointer.
175  *
176  * @return kStatus_USB_Success or error codes.
177  */
USB_HostVideoStreamOpenInterface(usb_host_video_instance_struct_t * videoInstance)178 static usb_status_t USB_HostVideoStreamOpenInterface(usb_host_video_instance_struct_t *videoInstance)
179 {
180     usb_status_t status;
181     uint8_t ep_index = 0U;
182     usb_host_pipe_init_t pipe_init;
183     usb_descriptor_endpoint_t *ep_desc = NULL;
184     usb_host_interface_t *interface_ptr;
185     void *temp;
186 
187     if (videoInstance->streamIsoInPipe != NULL)
188     {
189         status = USB_HostClosePipe(videoInstance->hostHandle, videoInstance->streamIsoInPipe);
190 
191         if (status != kStatus_USB_Success)
192         {
193 #ifdef HOST_ECHO
194             usb_echo("error when close pipe\r\n");
195 #endif
196         }
197         videoInstance->streamIsoInPipe = NULL;
198     }
199 
200     /* open interface pipes */
201     temp          = (void *)videoInstance->streamIntfHandle;
202     interface_ptr = (usb_host_interface_t *)temp;
203     for (ep_index = 0U; ep_index < interface_ptr->epCount; ++ep_index)
204     {
205         ep_desc = interface_ptr->epList[ep_index].epDesc;
206         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
207              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
208             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_ISOCHRONOUS))
209         {
210             pipe_init.devInstance     = videoInstance->deviceHandle;
211             pipe_init.pipeType        = USB_ENDPOINT_ISOCHRONOUS;
212             pipe_init.direction       = USB_IN;
213             pipe_init.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
214             pipe_init.interval        = ep_desc->bInterval;
215             pipe_init.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
216                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
217             pipe_init.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
218                                                    USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK) >>
219                                                   USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_SHFIT);
220             pipe_init.nakCount        = USB_HOST_CONFIG_MAX_NAK;
221 
222             videoInstance->isoInPacketSize = pipe_init.maxPacketSize;
223             videoInstance->isoInEpNum      = pipe_init.endpointAddress;
224             status = USB_HostOpenPipe(videoInstance->hostHandle, &videoInstance->streamIsoInPipe, &pipe_init);
225             if (status != kStatus_USB_Success)
226             {
227 #ifdef HOST_ECHO
228                 usb_echo("usb_host_video_stream_set_interface fail to open pipe\r\n");
229 #endif
230                 return kStatus_USB_Error;
231             }
232         }
233         else
234         {
235         }
236     }
237 
238     return kStatus_USB_Success;
239 }
240 
241 /*!
242  * @brief video control pipe transfer callback.
243  *
244  * @param param       callback parameter.
245  * @param transfer    callback transfer.
246  * @param status      transfer status.
247  */
USB_HostVideoSetControlInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)248 static void USB_HostVideoSetControlInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
249 {
250     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)param;
251 
252     videoInstance->controlTransfer = NULL;
253     if (status == kStatus_USB_Success)
254     {
255         status = USB_HostVideoControlOpenInterface(videoInstance);
256     }
257 
258     if (videoInstance->controlCallbackFn != NULL)
259     {
260         /* callback to application, callback function is initialized in the _USB_HostAudioControl,
261         USB_HostVideoStreamSetInterface
262         or USB_HostVideoControlSetInterface, but is the same function */
263         videoInstance->controlCallbackFn(videoInstance->controlCallbackParam, transfer->transferBuffer,
264                                          transfer->transferSofar, status);
265     }
266     (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
267 }
268 
269 /*!
270  * @brief video set interface callback, open pipes.
271  *
272  * @param param       callback parameter.
273  * @param transfer    callback transfer.
274  * @param status      transfer status.
275  */
USB_HostVideoSetStreamInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)276 static void USB_HostVideoSetStreamInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
277 {
278     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)param;
279 
280     videoInstance->controlTransfer = NULL;
281     if (status == kStatus_USB_Success)
282     {
283         status = USB_HostVideoStreamOpenInterface(videoInstance);
284     }
285 
286     if (videoInstance->controlCallbackFn != NULL)
287     {
288         /* callback to application, callback function is initialized in the _USB_HostAudioControl,
289         USB_HostAudioStreamSetInterface
290         or USB_HostAudioControlSetInterface, but is the same function */
291         videoInstance->controlCallbackFn(videoInstance->controlCallbackParam, NULL, 0U, status);
292     }
293     (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
294 }
295 
296 /*!
297  * @brief video control command transfer callback.
298  *
299  * @param param       callback parameter.
300  * @param transfer    callback transfer.
301  * @param status      transfer status.
302  */
USB_HostVideoControlCommandCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)303 static void USB_HostVideoControlCommandCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
304 {
305     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)param;
306 
307     if (videoInstance->controlCallbackFn != NULL)
308     {
309         /* callback to application, callback function is initialized in the USB_HostCdcControl,
310         USB_HostCdcSetControlInterface
311         or USB_HostCdcSetDataInterface, but is the same function */
312         videoInstance->controlCallbackFn(videoInstance->controlCallbackParam, transfer->transferBuffer,
313                                          transfer->transferSofar, status);
314     }
315     (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
316 }
317 
318 /*!
319  * @brief video stream iso in pipe transfer callback.
320  *
321  * @param param       callback parameter.
322  * @param transfer    callback transfer.
323  * @param status      transfer status.
324  */
USB_HostVideoStreamIsoInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)325 static void USB_HostVideoStreamIsoInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
326 {
327     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)param;
328 
329     if (videoInstance->streamIsoInCallbackFn != NULL)
330     {
331         /* callback function is initialized in USB_HosVideoStreamRecv */
332         videoInstance->streamIsoInCallbackFn(videoInstance->streamIsoInCallbackParam, transfer->transferBuffer,
333                                              transfer->transferSofar, status);
334     }
335     (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
336 }
337 
338 /*!
339  * @brief video send control transfer common code.
340  *
341  * @param classHandle     the class handle.
342  * @param typeRequest     setup packet request type.
343  * @param request         setup packet request value.
344  * @param wvalue          setup packet wvalue value.
345  * @param windex          setup packet index value.
346  * @param wlength         setup packet wlength value.
347  * @param data            data buffer pointer will be transfer.
348  * @param callbackFn      this callback is called after this function completes.
349  * @param callbackParam   the first parameter in the callback function.
350  *
351  * @return An error code or kStatus_USB_Success.
352  */
USB_HostVideoControl(usb_host_class_handle classHandle,uint8_t typeRequest,uint8_t request,uint16_t wvalue,uint16_t windex,uint16_t wlength,uint8_t * data,transfer_callback_t callbackFn,void * callbackParam)353 static usb_status_t USB_HostVideoControl(usb_host_class_handle classHandle,
354                                          uint8_t typeRequest,
355                                          uint8_t request,
356                                          uint16_t wvalue,
357                                          uint16_t windex,
358                                          uint16_t wlength,
359                                          uint8_t *data,
360                                          transfer_callback_t callbackFn,
361                                          void *callbackParam)
362 {
363     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
364     usb_host_transfer_t *transfer;
365 
366     if (classHandle == NULL)
367     {
368         return kStatus_USB_InvalidHandle;
369     }
370 
371     /* malloc one transfer */
372     if (USB_HostMallocTransfer(videoInstance->hostHandle, &transfer) != kStatus_USB_Success)
373     {
374 #ifdef HOST_ECHO
375         usb_echo("error to get transfer\r\n");
376 #endif
377         return kStatus_USB_Error;
378     }
379     /* save the application callback function */
380     videoInstance->controlCallbackFn    = callbackFn;
381     videoInstance->controlCallbackParam = callbackParam;
382 
383     transfer->transferBuffer             = data;
384     transfer->transferLength             = wlength;
385     transfer->callbackFn                 = USB_HostVideoControlCommandCallback;
386     transfer->callbackParam              = videoInstance;
387     transfer->setupPacket->bmRequestType = typeRequest;
388     transfer->setupPacket->bRequest      = request;
389     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
390     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(windex);
391     transfer->setupPacket->wLength       = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
392 
393     if (USB_HostSendSetup(videoInstance->hostHandle, videoInstance->controlPipe, transfer) != kStatus_USB_Success)
394     {
395 #ifdef HOST_ECHO
396         usb_echo("failed for USB_HostSendSetup\r\n");
397 #endif
398         (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
399         return kStatus_USB_Error;
400     }
401     videoInstance->controlTransfer = transfer;
402 
403     return kStatus_USB_Success;
404 }
405 
406 /*!
407  * @brief set video class stream interface.
408  *
409  * This function bind the interface with the video instance.
410  *
411  * @param classHandle       The class handle.
412  * @param interfaceHandle   The interface handle.
413  * @param alternateSetting  The alternate setting value.
414  * @param callbackFn        This callback is called after this function completes.
415  * @param callbackParam     The first parameter in the callback function.
416  *
417  * @retval kStatus_USB_Success        The device is initialized successfully.
418  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
419  * @retval kStatus_USB_Busy           There is no idle transfer.
420  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
421  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
422  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
423  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
424  */
USB_HostVideoStreamSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)425 usb_status_t USB_HostVideoStreamSetInterface(usb_host_class_handle classHandle,
426                                              usb_host_interface_handle interfaceHandle,
427                                              uint8_t alternateSetting,
428                                              transfer_callback_t callbackFn,
429                                              void *callbackParam)
430 {
431     usb_status_t status;
432     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
433     usb_host_interface_t *interface_ptr;
434     usb_host_transfer_t *transfer;
435     usb_host_video_descriptor_union_t descUnion;
436     uint32_t length, ep = 0U;
437     uint32_t descLength = 0;
438     void *temp;
439 
440     if (classHandle == NULL)
441     {
442         return kStatus_USB_InvalidParameter;
443     }
444 
445     videoInstance->streamIntfHandle = interfaceHandle;
446 
447     status = USB_HostOpenDeviceInterface(videoInstance->deviceHandle,
448                                          interfaceHandle); /* save the application callback function */
449     if (status != kStatus_USB_Success)
450     {
451         return status;
452     }
453 
454     /* cancel transfers */
455     if (videoInstance->streamIsoInPipe != NULL)
456     {
457         status = USB_HostCancelTransfer(videoInstance->hostHandle, videoInstance->streamIsoInPipe, NULL);
458 
459         if (status != kStatus_USB_Success)
460         {
461 #ifdef HOST_ECHO
462             usb_echo("error when cancel pipe\r\n");
463 #endif
464         }
465     }
466 
467     /* open interface pipes */
468     interface_ptr = (usb_host_interface_t *)interfaceHandle;
469 
470     if (0U == alternateSetting)
471     {
472         descUnion.bufr = interface_ptr->interfaceExtension;
473         length         = 0U;
474         while (length < interface_ptr->interfaceExtensionLength)
475         {
476             if (descUnion.common->bDescriptorType == USB_HOST_DESC_CS_INTERFACE)
477             {
478                 if (descUnion.common->bData[0] == USB_HOST_DESC_SUBTYPE_VS_INPUT_HEADER)
479                 {
480                     temp                             = (void *)descUnion.bufr;
481                     videoInstance->vsInputHeaderDesc = (usb_host_video_stream_input_header_desc_t *)temp;
482                     break;
483                 }
484             }
485             length += descUnion.common->bLength;
486             descUnion.bufr += descUnion.common->bLength;
487         }
488     }
489     else
490     {
491         descUnion.bufr = interface_ptr->interfaceExtension;
492         length         = 0U;
493         while (length < interface_ptr->interfaceExtensionLength)
494         {
495             if ((descUnion.common->bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE) &&
496                 (descUnion.interface->bAlternateSetting == alternateSetting))
497             {
498                 interface_ptr->epCount = descUnion.interface->bNumEndpoints;
499                 break;
500             }
501             length += descUnion.common->bLength;
502             descUnion.bufr += descUnion.common->bLength;
503         }
504 
505         while (ep < interface_ptr->epCount)
506         {
507             if (descUnion.common->bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT)
508             {
509                 temp                             = (void *)descUnion.bufr;
510                 interface_ptr->epList[ep].epDesc = (usb_descriptor_endpoint_t *)temp;
511                 descLength                       = descUnion.common->bLength;
512                 descUnion.bufr += descUnion.common->bLength;
513 
514                 if (USB_HOST_DESC_CS_ENDPOINT == descUnion.common->bDescriptorType)
515                 {
516                     interface_ptr->epList[ep].epExtension       = descUnion.bufr;
517                     interface_ptr->epList[ep].epExtensionLength = descUnion.common->bLength;
518                 }
519                 else
520                 {
521                     descUnion.bufr -= descLength;
522                 }
523                 ep++;
524             }
525             descUnion.bufr += descUnion.common->bLength;
526         }
527     }
528 
529     if (alternateSetting == 0U) /* open interface directly */
530     {
531         if (callbackFn != NULL)
532         {
533             status = USB_HostVideoStreamOpenInterface(videoInstance);
534             callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
535         }
536     }
537     else /* send setup transfer */
538     {
539         /* malloc one transfer */
540         if (USB_HostMallocTransfer(videoInstance->hostHandle, &transfer) != kStatus_USB_Success)
541         {
542 #ifdef HOST_ECHO
543             usb_echo("error to get transfer\r\n");
544 #endif
545             return kStatus_USB_Error;
546         }
547         /* save the application callback function */
548         videoInstance->controlCallbackFn    = callbackFn;
549         videoInstance->controlCallbackParam = callbackParam;
550         /* initialize transfer */
551         transfer->callbackFn                 = USB_HostVideoSetStreamInterfaceCallback;
552         transfer->callbackParam              = videoInstance;
553         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
554         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
555         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
556             ((usb_host_interface_t *)videoInstance->streamIntfHandle)->interfaceDesc->bInterfaceNumber);
557         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
558         transfer->setupPacket->wLength = 0;
559         transfer->transferBuffer       = NULL;
560         transfer->transferLength       = 0;
561         status = USB_HostSendSetup(videoInstance->hostHandle, videoInstance->controlPipe, transfer);
562 
563         if (status == kStatus_USB_Success)
564         {
565             videoInstance->controlTransfer = transfer;
566         }
567         else
568         {
569             (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
570         }
571     }
572 
573     return status;
574 }
575 
576 /*!
577  * @brief set control interface.
578  *
579  * This function bind the control interface with the video instance.
580  *
581  * @param classHandle      the class handle.
582  * @param interfaceHandle  the control interface handle.
583  * @param alternateSetting the alternate setting value.
584  * @param callbackFn       this callback is called after this function completes.
585  * @param callbackParam    the first parameter in the callback function.
586  *
587  * @retval kStatus_USB_Success        The device is initialized successfully.
588  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
589  * @retval kStatus_USB_Busy           There is no idle transfer.
590  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
591  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
592  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
593  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
594  */
USB_HostVideoControlSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)595 usb_status_t USB_HostVideoControlSetInterface(usb_host_class_handle classHandle,
596                                               usb_host_interface_handle interfaceHandle,
597                                               uint8_t alternateSetting,
598                                               transfer_callback_t callbackFn,
599                                               void *callbackParam)
600 {
601     usb_status_t status;
602     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
603     usb_host_interface_t *interface_ptr;
604     usb_host_transfer_t *transfer;
605     usb_host_video_descriptor_union_t desc;
606     uint32_t length = 0U;
607     void *temp;
608 
609     if (classHandle == NULL)
610     {
611         return kStatus_USB_InvalidParameter;
612     }
613     videoInstance->controlIntfHandle = interfaceHandle;
614     interface_ptr                    = (usb_host_interface_t *)interfaceHandle;
615 
616     status = USB_HostOpenDeviceInterface(videoInstance->deviceHandle,
617                                          interfaceHandle); /* notify host driver the interface is open */
618     if (status != kStatus_USB_Success)
619     {
620         return status;
621     }
622     desc.bufr = interface_ptr->interfaceExtension;
623 
624     length = 0U;
625 
626     while (length < interface_ptr->interfaceExtensionLength)
627     {
628         if (((interface_ptr->interfaceDesc->bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE) &&
629              (interface_ptr->interfaceDesc->bAlternateSetting == alternateSetting)) ||
630             ((desc.common->bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE) &&
631              (desc.interface->bAlternateSetting == alternateSetting)))
632         {
633             break;
634         }
635         length += desc.common->bLength;
636         desc.bufr += desc.common->bLength;
637     }
638     while (length < interface_ptr->interfaceExtensionLength)
639     {
640         if (desc.common->bDescriptorType == USB_HOST_DESC_CS_INTERFACE)
641         {
642             temp = (void *)desc.bufr;
643             if (desc.common->bData[0] == USB_HOST_DESC_SUBTYPE_VC_HEADER)
644             {
645                 videoInstance->vcHeaderDesc = (usb_host_video_ctrl_header_desc_t *)temp;
646             }
647             else if (desc.common->bData[0] == USB_HOST_DESC_SUBTYPE_VC_INPUT_TERMINAL)
648             {
649                 videoInstance->vcInputTerminalDesc = (usb_host_video_ctrl_it_desc_t *)temp;
650             }
651             else if (desc.common->bData[0] == USB_HOST_DESC_SUBTYPE_VC_OUTPUT_TERMINAL)
652             {
653                 videoInstance->vcOutputTerminalDesc = (usb_host_video_ctrl_ot_desc_t *)temp;
654             }
655             else if (desc.common->bData[0] == USB_HOST_DESC_SUBTYPE_VC_PROCESSING_UNIT)
656             {
657                 videoInstance->vcProcessingUnitDesc = (usb_host_video_ctrl_pu_desc_t *)temp;
658             }
659             else
660             {
661                 /*no action*/
662             }
663         }
664         length += desc.common->bLength;
665         desc.bufr += desc.common->bLength;
666     }
667 
668     if (alternateSetting == 0U) /* open interface directly */
669     {
670         if (callbackFn != NULL)
671         {
672             status = USB_HostVideoControlOpenInterface(videoInstance);
673             callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
674         }
675     }
676     else /* send setup transfer */
677     {
678         /* malloc one transfer */
679         if (USB_HostMallocTransfer(videoInstance->hostHandle, &transfer) != kStatus_USB_Success)
680         {
681 #ifdef HOST_ECHO
682             usb_echo("error to get transfer\r\n");
683 #endif
684             return kStatus_USB_Error;
685         }
686         /* save the application callback function */
687         videoInstance->controlCallbackFn    = callbackFn;
688         videoInstance->controlCallbackParam = callbackParam;
689         /* initialize transfer */
690         transfer->callbackFn                 = USB_HostVideoSetControlInterfaceCallback;
691         transfer->callbackParam              = videoInstance;
692         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
693         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
694         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
695             ((usb_host_interface_t *)videoInstance->controlIntfHandle)->interfaceDesc->bInterfaceNumber);
696         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
697         transfer->setupPacket->wLength = 0;
698         transfer->transferBuffer       = NULL;
699         transfer->transferLength       = 0;
700         status = USB_HostSendSetup(videoInstance->hostHandle, videoInstance->controlPipe, transfer);
701 
702         if (status == kStatus_USB_Success)
703         {
704             videoInstance->controlTransfer = transfer;
705         }
706         else
707         {
708             (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
709         }
710     }
711 
712     return status;
713 }
714 
715 /*!
716  * @brief video stream receive data.
717  *
718  * This function implements video receiving data.
719  *
720  * @param classHandle    The class handle.
721  * @param buffer         The buffer pointer.
722  * @param bufferLen      The buffer length.
723  * @param callbackFn     This callback is called after this function completes.
724  * @param callbackParam  The first parameter in the callback function.
725  *
726  * @retval kStatus_USB_Success        Receive request successfully.
727  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
728  * @retval kStatus_USB_Busy           There is no idle transfer.
729  * @retval kStatus_USB_Error          pipe is not initialized.
730  *                                    Or, send transfer fail, please reference to USB_HostRecv.
731  */
USB_HosVideoStreamRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLen,transfer_callback_t callbackFn,void * callbackParam)732 usb_status_t USB_HosVideoStreamRecv(usb_host_class_handle classHandle,
733                                     uint8_t *buffer,
734                                     uint32_t bufferLen,
735                                     transfer_callback_t callbackFn,
736                                     void *callbackParam)
737 {
738     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
739     usb_host_transfer_t *transfer;
740 
741     if (classHandle == NULL)
742     {
743         return kStatus_USB_InvalidHandle;
744     }
745 
746     if (videoInstance->streamIsoInPipe == NULL)
747     {
748         return kStatus_USB_Error;
749     }
750 
751     /* malloc one transfer */
752     if (USB_HostMallocTransfer(videoInstance->hostHandle, &transfer) != kStatus_USB_Success)
753     {
754 #ifdef HOST_ECHO
755         usb_echo("error to get transfer\r\n");
756 #endif
757         return kStatus_USB_Error;
758     }
759     /* save the application callback function */
760     videoInstance->streamIsoInCallbackFn    = callbackFn;
761     videoInstance->streamIsoInCallbackParam = callbackParam;
762     transfer->transferBuffer                = buffer;
763     transfer->transferLength                = bufferLen;
764     transfer->callbackFn                    = USB_HostVideoStreamIsoInPipeCallback;
765     transfer->callbackParam                 = videoInstance;
766 
767     if (USB_HostRecv(videoInstance->hostHandle, videoInstance->streamIsoInPipe, transfer) != kStatus_USB_Success)
768     {
769 #ifdef HOST_ECHO
770         usb_echo("failed to USB_HostRecv\r\n");
771 #endif
772         (void)USB_HostFreeTransfer(videoInstance->hostHandle, transfer);
773         return kStatus_USB_Error;
774     }
775 
776     return kStatus_USB_Success;
777 }
778 
779 /*!
780  * @brief initialize the video instance.
781  *
782  * This function allocate the resource for video instance.
783  *
784  * @param deviceHandle   the device handle.
785  * @param classHandle    return class handle.
786  *
787  * @retval kStatus_USB_Success        The device is initialized successfully.
788  * @retval kStatus_USB_AllocFail      Allocate memory fail.
789  */
USB_HostVideoInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandle)790 usb_status_t USB_HostVideoInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
791 {
792     usb_host_video_instance_struct_t *videoInstance =
793         (usb_host_video_instance_struct_t *)OSA_MemoryAllocate(sizeof(usb_host_video_instance_struct_t));
794     uint32_t info_value = 0U;
795     uint32_t *temp;
796     if (videoInstance == NULL)
797     {
798         return kStatus_USB_AllocFail;
799     }
800 
801     /* initialize video instance */
802     videoInstance->deviceHandle      = deviceHandle;
803     videoInstance->controlIntfHandle = NULL;
804     videoInstance->streamIntfHandle  = NULL;
805     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &info_value);
806     temp                      = (uint32_t *)info_value;
807     videoInstance->hostHandle = (usb_host_handle)temp;
808     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &info_value);
809     temp                       = (uint32_t *)info_value;
810     videoInstance->controlPipe = (usb_host_pipe_handle)temp;
811 
812     *classHandle = videoInstance;
813     return kStatus_USB_Success;
814 }
815 
816 /*!
817  * @brief de-initialize the video instance.
818  *
819  * This function release the resource for video instance.
820  *
821  * @param deviceHandle   the device handle.
822  * @param classHandle    the class handle.
823  *
824  * @retval kStatus_USB_Success    The device is de-initialized successfully.
825  */
USB_HostVideoDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)826 usb_status_t USB_HostVideoDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
827 {
828     usb_status_t status;
829     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
830 
831     if (deviceHandle == NULL)
832     {
833         return kStatus_USB_InvalidHandle;
834     }
835 
836     if (classHandle != NULL)
837     {
838         /* cancel transfers */
839         if (videoInstance->streamIsoInPipe != NULL)
840         {
841             status = USB_HostCancelTransfer(videoInstance->hostHandle, videoInstance->streamIsoInPipe, NULL);
842             if (status != kStatus_USB_Success)
843             {
844 #ifdef HOST_ECHO
845                 usb_echo("error when cancel pipe\r\n");
846 #endif
847             }
848             status = USB_HostClosePipe(videoInstance->hostHandle, videoInstance->streamIsoInPipe);
849 
850             if (status != kStatus_USB_Success)
851             {
852 #ifdef HOST_ECHO
853                 usb_echo("error when close pipe\r\n");
854 #endif
855             }
856             videoInstance->streamIsoInPipe = NULL;
857         }
858 
859         (void)USB_HostCloseDeviceInterface(deviceHandle, videoInstance->streamIntfHandle);
860 
861         /* cancel transfers */
862         if (videoInstance->interruptPipe != NULL)
863         {
864             status = USB_HostCancelTransfer(videoInstance->hostHandle, videoInstance->interruptPipe, NULL);
865             if (status != kStatus_USB_Success)
866             {
867 #ifdef HOST_ECHO
868                 usb_echo("error when cancel pipe\r\n");
869 #endif
870             }
871             status = USB_HostClosePipe(videoInstance->hostHandle, videoInstance->interruptPipe);
872 
873             if (status != kStatus_USB_Success)
874             {
875 #ifdef HOST_ECHO
876                 usb_echo("error when close pipe\r\n");
877 #endif
878             }
879             videoInstance->interruptPipe = NULL;
880         }
881         /* cancel transfers */
882         if ((videoInstance->controlPipe != NULL) && (videoInstance->controlTransfer != NULL))
883         {
884             status = USB_HostCancelTransfer(videoInstance->hostHandle, videoInstance->controlPipe,
885                                             videoInstance->controlTransfer);
886             if (status != kStatus_USB_Success)
887             {
888 #ifdef HOST_ECHO
889                 usb_echo("error when cancel pipe\r\n");
890 #endif
891             }
892         }
893         (void)USB_HostCloseDeviceInterface(deviceHandle, videoInstance->controlIntfHandle);
894         OSA_MemoryFree(videoInstance);
895     }
896     else
897     {
898         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
899     }
900 
901     return kStatus_USB_Success;
902 }
903 
904 /*!
905  * @brief get video stream format descriptor.
906  *
907  * This function implements get video stream format descriptor.
908  *
909  * @param classHandle   The class handle.
910  * @param subType       The descriptor subtype.
911  * @param descriptor    The pointer of specific format descriptor.
912  *
913  * @retval kStatus_USB_Success            Get video stream format descriptor request successfully.
914  * @retval kStatus_USB_InvalidHandle     The classHandle is NULL pointer.
915  * @retval kStatus_USB_InvalidParameter  The descriptor is NULL pointer.
916  *
917  */
USB_HostVideoStreamGetFormatDescriptor(usb_host_class_handle classHandle,uint8_t subType,void ** descriptor)918 usb_status_t USB_HostVideoStreamGetFormatDescriptor(usb_host_class_handle classHandle,
919                                                     uint8_t subType,
920                                                     void **descriptor)
921 {
922     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
923     usb_host_interface_t *interface_ptr;
924     usb_host_video_descriptor_union_t descUnion;
925     uint32_t length = 0U;
926 
927     if (NULL == classHandle)
928     {
929         return kStatus_USB_InvalidHandle;
930     }
931 
932     /* get the steam interface handle */
933     interface_ptr = (usb_host_interface_t *)videoInstance->streamIntfHandle;
934 
935     descUnion.bufr = interface_ptr->interfaceExtension;
936     length         = 0U;
937     while (length < interface_ptr->interfaceExtensionLength)
938     {
939         if (descUnion.common->bDescriptorType == USB_HOST_DESC_CS_INTERFACE)
940         {
941             if (descUnion.common->bData[0] == subType)
942             {
943                 *descriptor = descUnion.bufr;
944                 return kStatus_USB_Success;
945                 ;
946             }
947         }
948         length += descUnion.common->bLength;
949         descUnion.bufr += descUnion.common->bLength;
950     }
951 
952     return kStatus_USB_Error;
953 }
954 
955 /*!
956  * @brief get specific video stream frame descriptor.
957  *
958  * This function implements get specific video stream frame descriptor.
959  *
960  * @param classHandle        The class handle.
961  * @param formatDescriptor   The frame descriptor pointer.
962  * @param index              The specific frame descriptor id
963  * @param descriptor         The pointer of specific frame descriptor.
964  *
965  * @retval kStatus_USB_Success           Get video stream frame descriptor request successfully.
966  * @retval kStatus_USB_InvalidHandle     The classHandle is NULL pointer.
967  * @retval kStatus_USB_InvalidParameter  The descriptor is NULL pointer.
968  *
969  */
USB_HostVideoStreamGetFrameDescriptor(usb_host_class_handle classHandle,void * formatDescriptor,uint8_t subType,uint8_t frameIndex,void ** descriptor)970 usb_status_t USB_HostVideoStreamGetFrameDescriptor(
971     usb_host_class_handle classHandle, void *formatDescriptor, uint8_t subType, uint8_t frameIndex, void **descriptor)
972 {
973     usb_host_video_stream_payload_format_common_desc_t *formatDesc =
974         (usb_host_video_stream_payload_format_common_desc_t *)formatDescriptor;
975     usb_host_video_descriptor_union_t desc;
976     uint32_t i         = 0U;
977     uint8_t frameCount = 0U;
978 
979     if (NULL == classHandle)
980     {
981         return kStatus_USB_InvalidHandle;
982     }
983 
984     if ((formatDesc == NULL) || (formatDesc->bDescriptorType != USB_HOST_DESC_CS_INTERFACE))
985     {
986         return kStatus_USB_InvalidParameter;
987     }
988 
989     frameCount = formatDesc->bNumFrameDescriptors;
990     desc.bufr  = (void *)formatDesc;
991     desc.bufr += desc.common->bLength;
992 
993     while (i <= frameCount)
994     {
995         if ((desc.video_frame_common->bDescriptorType == USB_HOST_DESC_CS_INTERFACE) &&
996             (desc.video_frame_common->bDescriptorSubtype == subType))
997         {
998             if (desc.video_frame_common->bFrameIndex == frameIndex)
999             {
1000                 *descriptor = (void *)desc.bufr;
1001                 return kStatus_USB_Success;
1002             }
1003         }
1004         i++;
1005         desc.bufr += desc.common->bLength;
1006     }
1007 
1008     return kStatus_USB_Error;
1009 }
1010 
1011 /*!
1012  * @brief video set probe.
1013  *
1014  * This function implements the Video class-specific request (set probe).
1015  *
1016  * @param classHandle    the class handle.
1017  * @param request        setup packet request value.
1018  * @param probe          video probe data
1019  * @param callbackFn     this callback is called after this function completes.
1020  * @param callbackParam  the first parameter in the callback function.
1021  *
1022  * @retval kStatus_USB_Success           Request successful.
1023  * @retval kStatus_USB_InvalidHandle     The classHandle is NULL pointer.
1024  * @retval kStatus_USB_InvalidParameter  The interface descriptor is NULL pointer.
1025  */
USB_HostVideoSetProbe(usb_host_class_handle classHandle,uint8_t request,uint8_t * probe,transfer_callback_t callbackFn,void * callbackParam)1026 usb_status_t USB_HostVideoSetProbe(usb_host_class_handle classHandle,
1027                                    uint8_t request,
1028                                    uint8_t *probe,
1029                                    transfer_callback_t callbackFn,
1030                                    void *callbackParam)
1031 {
1032     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
1033     usb_host_interface_t *streamInterface;
1034     usb_status_t status;
1035     streamInterface = (usb_host_interface_t *)videoInstance->streamIntfHandle;
1036 
1037     if (NULL == streamInterface)
1038     {
1039         return kStatus_USB_InvalidHandle;
1040     }
1041     if (NULL == streamInterface->interfaceDesc)
1042     {
1043         return kStatus_USB_InvalidParameter;
1044     }
1045     status = USB_HostVideoControl(
1046         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1047         request, (uint16_t)(USB_HOST_VS_PROBE_CONTROL << 8UL), streamInterface->interfaceDesc->bInterfaceNumber, 26U,
1048         probe, callbackFn, callbackParam);
1049     return status;
1050 }
1051 
1052 /*!
1053  * @brief video get probe.
1054  *
1055  * This function implements the Video class-specific request (get probe).
1056  *
1057  * @param classHandle   the class handle.
1058  * @param request       setup packet request value.
1059  * @param probe         video probe data
1060  * @param callbackFn    this callback is called after this function completes.
1061  * @param callbackParam the first parameter in the callback function.
1062  *
1063  * @retval kStatus_USB_Success           Request successful.
1064  * @retval kStatus_USB_InvalidHandle     The classHandle is NULL pointer.
1065  * @retval kStatus_USB_InvalidParameter  The interface descriptor is NULL pointer.
1066  */
USB_HostVideoGetProbe(usb_host_class_handle classHandle,uint8_t request,uint8_t * probe,transfer_callback_t callbackFn,void * callbackParam)1067 usb_status_t USB_HostVideoGetProbe(usb_host_class_handle classHandle,
1068                                    uint8_t request,
1069                                    uint8_t *probe,
1070                                    transfer_callback_t callbackFn,
1071                                    void *callbackParam)
1072 {
1073     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
1074     usb_host_interface_t *streamInterface;
1075     usb_status_t status;
1076     streamInterface = (usb_host_interface_t *)videoInstance->streamIntfHandle;
1077     if (NULL == streamInterface)
1078     {
1079         return kStatus_USB_InvalidHandle;
1080     }
1081     if (NULL == streamInterface->interfaceDesc)
1082     {
1083         return kStatus_USB_InvalidParameter;
1084     }
1085     status = USB_HostVideoControl(
1086         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1087         request, (uint16_t)(USB_HOST_VS_PROBE_CONTROL << 8UL), streamInterface->interfaceDesc->bInterfaceNumber, 26U,
1088         probe, callbackFn, callbackParam);
1089     return status;
1090 }
1091 
1092 /*!
1093  * @brief video get commit.
1094  *
1095  * This function implements the Video class-specific request (get commit).
1096  *
1097  * @param classHandle    the class handle.
1098  * @param request        setup packet request value.
1099  * @param probe          video probe data
1100  * @param callbackFn     this callback is called after this function completes.
1101  * @param callbackParam  the first parameter in the callback function.
1102  *
1103  * @retval kStatus_USB_Success           Request successful.
1104  * @retval kStatus_USB_InvalidHandle     The classHandle is NULL pointer.
1105  * @retval kStatus_USB_InvalidParameter  The interface descriptor is NULL pointer.
1106  */
USB_HostVideoGetCommit(usb_host_class_handle classHandle,uint8_t brequest,uint8_t * probe,transfer_callback_t callbackFn,void * callbackParam)1107 usb_status_t USB_HostVideoGetCommit(usb_host_class_handle classHandle,
1108                                     uint8_t brequest,
1109                                     uint8_t *probe,
1110                                     transfer_callback_t callbackFn,
1111                                     void *callbackParam)
1112 {
1113     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
1114     usb_host_interface_t *streamInterface;
1115     usb_status_t status;
1116     streamInterface = (usb_host_interface_t *)videoInstance->streamIntfHandle;
1117     if (NULL == streamInterface)
1118     {
1119         return kStatus_USB_InvalidHandle;
1120     }
1121     if (NULL == streamInterface->interfaceDesc)
1122     {
1123         return kStatus_USB_InvalidParameter;
1124     }
1125     status = USB_HostVideoControl(
1126         classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1127         brequest, (uint16_t)(USB_HOST_VS_COMMIT_CONTROL << 8UL), streamInterface->interfaceDesc->bInterfaceNumber, 26U,
1128         probe, callbackFn, callbackParam);
1129     return status;
1130 }
1131 
1132 /*!
1133  * @brief video set commit.
1134  *
1135  * This function implements the Video class-specific request (set commit).
1136  *
1137  * @param classHandle    the class handle.
1138  * @param request        setup packet request value.
1139  * @param probe          video probe data
1140  * @param callbackFn     this callback is called after this function completes.
1141  * @param callbackParam  the first parameter in the callback function.
1142  *
1143  * @retval kStatus_USB_Success           Request successful.
1144  * @retval kStatus_USB_InvalidHandle     The classHandle is NULL pointer.
1145  * @retval kStatus_USB_InvalidParameter  The interface descriptor is NULL pointer.
1146  */
USB_HostVideoSetCommit(usb_host_class_handle classHandle,uint8_t brequest,uint8_t * probe,transfer_callback_t callbackFn,void * callbackParam)1147 usb_status_t USB_HostVideoSetCommit(usb_host_class_handle classHandle,
1148                                     uint8_t brequest,
1149                                     uint8_t *probe,
1150                                     transfer_callback_t callbackFn,
1151                                     void *callbackParam)
1152 {
1153     usb_host_video_instance_struct_t *videoInstance = (usb_host_video_instance_struct_t *)classHandle;
1154     usb_host_interface_t *streamInterface;
1155     usb_status_t status;
1156     streamInterface = (usb_host_interface_t *)videoInstance->streamIntfHandle;
1157     if (NULL == streamInterface)
1158     {
1159         return kStatus_USB_InvalidHandle;
1160     }
1161     if (NULL == streamInterface->interfaceDesc)
1162     {
1163         return kStatus_USB_InvalidParameter;
1164     }
1165     status = USB_HostVideoControl(
1166         classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
1167         brequest, (uint16_t)(USB_HOST_VS_COMMIT_CONTROL << 8UL), streamInterface->interfaceDesc->bInterfaceNumber, 26U,
1168         probe, callbackFn, callbackParam);
1169     return status;
1170 }
1171 
1172 #endif
1173