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 /** USBX Component */
15 /** */
16 /** Device Video Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_video.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_video_change PORTABLE C */
36 /* 6.2.0 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function changes the interface of the Video device */
44 /* */
45 /* INPUT */
46 /* */
47 /* command Pointer to video command */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* Completion Status */
52 /* */
53 /* CALLS */
54 /* */
55 /* _ux_system_error_handler System error trap */
56 /* */
57 /* CALLED BY */
58 /* */
59 /* Device Video Class */
60 /* */
61 /* RELEASE HISTORY */
62 /* */
63 /* DATE NAME DESCRIPTION */
64 /* */
65 /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */
66 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
67 /* fixed parameter/variable */
68 /* names conflict C++ keyword, */
69 /* resulting in version 6.1.12 */
70 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
71 /* added standalone support, */
72 /* resulting in version 6.2.0 */
73 /* */
74 /**************************************************************************/
_ux_device_class_video_change(UX_SLAVE_CLASS_COMMAND * command)75 UINT _ux_device_class_video_change(UX_SLAVE_CLASS_COMMAND *command)
76 {
77
78 UX_DEVICE_CLASS_VIDEO *video;
79 UX_DEVICE_CLASS_VIDEO_STREAM *stream;
80 UX_SLAVE_CLASS *class_ptr;
81 UX_SLAVE_INTERFACE *interface_ptr;
82 UX_SLAVE_ENDPOINT *endpoint;
83 UCHAR *payload_buffer;
84 ULONG stream_index;
85
86
87 /* Get the class container. */
88 class_ptr = command -> ux_slave_class_command_class_ptr;
89
90 /* Get the class instance in the container. */
91 video = (UX_DEVICE_CLASS_VIDEO *) class_ptr -> ux_slave_class_instance;
92
93 /* Get the interface that owns this instance. */
94 interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
95
96 /* Get the interface number (base 0). */
97 if (video -> ux_device_class_video_interface)
98 {
99
100 /* If IAD used, calculate stream index based on interface number. */
101 stream_index = interface_ptr -> ux_slave_interface_descriptor.bInterfaceNumber;
102 stream_index -= video -> ux_device_class_video_interface -> ux_slave_interface_descriptor.bInterfaceNumber;
103 stream_index --;
104 }
105 else
106
107 /* One stream for one driver! */
108 stream_index = 0;
109
110 /* Get the stream instance. */
111 stream = &video -> ux_device_class_video_streams[stream_index];
112
113 /* Update the interface. */
114 stream -> ux_device_class_video_stream_interface = interface_ptr;
115
116 /* If the interface to mount has a non zero alternate setting, the class is really active with
117 the endpoints active. If the interface reverts to alternate setting 0, it needs to have
118 the pending transactions terminated. */
119 if (interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting != 0)
120 {
121
122 /* Locate the endpoints. ISO IN/OUT for Streaming Interface. */
123 endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
124
125 /* Parse all endpoints. */
126 stream -> ux_device_class_video_stream_endpoint = UX_NULL;
127 while (endpoint != UX_NULL)
128 {
129
130 /* Check the endpoint. */
131 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_ISOCHRONOUS_ENDPOINT)
132 {
133
134 /* We found the endpoint, check its size. */
135 if (endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_transfer_length >
136 (stream -> ux_device_class_video_stream_payload_buffer_size - 4))
137 {
138
139 /* Error trap! */
140 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
141
142 /* payload buffer too small for endpoints. */
143 return(UX_MEMORY_INSUFFICIENT);
144 }
145
146 /* Save it. */
147 stream -> ux_device_class_video_stream_endpoint = endpoint;
148 break;
149 }
150
151 /* Next endpoint. */
152 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
153 }
154
155 /* Now check if all endpoints have been found. */
156 if (stream -> ux_device_class_video_stream_endpoint == UX_NULL)
157 {
158
159 /* Error trap! */
160 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
161
162 /* Not all endpoints have been found. Major error, do not proceed. */
163 return(UX_DESCRIPTOR_CORRUPTED);
164 }
165
166 #if defined(UX_DEVICE_STANDALONE)
167
168 /* Reset background transfer state. */
169 stream -> ux_device_class_video_stream_task_state = UX_STATE_RESET;
170 #endif
171
172 /* Now reset payload buffer error count. */
173 stream -> ux_device_class_video_stream_buffer_error_count = 0;
174
175 /* Now reset payload buffers. */
176 payload_buffer = stream -> ux_device_class_video_stream_buffer;
177 while(payload_buffer < stream -> ux_device_class_video_stream_buffer + stream -> ux_device_class_video_stream_buffer_size)
178 {
179
180 /* Reset header information. */
181 *((ULONG *) payload_buffer ) = 0;
182
183 /* Next. */
184 payload_buffer += stream -> ux_device_class_video_stream_payload_buffer_size;
185 }
186 stream -> ux_device_class_video_stream_transfer_pos = stream -> ux_device_class_video_stream_access_pos;
187 }
188 else
189 {
190
191 /* There is no data endpoint. */
192 stream -> ux_device_class_video_stream_endpoint = UX_NULL;
193
194 /* In this case, we are reverting to the Alternate Setting 0. We need to terminate the pending transactions. */
195 /* Endpoints actually aborted and destroyed before change command. */
196 /*
197 _ux_device_stack_transfer_all_request_abort(stream -> ux_device_class_video_stream_endpoint, UX_TRANSFER_APPLICATION_RESET);
198 */
199 }
200
201 /* Invoke stream change callback. */
202 if (stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_change)
203 stream -> ux_device_class_video_stream_callbacks.ux_device_class_video_stream_change(stream, interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting);
204
205 /* Return completion status. */
206 return(UX_SUCCESS);
207 }
208