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 /**************************************************************************/
14 /** */
15 /** USBX Component */
16 /** */
17 /** Video Class */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #define UX_SOURCE_CODE
26
27 #include "ux_api.h"
28 #include "ux_host_class_video.h"
29 #include "ux_host_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_host_class_video_format_data_get PORTABLE C */
37 /* 6.3.0 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function finds the format data within the input terminal. */
45 /* */
46 /* INPUT */
47 /* */
48 /* video Pointer to video class */
49 /* format_parameter Format Parameter structure */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* Completion Status */
54 /* */
55 /* CALLS */
56 /* */
57 /* _ux_system_error_handler Log system error */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* Video Class */
62 /* */
63 /* RELEASE HISTORY */
64 /* */
65 /* DATE NAME DESCRIPTION */
66 /* */
67 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
68 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
69 /* resulting in version 6.1 */
70 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
71 /* improved extracted data, */
72 /* resulting in version 6.3.0 */
73 /* */
74 /**************************************************************************/
_ux_host_class_video_format_data_get(UX_HOST_CLASS_VIDEO * video,UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA * format_parameter)75 UINT _ux_host_class_video_format_data_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA *format_parameter)
76 {
77
78 UCHAR *descriptor;
79 ULONG total_descriptor_length;
80 ULONG descriptor_length;
81 ULONG descriptor_type;
82 ULONG descriptor_subtype;
83 UCHAR *guid;
84
85
86 /* Get the descriptor to the selected format. */
87 descriptor = video -> ux_host_class_video_format_address;
88 total_descriptor_length = video -> ux_host_class_video_length_formats;
89
90 /* Descriptors are arranged in order. First FORMAT then FRAME. */
91 while (total_descriptor_length)
92 {
93
94 /* Gather the length, type and subtype of the descriptor. */
95 descriptor_length = *descriptor;
96 descriptor_type = *(descriptor + 1);
97 descriptor_subtype = *(descriptor + 2);
98
99 /* Make sure this descriptor has at least the minimum length. */
100 if (descriptor_length < 3)
101 {
102
103 /* Error trap. */
104 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
105
106 /* If trace is enabled, insert this event into the trace buffer. */
107 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
108
109 return(UX_DESCRIPTOR_CORRUPTED);
110 }
111
112 /* Must be CS_INTERFACE. */
113 if (descriptor_type == UX_HOST_CLASS_VIDEO_CS_INTERFACE)
114 {
115
116 /* Process relative to descriptor type. */
117 guid = UX_NULL;
118 switch (descriptor_subtype)
119 {
120
121 case UX_HOST_CLASS_VIDEO_VS_FORMAT_UNCOMPRESSED : /* guidFormat @ 5 */
122 /* Fall through. */
123 case UX_HOST_CLASS_VIDEO_VS_FORMAT_FRAME_BASED : /* guidFormat @ 5 */
124 /* Fall through. */
125 case UX_HOST_CLASS_VIDEO_VS_FORMAT_STREAM_BASED : /* guidFormat @ 4, no frame */
126 /* Fall through. */
127 case UX_HOST_CLASS_VIDEO_VS_FORMAT_MPEG2TS : /* guidStrideFormat @ 7, no frame */
128 if (descriptor_subtype == UX_HOST_CLASS_VIDEO_VS_FORMAT_STREAM_BASED)
129 guid = (descriptor + 4);
130 else if (descriptor_subtype == UX_HOST_CLASS_VIDEO_VS_FORMAT_MPEG2TS)
131 guid = (descriptor + 7);
132 else
133 guid = (descriptor + 5);
134
135 /* Fall through. */
136 case UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG : /* no GUID */
137 /* Fall through. */
138 case UX_HOST_CLASS_VIDEO_VS_FORMAT_H264 : /* no GUID */
139 /* Fall through. */
140 case UX_HOST_CLASS_VIDEO_VS_FORMAT_H264_SIMULCAST :
141 /* Fall through. */
142 case UX_HOST_CLASS_VIDEO_VS_FORMAT_VP8 : /* no GUID */
143 /* Fall through. */
144 case UX_HOST_CLASS_VIDEO_VS_FORMAT_VP8_SIMULCAST :
145 /* Fall through. */
146 case UX_HOST_CLASS_VIDEO_VS_FORMAT_DV : /* no GUID, no frame */
147
148 /* We found a Format descriptor. Is it the right one ? */
149 if (format_parameter -> ux_host_class_video_parameter_format_requested == *(descriptor + 3))
150 {
151
152 /* Save the subtype for this format. */
153 format_parameter -> ux_host_class_video_parameter_format_subtype = descriptor_subtype;
154
155 /* Save the number of frame descriptors associated with this format. */
156 if (descriptor_subtype != UX_HOST_CLASS_VIDEO_VS_FORMAT_STREAM_BASED &&
157 descriptor_subtype != UX_HOST_CLASS_VIDEO_VS_FORMAT_DV &&
158 descriptor_subtype != UX_HOST_CLASS_VIDEO_VS_FORMAT_MPEG2TS)
159 format_parameter -> ux_host_class_video_parameter_number_frame_descriptors = *(descriptor + 4);
160 else
161 format_parameter -> ux_host_class_video_parameter_number_frame_descriptors = 0;
162
163 /* Save the GUID of frame descriptor. */
164 format_parameter -> ux_host_class_video_parameter_format_guid = guid;
165
166 /* Save the address of this format. */
167 video -> ux_host_class_video_current_format_address = descriptor;
168
169 /* And the current format index. */
170 video -> ux_host_class_video_current_format = format_parameter -> ux_host_class_video_parameter_format_requested;
171
172 /* We are done here. */
173 return(UX_SUCCESS);
174
175 }
176 break;
177 }
178 }
179
180 /* Verify if the descriptor is still valid. */
181 if (descriptor_length > total_descriptor_length)
182 {
183
184 /* Error trap. */
185 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
186
187 /* If trace is enabled, insert this event into the trace buffer. */
188 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
189
190 return(UX_DESCRIPTOR_CORRUPTED);
191 }
192
193 /* Jump to the next descriptor if we have not reached the end. */
194 descriptor += descriptor_length;
195
196 /* And adjust the length left to parse in the descriptor. */
197 total_descriptor_length -= descriptor_length;
198 }
199
200 /* Error trap. */
201 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE);
202
203 /* We get here when either the report descriptor has a problem or we could
204 not find the right video device. */
205 return(UX_HOST_CLASS_VIDEO_WRONG_TYPE);
206 }
207