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