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_entities_parse PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function parsees all interface descriptors and their video */
45 /* class specific descriptors. */
46 /* */
47 /* The function scans the device configuration descriptor. Once the */
48 /* interface descriptors of the video instance are found, each video */
49 /* class descriptors belong to the interface are passed to parse */
50 /* function for caller one by one to parse. The interface descriptor */
51 /* is also passed to provide more information. Another pointer to */
52 /* arguments is also available as parse function parameter for caller */
53 /* to pass necessary caller specific data to process in parse function.*/
54 /* */
55 /* The descriptor parsing can be terminated by returning non-zero */
56 /* code in parse function. */
57 /* */
58 /* INPUT */
59 /* */
60 /* video Pointer to video instance */
61 /* parse_function Parse function for each */
62 /* video class descriptor */
63 /* arg Parse function argument */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* Completion Status */
68 /* */
69 /* CALLS */
70 /* */
71 /* CALLED BY */
72 /* */
73 /* Video Class */
74 /* Application */
75 /* */
76 /* RELEASE HISTORY */
77 /* */
78 /* DATE NAME DESCRIPTION */
79 /* */
80 /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */
81 /* 08-02-2021 Wen Wang Modified comment(s), */
82 /* fixed spelling error, */
83 /* resulting in version 6.1.8 */
84 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
85 /* fixed parameter/variable */
86 /* names conflict C++ keyword, */
87 /* resulting in version 6.1.12 */
88 /* */
89 /**************************************************************************/
_ux_host_class_video_entities_parse(UX_HOST_CLASS_VIDEO * video,UINT (* parse_function)(VOID * arg,UCHAR * packed_interface_descriptor,UCHAR * packed_entity_descriptor),VOID * arg)90 UINT _ux_host_class_video_entities_parse(UX_HOST_CLASS_VIDEO *video,
91 UINT(*parse_function)(VOID *arg,
92 UCHAR *packed_interface_descriptor,
93 UCHAR *packed_entity_descriptor),
94 VOID* arg)
95 {
96
97 UCHAR *descriptor;
98 UCHAR *interface_descriptor;
99 UX_INTERFACE *interface_ptr;
100 ULONG total_descriptor_length;
101 ULONG descriptor_length;
102 ULONG descriptor_type;
103 UINT status;
104
105
106 /* Device state check. */
107 if (video -> ux_host_class_video_device -> ux_device_state != UX_DEVICE_CONFIGURED)
108 return(UX_HOST_CLASS_VIDEO_DEVICE_NOT_READY);
109
110 /* Get the descriptor to the selected format. */
111 descriptor = video -> ux_host_class_video_configuration_descriptor;
112 total_descriptor_length = video -> ux_host_class_video_configuration_descriptor_length;
113
114 /* Haven't found interface yet. */
115 interface_descriptor = UX_NULL;
116
117 /* Scan the descriptor for the Video Streaming interface. */
118 while (total_descriptor_length)
119 {
120
121 /* Gather the length, type and subtype of the descriptor. */
122 descriptor_length = *descriptor;
123 descriptor_type = *(descriptor + 1);
124
125 /* Make sure this descriptor has at least the minimum length. */
126 if (descriptor_length < 3)
127 return(UX_DESCRIPTOR_CORRUPTED);
128
129 /* Process relative to descriptor type. */
130 switch (descriptor_type)
131 {
132
133 case UX_INTERFACE_DESCRIPTOR_ITEM:
134
135 /* Haven't found it. */
136 interface_descriptor = UX_NULL;
137
138 /* Ensure we have the correct interface for Video Control/Streaming. */
139 if (descriptor[5] == UX_HOST_CLASS_VIDEO_CLASS)
140 {
141
142 /* VideoControl Interface. */
143 if (descriptor[6] == UX_HOST_CLASS_VIDEO_SUBCLASS_CONTROL)
144
145 /* Mark we have found it. */
146 interface_descriptor = descriptor;
147 else
148 {
149
150 /* VideoStreaming interface, currently only one supported. */
151 interface_ptr = video -> ux_host_class_video_streaming_interface;
152 if (descriptor[2] == interface_ptr -> ux_interface_descriptor.bInterfaceNumber)
153
154 /* Mark we have found it. */
155 interface_descriptor = descriptor;
156 }
157 }
158 break;
159
160 case UX_HOST_CLASS_VIDEO_CS_INTERFACE:
161
162 /* Have we found the video interface yet? */
163 if (interface_descriptor != UX_NULL)
164 {
165
166 /* Yes, parse the entity descriptor. */
167 status = parse_function(arg, interface_descriptor, descriptor);
168
169 /* Terminate the parsing if status is not 0. */
170 if (status)
171 return(UX_SUCCESS);
172 }
173 break;
174 }
175
176 /* Verify if the descriptor is still valid. */
177 if (descriptor_length > total_descriptor_length)
178 return(UX_DESCRIPTOR_CORRUPTED);
179
180 /* Jump to the next descriptor if we have not reached the end. */
181 descriptor += descriptor_length;
182
183 /* And adjust the length left to parse in the descriptor. */
184 total_descriptor_length -= descriptor_length;
185 }
186
187 /* We get here when all descriptors scanned. */
188 return(UX_SUCCESS);
189 }
190
191 /**************************************************************************/
192 /* */
193 /* FUNCTION RELEASE */
194 /* */
195 /* _uxe_host_class_video_entities_parse PORTABLE C */
196 /* 6.3.0 */
197 /* AUTHOR */
198 /* */
199 /* Yajun Xia, Microsoft Corporation */
200 /* */
201 /* DESCRIPTION */
202 /* */
203 /* This function checks errors in video entities parse function call. */
204 /* */
205 /* INPUT */
206 /* */
207 /* video Pointer to video instance */
208 /* parse_function Parse function for each */
209 /* video class descriptor */
210 /* arg Parse function argument */
211 /* */
212 /* OUTPUT */
213 /* */
214 /* Completion Status */
215 /* */
216 /* CALLS */
217 /* */
218 /* _ux_host_class_video_entities_parse Video entities parse */
219 /* */
220 /* CALLED BY */
221 /* */
222 /* Video Class */
223 /* Application */
224 /* */
225 /* RELEASE HISTORY */
226 /* */
227 /* DATE NAME DESCRIPTION */
228 /* */
229 /* 10-31-2023 Yajun xia Initial Version 6.3.0 */
230 /* */
231 /**************************************************************************/
_uxe_host_class_video_entities_parse(UX_HOST_CLASS_VIDEO * video,UINT (* parse_function)(VOID * arg,UCHAR * packed_interface_descriptor,UCHAR * packed_entity_descriptor),VOID * arg)232 UINT _uxe_host_class_video_entities_parse(UX_HOST_CLASS_VIDEO *video,
233 UINT(*parse_function)(VOID *arg,
234 UCHAR *packed_interface_descriptor,
235 UCHAR *packed_entity_descriptor),
236 VOID* arg)
237 {
238
239 /* Sanity checks. */
240 if (video == UX_NULL)
241 return(UX_INVALID_PARAMETER);
242
243 /* Call the actual video entities parse function. */
244 return(_ux_host_class_video_entities_parse(video, parse_function, arg));
245 }