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 /**   Device Stack                                                        */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define UX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "ux_api.h"
28 #include "ux_device_stack.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _ux_device_stack_get_status                         PORTABLE C      */
36 /*                                                           6.1.6        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function obtains the status of a USB component of the device   */
44 /*    such as device or endpoint.                                         */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    request_type                          Request type                  */
49 /*    request_index                         Request index                 */
50 /*    request_length                        Request length                */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_device_stack_transfer_request     Transfer request              */
59 /*    (ux_slave_dcd_function)               DCD dispatch function         */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    Device Stack                                                        */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
70 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
71 /*                                            resulting in version 6.1    */
72 /*  04-02-2021     Chaoqiong Xiao           Modified comment(s),          */
73 /*                                            supported bi-dir-endpoints, */
74 /*                                            resulting in version 6.1.6  */
75 /*                                                                        */
76 /**************************************************************************/
_ux_device_stack_get_status(ULONG request_type,ULONG request_index,ULONG request_length)77 UINT  _ux_device_stack_get_status(ULONG request_type, ULONG request_index, ULONG request_length)
78 {
79 
80 UX_SLAVE_DCD            *dcd;
81 UX_SLAVE_TRANSFER       *transfer_request;
82 UX_SLAVE_DEVICE         *device;
83 UX_SLAVE_ENDPOINT       *endpoint;
84 UINT                    status;
85 ULONG                   data_length;
86 
87     UX_PARAMETER_NOT_USED(request_length);
88 
89     /* If trace is enabled, insert this event into the trace buffer.  */
90     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_GET_STATUS, request_type, request_index, request_length, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0)
91 
92     /* Get the pointer to the DCD.  */
93     dcd =  &_ux_system_slave -> ux_system_slave_dcd;
94 
95     /* Get the pointer to the device.  */
96     device =  &_ux_system_slave -> ux_system_slave_device;
97 
98     /* Get the control endpoint for the device.  */
99     endpoint =  &device -> ux_slave_device_control_endpoint;
100 
101     /* Get the pointer to the transfer request associated with the endpoint.  */
102     transfer_request =  &endpoint -> ux_slave_endpoint_transfer_request;
103 
104     /* Reset the status buffer.  */
105     *transfer_request -> ux_slave_transfer_request_data_pointer =  0;
106     *(transfer_request -> ux_slave_transfer_request_data_pointer + 1) =  0;
107 
108     /* The default length for GET_STATUS is 2, except for OTG get Status.  */
109     data_length = 2;
110 
111     /* The status can be for either the device or the endpoint.  */
112     switch (request_type & UX_REQUEST_TARGET)
113     {
114 
115     case UX_REQUEST_TARGET_DEVICE:
116 
117         /* When the device is probed, it is either for the power/remote capabilities or OTG role swap.
118            We differentiate with the Windex, 0 or OTG status Selector.  */
119         if (request_index == UX_OTG_STATUS_SELECTOR)
120         {
121 
122             /* Set the data length to 1.  */
123             data_length = 1;
124 
125 #ifdef UX_OTG_SUPPORT
126             /* Store the Role Swap flag.  */
127             *transfer_request -> ux_slave_transfer_request_data_pointer =  (UCHAR) _ux_system_otg -> ux_system_otg_slave_role_swap_flag;
128 #endif
129 
130         }
131         else
132         {
133 
134             /* Store the current power state in the status buffer. */
135             if (_ux_system_slave -> ux_system_slave_power_state == UX_DEVICE_SELF_POWERED)
136                 *transfer_request -> ux_slave_transfer_request_data_pointer =  1;
137 
138             /* Store the remote wakeup capability state in the status buffer.  */
139 
140             if (_ux_system_slave -> ux_system_slave_remote_wakeup_enabled)
141                 *transfer_request -> ux_slave_transfer_request_data_pointer |=  2;
142         }
143 
144         break;
145 
146     case UX_REQUEST_TARGET_ENDPOINT:
147 
148 #ifndef UX_DEVICE_BIDIRECTIONAL_ENDPOINT_SUPPORT
149 
150         /* This feature returns the halt state of a specific endpoint.  The endpoint index
151            is used to retrieve the endpoint container.  */
152         status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_ENDPOINT_STATUS, (VOID *)(ALIGN_TYPE)(request_index & (UINT)~UX_ENDPOINT_DIRECTION));
153 #else
154 
155         /* This feature returns the halt state of a specific endpoint.  The endpoint address
156            is used to retrieve the endpoint container.  */
157         status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_ENDPOINT_STATUS, (VOID *)(ALIGN_TYPE)(request_index));
158 #endif
159 
160         /* Check the status. We may have a unknown endpoint.  */
161         if (status != UX_ERROR)
162         {
163 
164             if (status == UX_TRUE)
165                 *transfer_request -> ux_slave_transfer_request_data_pointer =  1;
166         }
167         else
168         {
169 
170             /* We stall the command. Endpoint is wrong.  */
171             dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint);
172 
173             /* No more work to do here.  The command failed but the upper layer does not depend on it.  */
174             return(UX_SUCCESS);
175         }
176         break;
177 
178     default:
179 
180         /* We stall the command.  */
181         dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint);
182 
183         /* No more work to do here.  The command failed but the upper layer does not depend on it.  */
184         return(UX_SUCCESS);
185     }
186 
187     /* Set the phase of the transfer to data out.  */
188     transfer_request -> ux_slave_transfer_request_phase =  UX_TRANSFER_PHASE_DATA_OUT;
189 
190     /* Send the descriptor with the appropriate length to the host.  */
191     status =  _ux_device_stack_transfer_request(transfer_request, data_length, data_length);
192 
193     /* Return the function status.  */
194     return(status);
195 }
196 
197