1 /*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 /**************************************************************************/ 12 /** */ 13 /** USBX Component */ 14 /** */ 15 /** Device Video Class */ 16 /** */ 17 /**************************************************************************/ 18 /**************************************************************************/ 19 20 #define UX_SOURCE_CODE 21 22 23 /* Include necessary system files. */ 24 25 #include "ux_api.h" 26 #include "ux_device_class_video.h" 27 #include "ux_device_stack.h" 28 29 30 /**************************************************************************/ 31 /* */ 32 /* FUNCTION RELEASE */ 33 /* */ 34 /* _ux_device_class_video_activate PORTABLE C */ 35 /* 6.2.0 */ 36 /* AUTHOR */ 37 /* */ 38 /* Chaoqiong Xiao, Microsoft Corporation */ 39 /* */ 40 /* DESCRIPTION */ 41 /* */ 42 /* This function initializes the USB Video device. */ 43 /* */ 44 /* INPUT */ 45 /* */ 46 /* command Pointer to video command */ 47 /* */ 48 /* OUTPUT */ 49 /* */ 50 /* Completion Status */ 51 /* */ 52 /* CALLS */ 53 /* */ 54 /* _ux_system_error_handler System error trap */ 55 /* */ 56 /* CALLED BY */ 57 /* */ 58 /* Device Video Class */ 59 /* */ 60 /* RELEASE HISTORY */ 61 /* */ 62 /* DATE NAME DESCRIPTION */ 63 /* */ 64 /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */ 65 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */ 66 /* fixed parameter/variable */ 67 /* names conflict C++ keyword, */ 68 /* resulting in version 6.1.12 */ 69 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */ 70 /* added standalone support, */ 71 /* resulting in version 6.2.0 */ 72 /* */ 73 /**************************************************************************/ _ux_device_class_video_activate(UX_SLAVE_CLASS_COMMAND * command)74UINT _ux_device_class_video_activate(UX_SLAVE_CLASS_COMMAND *command) 75 { 76 77 UX_SLAVE_DEVICE *device; 78 UX_SLAVE_INTERFACE *interface_ptr; 79 UX_SLAVE_CLASS *class_ptr; 80 UX_SLAVE_INTERFACE *control_interface; 81 UX_SLAVE_INTERFACE *stream_interface; 82 UX_DEVICE_CLASS_VIDEO *video; 83 UX_DEVICE_CLASS_VIDEO_STREAM *stream; 84 ULONG stream_index; 85 86 87 /* Get the class container. */ 88 class_ptr = command -> ux_slave_class_command_class_ptr; 89 90 /* Get the class instance in the container. */ 91 video = (UX_DEVICE_CLASS_VIDEO *) class_ptr -> ux_slave_class_instance; 92 93 /* Get the interface that owns this instance. */ 94 interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; 95 96 /* Get the device instance. */ 97 device = &_ux_system_slave -> ux_system_slave_device; 98 video -> ux_device_class_video_device = device; 99 100 /* We only support video interface here. */ 101 if (interface_ptr -> ux_slave_interface_descriptor.bInterfaceClass != UX_DEVICE_CLASS_VIDEO_CLASS) 102 return(UX_NO_CLASS_MATCH); 103 104 /* It's control interface? */ 105 if (interface_ptr -> ux_slave_interface_descriptor.bInterfaceSubClass == UX_DEVICE_CLASS_VIDEO_SUBCLASS_CONTROL) 106 { 107 108 /* Store the interface in the class instance. */ 109 video -> ux_device_class_video_interface = interface_ptr; 110 111 /* Store the class instance into the interface. */ 112 interface_ptr -> ux_slave_interface_class_instance = (VOID *)video; 113 } 114 else 115 { 116 117 /* It's streaming interface. */ 118 stream_interface = interface_ptr; 119 120 /* Separate driver for each interface (IAD not used)? */ 121 if (video -> ux_device_class_video_interface == UX_NULL) 122 { 123 124 /* Always use just 1 stream for 1 interface. */ 125 stream_index = 0; 126 } 127 128 /* Re-use the same driver (IAD used)? */ 129 else 130 { 131 132 /* Re-use saved control interface. */ 133 control_interface = video -> ux_device_class_video_interface; 134 135 /* Calculate stream index. */ 136 stream_index = stream_interface -> ux_slave_interface_descriptor.bInterfaceNumber; 137 stream_index -= control_interface -> ux_slave_interface_descriptor.bInterfaceNumber; 138 stream_index --; 139 140 } 141 142 /* Sanity check. */ 143 if (stream_index >= video -> ux_device_class_video_streams_nb) 144 { 145 146 /* Error trap! */ 147 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); 148 return(UX_MEMORY_INSUFFICIENT); 149 } 150 151 /* Locate stream based on interface number. */ 152 stream = &video -> ux_device_class_video_streams[stream_index]; 153 154 /* Store the interface for the stream. */ 155 stream -> ux_device_class_video_stream_interface = stream_interface; 156 157 /* Store the class instance into the interface. */ 158 stream_interface -> ux_slave_interface_class_instance = (VOID *)video; 159 160 #if defined(UX_DEVICE_STANDALONE) 161 162 /* Reset stream task state. */ 163 stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET; 164 stream -> ux_device_class_video_stream_task_status = UX_SUCCESS; 165 #endif 166 167 } 168 169 /* If there is a activate function call it. */ 170 if (video -> ux_device_class_video_callbacks.ux_slave_class_video_instance_activate != UX_NULL) 171 { 172 173 /* Invoke the application. */ 174 video -> ux_device_class_video_callbacks.ux_slave_class_video_instance_activate(video); 175 } 176 177 /* Return completion status. */ 178 return(UX_SUCCESS); 179 } 180