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 /**   Host Stack                                                          */
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_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_stack_device_address_set                   PORTABLE C      */
37 /*                                                           6.1.10       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function sets the device address to the new device.            */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    device                                Pointer to device             */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    Completion Status                                                   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_utility_delay_ms                  Thread sleep                  */
57 /*    _ux_host_stack_transfer_request       Process transfer request      */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    USBX Components                                                     */
62 /*                                                                        */
63 /*  RELEASE HISTORY                                                       */
64 /*                                                                        */
65 /*    DATE              NAME                      DESCRIPTION             */
66 /*                                                                        */
67 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
68 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
69 /*                                            optimized based on compile  */
70 /*                                            definitions,                */
71 /*                                            resulting in version 6.1    */
72 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
73 /*                                            added standalone support,   */
74 /*                                            resulting in version 6.1.10 */
75 /*                                                                        */
76 /**************************************************************************/
_ux_host_stack_device_address_set(UX_DEVICE * device)77 UINT  _ux_host_stack_device_address_set(UX_DEVICE *device)
78 {
79 
80 
81 UINT            status = UX_ERROR;
82 UX_TRANSFER     *transfer_request;
83 UX_ENDPOINT     *control_endpoint;
84 USHORT          device_address;
85 #if UX_MAX_DEVICES > 1
86 UX_HCD          *hcd;
87 UINT            address_byte_index;
88 UINT            address_bit_index;
89 UCHAR           device_address_byte;
90 #endif
91 
92     /* Retrieve the pointer to the control endpoint.  */
93     control_endpoint =  &device -> ux_device_control_endpoint;
94 
95     /* Retrieve the transfer request pointer.  */
96     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
97 
98     /* Initialize device address to 1.  */
99     device_address =  1;
100 
101 #if UX_MAX_DEVICES > 1
102 
103     /* We need the HCD pointer as well.  */
104     hcd = UX_DEVICE_HCD_GET(device);
105 
106     /* Calculate the new address of this device. We start with address 1.  */
107     for (address_byte_index = 0; address_byte_index < 16; address_byte_index++)
108     {
109 
110         /* Get the address mask byte.  */
111         device_address_byte =  hcd -> ux_hcd_address[address_byte_index];
112 
113         /* Scan each bit for an empty spot.  */
114         for (address_bit_index = 0; address_bit_index < 8; address_bit_index++)
115         {
116 
117             if ((device_address_byte & (1 << address_bit_index)) == 0)
118             {
119 
120                 /* We have found an empty spot. Reserve this address.  */
121                 device_address_byte = (UCHAR)((UCHAR)device_address_byte | (UCHAR)(1 << address_bit_index));
122 
123                 /* Store the address mask byte.  */
124                 hcd -> ux_hcd_address[address_byte_index] =  device_address_byte;
125 
126                 /* OK, apply address.  */
127                 status = UX_SUCCESS;
128                 break;
129             }
130 
131             /* This address was already taken, increment to the next address.  */
132             device_address++;
133         }
134 
135         /* If address found, break the loop.  */
136         if (status == UX_SUCCESS)
137         {
138             break;
139         }
140     }
141     if (status == UX_ERROR)
142 
143         /* We should never get here!  */
144         return(UX_ERROR);
145 #endif
146 
147     /* If trace is enabled, insert this event into the trace buffer.  */
148     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_ADDRESS_SET, device, device_address, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
149 
150     /* Create a transfer request for the SET_ADDRESS request.  */
151     transfer_request -> ux_transfer_request_data_pointer =      UX_NULL;
152     transfer_request -> ux_transfer_request_requested_length =  0;
153     transfer_request -> ux_transfer_request_function =          UX_SET_ADDRESS;
154     transfer_request -> ux_transfer_request_type =              UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
155     transfer_request -> ux_transfer_request_value =             device_address;
156     transfer_request -> ux_transfer_request_index =             0;
157 
158 #if defined(UX_HOST_STANDALONE)
159     device -> ux_device_enum_trans = transfer_request;
160     status = UX_SUCCESS;
161     return(status);
162 #else
163 
164     /* Send request to HCD layer.  */
165     status =  _ux_host_stack_transfer_request(transfer_request);
166 
167     /* Now, this address will be the one used in future transfers.  The transfer may have failed and therefore
168         all the device resources including the new address will be free.*/
169     device -> ux_device_address =  (ULONG) device_address;
170 
171     /* Check completion status.  */
172     if (status == UX_SUCCESS)
173     {
174 
175         /* Mark the device as ADDRESSED now.  */
176         device -> ux_device_state = UX_DEVICE_ADDRESSED;
177 
178         /* Some devices need some time to accept this address.  */
179         _ux_utility_delay_ms(UX_DEVICE_ADDRESS_SET_WAIT);
180 
181         /* Return successful status.  */
182         return(status);
183     }
184     else
185     {
186 
187         /* We have an error at the first device transaction. This is mostly
188             due to the device having failed on the reset after power up.
189             we will try again either at the root hub or regular hub. */
190         return(status);
191     }
192 #endif
193 }
194