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