1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** Video Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_host_class_video.h"
30 #include "ux_host_stack.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_video_control_request PORTABLE C */
38 /* 6.1.12 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function issues a control request to a given video entity */
46 /* (unit or terminal). */
47 /* The unit or terminal IDs can be parsed once the video device is */
48 /* ready, via ux_host_class_video_entities_parse. */
49 /* */
50 /* Note: only one VideoStreaming interface is supported for now. */
51 /* */
52 /* INPUT */
53 /* */
54 /* video Pointer to video class */
55 /* request The request to issue */
56 /* interface_index The interface index */
57 /* 0: VideoControl interface */
58 /* 1: VideoStreaming 1 */
59 /* N: VideoStreaming N */
60 /* entity_id The terminal or unit ID */
61 /* control_selector The control selector */
62 /* parameter Pointer to parameter block */
63 /* parameter_size Size of parameter block */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* Completion Status */
68 /* */
69 /* CALLS */
70 /* */
71 /* CALLED BY */
72 /* */
73 /* Application */
74 /* */
75 /* RELEASE HISTORY */
76 /* */
77 /* DATE NAME DESCRIPTION */
78 /* */
79 /* 09-30-2020 Chaoqiong Xiao Initial Version 6.1 */
80 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
81 /* refined macros names, */
82 /* resulting in version 6.1.10 */
83 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
84 /* fixed parameter/variable */
85 /* names conflict C++ keyword, */
86 /* resulting in version 6.1.12 */
87 /* */
88 /**************************************************************************/
_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)89 UINT _ux_host_class_video_control_request(UX_HOST_CLASS_VIDEO *video,
90 UINT request, UCHAR interface_index,
91 UINT entity_id, UINT control_selector,
92 UCHAR *parameter, UINT parameter_size)
93 {
94
95 UX_ENDPOINT *control_endpoint;
96 UX_TRANSFER *transfer_request;
97 UINT status;
98 UCHAR *control_buffer;
99 UCHAR request_direction;
100 UX_INTERFACE *interface_ptr;
101 UCHAR interface_number;
102
103
104 /* Ensure the instance is valid. */
105 if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS)
106 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
107
108 /* Protect thread reentry to this instance. */
109 status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore_control_request, UX_WAIT_FOREVER);
110 if (status != UX_SUCCESS)
111 return(status);
112
113 /* We need to get the default control endpoint transfer request pointer. */
114 control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint;
115 transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
116
117 /* Need to allocate memory for the control buffer. */
118 control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, parameter_size);
119 if (control_buffer == UX_NULL)
120 {
121
122 /* Unprotect thread reentry to this instance. */
123 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
124
125 /* Return an error. */
126 return(UX_MEMORY_INSUFFICIENT);
127 }
128
129 /* Get the request direction from the control request ID. */
130 request_direction = (request & 0x80);
131
132 /* Are we setting a value? */
133 if (request_direction == 0)
134 {
135
136 /* Put parameter block in buffer. */
137 if (parameter_size)
138 _ux_utility_memory_copy(control_buffer, parameter, parameter_size); /* Use case of memcpy is verified. */
139 }
140
141 /* Protect the control endpoint semaphore here. It will be unprotected in the
142 transfer request function. */
143 status = _ux_host_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
144
145 /* Check for status. */
146 if (status != UX_SUCCESS)
147 {
148
149 /* Something went wrong. */
150 _ux_utility_memory_free(control_buffer);
151 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
152 return(status);
153 }
154
155 /* Get the interface number. */
156 if (interface_index == 0)
157 interface_number = (UCHAR)video -> ux_host_class_video_control_interface_number;
158 else
159 {
160
161 /* Only one streaming interface is supported now. */
162 interface_ptr = video -> ux_host_class_video_streaming_interface;
163 interface_number = (UCHAR)interface_ptr -> ux_interface_descriptor.bInterfaceNumber;
164 }
165
166 /* Create a transfer request for the request. */
167 transfer_request -> ux_transfer_request_data_pointer = control_buffer;
168 transfer_request -> ux_transfer_request_requested_length = parameter_size;
169 transfer_request -> ux_transfer_request_function = request;
170 transfer_request -> ux_transfer_request_type = request_direction | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
171 transfer_request -> ux_transfer_request_value = (control_selector << 8);
172 transfer_request -> ux_transfer_request_index = interface_number | (entity_id << 8);
173
174 /* Send request to HCD layer. */
175 status = _ux_host_stack_transfer_request(transfer_request);
176
177 /* Check for correct transfer. */
178 if (status != UX_SUCCESS)
179 {
180
181 /* Free the previous control buffer. */
182 _ux_utility_memory_free(control_buffer);
183
184 /* Unprotect thread reentry to this instance. */
185 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
186
187 /* Return completion status. */
188 return(status);
189 }
190
191 /* Are we getting a value? */
192 if (request_direction)
193 {
194
195 /* Then store it in the caller's buffer. */
196 if (parameter_size)
197 _ux_utility_memory_copy(parameter, control_buffer, parameter_size); /* Use case of memcpy is verified. */
198 }
199
200 /* Free all used resources. */
201 _ux_utility_memory_free(control_buffer);
202
203 /* Unprotect thread reentry to this instance. */
204 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore_control_request);
205
206 /* Return completion status. */
207 return(status);
208 }
209