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