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_transfer_buffer_add PORTABLE C */
37 /* 6.3.0 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function adds a buffer for video transfer requests. */
45 /* */
46 /* Note check ux_host_class_video_max_payload_get to see minimum */
47 /* recommended buffer size. */
48 /* */
49 /* INPUT */
50 /* */
51 /* video Pointer to video class */
52 /* buffer Pointer to data buffer */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* Completion Status */
57 /* */
58 /* CALLS */
59 /* */
60 /* _ux_host_stack_class_instance_verify Verify instance is valid */
61 /* _ux_host_stack_transfer_request Process transfer request */
62 /* _ux_host_semaphore_get Get semaphore */
63 /* _ux_host_semaphore_put Release semaphore */
64 /* _ux_system_error_handler Log system error */
65 /* */
66 /* CALLED BY */
67 /* */
68 /* Application */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
75 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
76 /* resulting in version 6.1 */
77 /* 10-15-2021 Chaoqiong Xiao Modified comment(s), */
78 /* use pre-calculated value */
79 /* instead of wMaxPacketSize, */
80 /* resulting in version 6.1.9 */
81 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
82 /* refined macros names, */
83 /* resulting in version 6.1.10 */
84 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
85 /* fixed standalone compile, */
86 /* resulting in version 6.1.11 */
87 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
88 /* set pending on endpoint, */
89 /* resulting in version 6.1.12 */
90 /* 10-31-2023 Yajun xia Modified comment(s), */
91 /* resulting in version 6.3.0 */
92 /* */
93 /**************************************************************************/
_ux_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO * video,UCHAR * buffer)94 UINT _ux_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO *video, UCHAR* buffer)
95 {
96
97 UINT status;
98 UX_TRANSFER *transfer_request;
99 UX_ENDPOINT *endpoint;
100 ULONG transfer_index;
101 ULONG packet_size;
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 {
106
107 /* Error trap. */
108 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN);
109
110 /* If trace is enabled, insert this event into the trace buffer. */
111 // UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, video, 0, 0, UX_TRACE_ERRORS, 0, 0)
112
113 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
114 }
115
116 /* Protect thread reentry to this instance. */
117 status = _ux_host_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER);
118 if (status != UX_SUCCESS)
119 return(status);
120
121 /* Get endpoint. */
122 endpoint = video -> ux_host_class_video_isochronous_endpoint;
123
124 /* Ensure we have a selected interface that allows isoch transmission. */
125 if ((endpoint == UX_NULL) ||
126 (endpoint -> ux_endpoint_descriptor.wMaxPacketSize == 0))
127 {
128
129 /* Unprotect thread reentry to this instance. */
130 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore);
131
132 /* Error trap. */
133 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE);
134
135 /* Return error status. */
136 return(UX_HOST_CLASS_VIDEO_WRONG_INTERFACE);
137 }
138
139 transfer_index = video->ux_host_class_video_transfer_request_start_index;
140 transfer_index ++;
141 if (transfer_index == UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT)
142 transfer_index = 0;
143 if (transfer_index == video->ux_host_class_video_transfer_request_end_index)
144 {
145
146 /* Unprotect thread reentry to this instance. */
147 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore);
148
149 /* Return error status. */
150 return(UX_MEMORY_ARRAY_FULL);
151 }
152
153 transfer_request = &video->ux_host_class_video_transfer_requests[video->ux_host_class_video_transfer_request_start_index];
154 video->ux_host_class_video_transfer_request_start_index = transfer_index;
155
156 /* Select the direction. We do this by taking the endpoint direction. */
157 transfer_request -> ux_transfer_request_type = endpoint ->
158 ux_endpoint_descriptor.bEndpointAddress & UX_REQUEST_DIRECTION;
159
160 /* Calculate packet size. */
161 packet_size = video -> ux_host_class_video_current_max_payload_size;
162
163 /* Fill the transfer request with all the required fields. */
164 transfer_request -> ux_transfer_request_endpoint = endpoint;
165 transfer_request -> ux_transfer_request_data_pointer = buffer;
166 transfer_request -> ux_transfer_request_requested_length = packet_size;
167 transfer_request -> ux_transfer_request_completion_function = _ux_host_class_video_transfer_request_callback;
168 transfer_request -> ux_transfer_request_class_instance = video;
169
170 /* Add single transfer. */
171 transfer_request -> ux_transfer_request_next_transfer_request = UX_NULL;
172
173 /* Set endpoint to pending state, for callback and abort to check. */
174 endpoint -> ux_endpoint_transfer_request.ux_transfer_request_completion_code = UX_TRANSFER_STATUS_PENDING;
175
176 /* Transfer the transfer request. */
177 status = _ux_host_stack_transfer_request(transfer_request);
178
179 /* Unprotect thread reentry to this instance. */
180 _ux_host_semaphore_put(&video -> ux_host_class_video_semaphore);
181
182 /* Return completion status. */
183 return(status);
184 }
185
186 /**************************************************************************/
187 /* */
188 /* FUNCTION RELEASE */
189 /* */
190 /* _uxe_host_class_video_transfer_buffer_add PORTABLE C */
191 /* 6.3.0 */
192 /* AUTHOR */
193 /* */
194 /* Yajun Xia, Microsoft Corporation */
195 /* */
196 /* DESCRIPTION */
197 /* */
198 /* This function checks errors in video transfer buffer add function */
199 /* call. */
200 /* */
201 /* INPUT */
202 /* */
203 /* video Pointer to video class */
204 /* buffer Pointer to data buffer */
205 /* */
206 /* OUTPUT */
207 /* */
208 /* Completion Status */
209 /* */
210 /* CALLS */
211 /* */
212 /* _ux_host_class_video_transfer_buffer_add */
213 /* video transfer buffer add */
214 /* */
215 /* CALLED BY */
216 /* */
217 /* Application */
218 /* */
219 /* RELEASE HISTORY */
220 /* */
221 /* DATE NAME DESCRIPTION */
222 /* */
223 /* 10-31-2023 Yajun xia Initial Version 6.3.0 */
224 /* */
225 /**************************************************************************/
_uxe_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO * video,UCHAR * buffer)226 UINT _uxe_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO *video, UCHAR* buffer)
227 {
228
229 /* Sanity checks. */
230 if ((video == UX_NULL) || (buffer == UX_NULL))
231 return(UX_INVALID_PARAMETER);
232
233 /* Call actual video transfer buffer add function. */
234 return(_ux_host_class_video_transfer_buffer_add(video, buffer));
235 }
236