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_control_request PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function issues a control request to a given video entity */
45 /* (unit or terminal). */
46 /* The unit or terminal IDs can be parsed once the video device is */
47 /* ready, via ux_host_class_video_entities_parse. */
48 /* */
49 /* Note: only one VideoStreaming interface is supported for now. */
50 /* */
51 /* INPUT */
52 /* */
53 /* video Pointer to video class */
54 /* request The request to issue */
55 /* interface_index The interface index */
56 /* 0: VideoControl interface */
57 /* 1: VideoStreaming 1 */
58 /* N: VideoStreaming N */
59 /* entity_id The terminal or unit ID */
60 /* control_selector The control selector */
61 /* parameter Pointer to parameter block */
62 /* parameter_size Size of parameter block */
63 /* */
64 /* OUTPUT */
65 /* */
66 /* Completion Status */
67 /* */
68 /* CALLS */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application */
73 /* */
74 /* RELEASE HISTORY */
75 /* */
76 /* DATE NAME DESCRIPTION */
77 /* */
78 /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */
79 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
80 /* refined macros names, */
81 /* resulting in version 6.1.10 */
82 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
83 /* fixed parameter/variable */
84 /* names conflict C++ keyword, */
85 /* resulting in version 6.1.12 */
86 /* */
87 /**************************************************************************/
_ux_host_class_video_control_request(UX_HOST_CLASS_VIDEO * video,UINT request,UCHAR interface_index,UINT entity_id,UINT control_selector,UCHAR * parameter,UINT parameter_size)88 UINT _ux_host_class_video_control_request(UX_HOST_CLASS_VIDEO *video,
89 UINT request, UCHAR interface_index,
90 UINT entity_id, UINT control_selector,
91 UCHAR *parameter, UINT parameter_size)
92 {
93
94 UX_ENDPOINT *control_endpoint;
95 UX_TRANSFER *transfer_request;
96 UINT status;
97 UCHAR *control_buffer;
98 UCHAR request_direction;
99 UX_INTERFACE *interface_ptr;
100 UCHAR interface_number;
101
102
103 /* Ensure the instance is valid. */
104 if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS)
105 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
106
107 /* Protect thread reentry to this instance. */
108 status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore_control_request, UX_WAIT_FOREVER);
109 if (status != UX_SUCCESS)
110 return(status);
111
112 /* We need to get the default control endpoint transfer request pointer. */
113 control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint;
114 transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
115
116 /* Need to allocate memory for the control buffer. */
117 control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, parameter_size);
118 if (control_buffer == UX_NULL)
119 {
120
121 /* Unprotect thread reentry to this instance. */
122 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
123
124 /* Return an error. */
125 return(UX_MEMORY_INSUFFICIENT);
126 }
127
128 /* Get the request direction from the control request ID. */
129 request_direction = (request & 0x80);
130
131 /* Are we setting a value? */
132 if (request_direction == 0)
133 {
134
135 /* Put parameter block in buffer. */
136 if (parameter_size)
137 _ux_utility_memory_copy(control_buffer, parameter, parameter_size); /* Use case of memcpy is verified. */
138 }
139
140 /* Protect the control endpoint semaphore here. It will be unprotected in the
141 transfer request function. */
142 status = _ux_host_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
143
144 /* Check for status. */
145 if (status != UX_SUCCESS)
146 {
147
148 /* Something went wrong. */
149 _ux_utility_memory_free(control_buffer);
150 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
151 return(status);
152 }
153
154 /* Get the interface number. */
155 if (interface_index == 0)
156 interface_number = (UCHAR)video -> ux_host_class_video_control_interface_number;
157 else
158 {
159
160 /* Only one streaming interface is supported now. */
161 interface_ptr = video -> ux_host_class_video_streaming_interface;
162 interface_number = (UCHAR)interface_ptr -> ux_interface_descriptor.bInterfaceNumber;
163 }
164
165 /* Create a transfer request for the request. */
166 transfer_request -> ux_transfer_request_data_pointer = control_buffer;
167 transfer_request -> ux_transfer_request_requested_length = parameter_size;
168 transfer_request -> ux_transfer_request_function = request;
169 transfer_request -> ux_transfer_request_type = request_direction | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
170 transfer_request -> ux_transfer_request_value = (control_selector << 8);
171 transfer_request -> ux_transfer_request_index = interface_number | (entity_id << 8);
172
173 /* Send request to HCD layer. */
174 status = _ux_host_stack_transfer_request(transfer_request);
175
176 /* Check for correct transfer. */
177 if (status != UX_SUCCESS)
178 {
179
180 /* Free the previous control buffer. */
181 _ux_utility_memory_free(control_buffer);
182
183 /* Unprotect thread reentry to this instance. */
184 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
185
186 /* Return completion status. */
187 return(status);
188 }
189
190 /* Are we getting a value? */
191 if (request_direction)
192 {
193
194 /* Then store it in the caller's buffer. */
195 if (parameter_size)
196 _ux_utility_memory_copy(parameter, control_buffer, parameter_size); /* Use case of memcpy is verified. */
197 }
198
199 /* Free all used resources. */
200 _ux_utility_memory_free(control_buffer);
201
202 /* Unprotect thread reentry to this instance. */
203 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
204
205 /* Return completion status. */
206 return(status);
207 }
208
209 /**************************************************************************/
210 /* */
211 /* FUNCTION RELEASE */
212 /* */
213 /* _uxe_host_class_video_control_request PORTABLE C */
214 /* 6.3.0 */
215 /* AUTHOR */
216 /* */
217 /* Yajun Xia, Microsoft Corporation */
218 /* */
219 /* DESCRIPTION */
220 /* */
221 /* This function checks errors in video control request function call. */
222 /* */
223 /* INPUT */
224 /* */
225 /* video Pointer to video class */
226 /* request The request to issue */
227 /* interface_index The interface index */
228 /* 0: VideoControl interface */
229 /* 1: VideoStreaming 1 */
230 /* N: VideoStreaming N */
231 /* entity_id The terminal or unit ID */
232 /* control_selector The control selector */
233 /* parameter Pointer to parameter block */
234 /* parameter_size Size of parameter block */
235 /* */
236 /* OUTPUT */
237 /* */
238 /* Completion Status */
239 /* */
240 /* CALLS */
241 /* */
242 /* _ux_host_class_video_control_request Video control request */
243 /* */
244 /* CALLED BY */
245 /* */
246 /* Application */
247 /* Video Class */
248 /* */
249 /* RELEASE HISTORY */
250 /* */
251 /* DATE NAME DESCRIPTION */
252 /* */
253 /* 10-31-2023 Yajun xia Initial Version 6.3.0 */
254 /* */
255 /**************************************************************************/
_uxe_host_class_video_control_request(UX_HOST_CLASS_VIDEO * video,UINT request,UCHAR interface_index,UINT entity_id,UINT control_selector,UCHAR * parameter,UINT parameter_size)256 UINT _uxe_host_class_video_control_request(UX_HOST_CLASS_VIDEO *video,
257 UINT request, UCHAR interface_index,
258 UINT entity_id, UINT control_selector,
259 UCHAR *parameter, UINT parameter_size)
260 {
261
262 /* Sanity checks. */
263 if (video == UX_NULL)
264 return(UX_INVALID_PARAMETER);
265
266 /* Call the video control request function. */
267 return(_ux_host_class_video_control_request(video, request, interface_index,
268 entity_id, control_selector,
269 parameter, parameter_size));
270 }
271