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 VS_FRAME_UNCOMPRESSED : wWidth @ 5, wHeight @ 7, dwDefaultFrameInterval @ 21, bFrameIntervalType @ 25, intervals @ 26
33 VS_FRAME_MJPEG : wWidth @ 5, wHeight @ 7, dwDefaultFrameInterval @ 21, bFrameIntervalType @ 25, intervals @ 26
34 VS_FRAME_FRAME_BASED : wWidth @ 5, wHeight @ 7, dwDefaultFrameInterval @ 17, bFrameIntervalType @ 21, intervals @ 26
35 VS_FRAME_H264 : wWidth @ 4, wHeight @ 6, dwDefaultFrameInterval @ 39, bNumFrameIntervals @ 43, intervals @ 44
36 VS_FRAME_VP8 : wWidth @ 4, wHeight @ 6, dwDefaultFrameInterval @ 26, bNumFrameIntervals @ 30, intervals @ 31
37 */
38 static const UCHAR _ux_host_class_video_frame_descriptor_offsets[][5] =
39 {
40 { 5, 7, 21, 25, 26 },
41 { 5, 7, 17, 21, 26 },
42 { 4, 6, 39, 43, 44 },
43 { 4, 6, 26, 30, 31 },
44 };
45 #define _OFFSETS_UNCOMPRESSED_MJPEG 0
46 #define _OFFSETS_FRAME_BASED 1
47 #define _OFFSETS_H264 2
48 #define _OFFSETS_VP8 3
49
50
51 /**************************************************************************/
52 /* */
53 /* FUNCTION RELEASE */
54 /* */
55 /* _ux_host_class_video_frame_data_get PORTABLE C */
56 /* 6.3.0 */
57 /* AUTHOR */
58 /* */
59 /* Chaoqiong Xiao, Microsoft Corporation */
60 /* */
61 /* DESCRIPTION */
62 /* */
63 /* This function finds the frame data within the input terminal. */
64 /* */
65 /* INPUT */
66 /* */
67 /* video Pointer to video class */
68 /* frame_data Frame request structure */
69 /* */
70 /* OUTPUT */
71 /* */
72 /* Completion Status */
73 /* */
74 /* CALLS */
75 /* */
76 /* _ux_system_error_handler Log system error */
77 /* _ux_utility_descriptor_parse Parse descriptor */
78 /* */
79 /* CALLED BY */
80 /* */
81 /* Video Class */
82 /* */
83 /* RELEASE HISTORY */
84 /* */
85 /* DATE NAME DESCRIPTION */
86 /* */
87 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
88 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
89 /* resulting in version 6.1 */
90 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
91 /* improved extracted data, */
92 /* resulting in version 6.3.0 */
93 /* */
94 /**************************************************************************/
_ux_host_class_video_frame_data_get(UX_HOST_CLASS_VIDEO * video,UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA * frame_parameter)95 UINT _ux_host_class_video_frame_data_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA *frame_parameter)
96 {
97
98 UCHAR *descriptor;
99 ULONG total_descriptor_length;
100 ULONG descriptor_length;
101 ULONG descriptor_type;
102 ULONG descriptor_subtype;
103 UCHAR *field_offsets;
104
105
106 /* Get the descriptor to the selected format. */
107 descriptor = video -> ux_host_class_video_current_format_address;
108 total_descriptor_length = video -> ux_host_class_video_length_formats;
109
110 /* Descriptors are arranged in order. First FORMAT then FRAME. */
111 while (total_descriptor_length)
112 {
113
114 /* Gather the length, type and subtype of the descriptor. */
115 descriptor_length = *descriptor;
116 descriptor_type = *(descriptor + 1);
117 descriptor_subtype = *(descriptor + 2);
118
119 /* Make sure this descriptor has at least the minimum length. */
120 if (descriptor_length < 3)
121 {
122
123 /* Error trap. */
124 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
125
126 /* If trace is enabled, insert this event into the trace buffer. */
127 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0)
128
129 return(UX_DESCRIPTOR_CORRUPTED);
130 }
131
132 /* Must be CS_INTERFACE. */
133 if (descriptor_type == UX_HOST_CLASS_VIDEO_CS_INTERFACE)
134 {
135
136 /* Process relative to descriptor type. */
137 switch (descriptor_subtype)
138 {
139
140 case UX_HOST_CLASS_VIDEO_VS_FRAME_UNCOMPRESSED : /* wWidth @ 5, wHeight @ 7, dwDefaultFrameInterval @ 21, bFrameIntervalType @ 25, intervals @ 26 */
141 case UX_HOST_CLASS_VIDEO_VS_FRAME_MJPEG : /* wWidth @ 5, wHeight @ 7, dwDefaultFrameInterval @ 21, bFrameIntervalType @ 25, intervals @ 26 */
142 case UX_HOST_CLASS_VIDEO_VS_FRAME_FRAME_BASED : /* wWidth @ 5, wHeight @ 7, dwDefaultFrameInterval @ 17, bFrameIntervalType @ 21, intervals @ 26 */
143 case UX_HOST_CLASS_VIDEO_VS_FRAME_H264 : /* wWidth @ 4, wHeight @ 6, dwDefaultFrameInterval @ 39, bNumFrameIntervals @ 43, intervals @ 44 */
144 case UX_HOST_CLASS_VIDEO_VS_FRAME_VP8 : /* wWidth @ 4, wHeight @ 6, dwDefaultFrameInterval @ 26, bNumFrameIntervals @ 30, intervals @ 31 */
145
146 /* We found a Frame descriptor. Is it the right one ? */
147 if (frame_parameter -> ux_host_class_video_parameter_frame_requested == *(descriptor + 3))
148 {
149
150 /* Get key offsets. */
151 if (descriptor_subtype == UX_HOST_CLASS_VIDEO_VS_FRAME_FRAME_BASED)
152 field_offsets = (UCHAR*)_ux_host_class_video_frame_descriptor_offsets[_OFFSETS_FRAME_BASED];
153 else if (descriptor_subtype == UX_HOST_CLASS_VIDEO_VS_FRAME_H264)
154 field_offsets = (UCHAR*)_ux_host_class_video_frame_descriptor_offsets[_OFFSETS_H264];
155 else if (descriptor_subtype == UX_HOST_CLASS_VIDEO_VS_FRAME_VP8)
156 field_offsets = (UCHAR*)_ux_host_class_video_frame_descriptor_offsets[_OFFSETS_VP8];
157 else
158 field_offsets = (UCHAR*)_ux_host_class_video_frame_descriptor_offsets[_OFFSETS_UNCOMPRESSED_MJPEG];
159
160 /* Save the frame subtype. */
161 frame_parameter -> ux_host_class_video_parameter_frame_subtype = descriptor_type;
162
163 /* Save useful frame parameters. */
164 frame_parameter -> ux_host_class_video_parameter_frame_width = _ux_utility_short_get(descriptor + field_offsets[0]);
165 frame_parameter -> ux_host_class_video_parameter_frame_height = _ux_utility_short_get(descriptor + field_offsets[1]);
166 frame_parameter -> ux_host_class_video_parameter_default_frame_interval = _ux_utility_long_get(descriptor + field_offsets[2]);
167 frame_parameter -> ux_host_class_video_parameter_frame_interval_type = *(descriptor + field_offsets[3]);
168 frame_parameter -> ux_host_class_video_parameter_frame_intervals = (descriptor + field_offsets[4]);
169
170 video -> ux_host_class_video_current_frame_address = descriptor;
171 video -> ux_host_class_video_current_frame_interval = frame_parameter -> ux_host_class_video_parameter_default_frame_interval;
172
173 /* We are done here. */
174 return(UX_SUCCESS);
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