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