source: mainline/uspace/lib/usbhost/src/utility.c@ 69b2dfee

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 69b2dfee was 2833bb4, checked in by Ondřej Hlavatý <aearsis@…>, 8 years ago

xhci: recognise hubs

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Copyright (c) 2013 Jan Vesely
3 * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29/** @addtogroup libusbhost
30 * @{
31 */
32/** @file
33 */
34
35#include <macros.h>
36#include <str_error.h>
37#include <usb/debug.h>
38#include <usb/descriptor.h>
39
40#include "ddf_helpers.h"
41#include "utility.h"
42
43
44/**
45 * Get max packet size for the control endpoint 0.
46 *
47 * For LS, HS, and SS devices this value is fixed. For FS devices we must fetch
48 * the first 8B of the device descriptor to determine it.
49 *
50 * @return Max packet size for EP 0
51 */
52int hc_get_ep0_max_packet_size(uint16_t *mps, bus_t *bus, device_t *dev)
53{
54 assert(mps);
55
56 static const uint16_t mps_fixed [] = {
57 [USB_SPEED_LOW] = 8,
58 [USB_SPEED_HIGH] = 64,
59 [USB_SPEED_SUPER] = 512,
60 };
61
62 if (dev->speed < ARRAY_SIZE(mps_fixed) && mps_fixed[dev->speed] != 0) {
63 *mps = mps_fixed[dev->speed];
64 return EOK;
65 }
66
67 const usb_target_t control_ep = {{
68 .address = dev->address,
69 .endpoint = 0,
70 }};
71
72 usb_standard_device_descriptor_t desc = { 0 };
73 const usb_device_request_setup_packet_t get_device_desc_8 =
74 GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
75
76 usb_log_debug("Requesting first 8B of device descriptor to determine MPS.");
77 ssize_t got = bus_device_send_batch_sync(dev, control_ep, USB_DIRECTION_IN,
78 (char *) &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
79 "read first 8 bytes of dev descriptor");
80
81 if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
82 const int err = got < 0 ? got : EOVERFLOW;
83 usb_log_error("Failed to get 8B of dev descr: %s.", str_error(err));
84 return err;
85 }
86
87 if (desc.descriptor_type != USB_DESCTYPE_DEVICE) {
88 usb_log_error("The device responded with wrong device descriptor.");
89 return EIO;
90 }
91
92 uint16_t version = uint16_usb2host(desc.usb_spec_version);
93 if (version < 0x0300) {
94 /* USB 2 and below have MPS raw in the field */
95 *mps = desc.max_packet_size;
96 } else {
97 /* USB 3 have MPS as an 2-based exponent */
98 *mps = (1 << desc.max_packet_size);
99 }
100 return EOK;
101}
102
103/** Check setup packet data for signs of toggle reset.
104 *
105 * @param[in] requst Setup requst data.
106 *
107 * @retval -1 No endpoints need reset.
108 * @retval 0 All endpoints need reset.
109 * @retval >0 Specified endpoint needs reset.
110 *
111 */
112toggle_reset_mode_t hc_get_request_toggle_reset_mode(const usb_device_request_setup_packet_t *request)
113{
114 assert(request);
115 switch (request->request)
116 {
117 /* Clear Feature ENPOINT_STALL */
118 case USB_DEVREQ_CLEAR_FEATURE: /*resets only cleared ep */
119 /* 0x2 ( HOST to device | STANDART | TO ENPOINT) */
120 if ((request->request_type == 0x2) &&
121 (request->value == USB_FEATURE_ENDPOINT_HALT))
122 return RESET_EP;
123 break;
124 case USB_DEVREQ_SET_CONFIGURATION:
125 case USB_DEVREQ_SET_INTERFACE:
126 /* Recipient must be device, this resets all endpoints,
127 * In fact there should be no endpoints but EP 0 registered
128 * as different interfaces use different endpoints,
129 * unless you're changing configuration or alternative
130 * interface of an already setup device. */
131 if (!(request->request_type & SETUP_REQUEST_TYPE_DEVICE_TO_HOST))
132 return RESET_ALL;
133 break;
134 default:
135 break;
136 }
137
138 return RESET_NONE;
139}
140
141int hc_get_device_desc(device_t *device, usb_standard_device_descriptor_t *desc)
142{
143 const usb_target_t control_ep = {{
144 .address = device->address,
145 .endpoint = 0,
146 }};
147
148 /* Get std device descriptor */
149 const usb_device_request_setup_packet_t get_device_desc =
150 GET_DEVICE_DESC(sizeof(*desc));
151
152 usb_log_debug("Device(%d): Requesting full device descriptor.",
153 device->address);
154 ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
155 (char *) desc, sizeof(*desc), *(uint64_t *)&get_device_desc,
156 "read device descriptor");
157
158 if (got < 0)
159 return got;
160
161 return got == sizeof(*desc) ? EOK : EOVERFLOW;
162}
163
164int hc_get_hub_desc(device_t *device, usb_hub_descriptor_header_t *desc)
165{
166 const usb_target_t control_ep = {{
167 .address = device->address,
168 .endpoint = 0,
169 }};
170
171 const usb_device_request_setup_packet_t get_hub_desc = {
172 .request_type = SETUP_REQUEST_TYPE_DEVICE_TO_HOST
173 | (USB_REQUEST_TYPE_CLASS << 5)
174 | USB_REQUEST_RECIPIENT_DEVICE,
175 .request = USB_DEVREQ_GET_DESCRIPTOR, \
176 .value = uint16_host2usb(USB_DESCTYPE_HUB << 8), \
177 .length = sizeof(*desc),
178 };
179
180 usb_log_debug("Device(%d): Requesting hub descriptor.",
181 device->address);
182 ssize_t got = bus_device_send_batch_sync(device, control_ep, USB_DIRECTION_IN,
183 (char *) desc, sizeof(*desc), *(uint64_t *)&get_hub_desc,
184 "get hub descriptor");
185
186 if (got < 0)
187 return got;
188
189 return got == sizeof(*desc) ? EOK : EOVERFLOW;
190}
191
192int hc_device_explore(device_t *device)
193{
194 int err;
195 usb_standard_device_descriptor_t desc = { 0 };
196
197 if ((err = hc_get_device_desc(device, &desc))) {
198 usb_log_error("Device(%d): Failed to get dev descriptor: %s",
199 device->address, str_error(err));
200 return err;
201 }
202
203 if ((err = hcd_ddf_setup_match_ids(device, &desc))) {
204 usb_log_error("Device(%d): Failed to setup match ids: %s", device->address, str_error(err));
205 return err;
206 }
207
208 return EOK;
209}
210
211/** Announce root hub to the DDF
212 *
213 * @param[in] device Host controller ddf device
214 * @return Error code
215 */
216int hc_setup_virtual_root_hub(hc_device_t *hcd)
217{
218 int err;
219
220 assert(hcd);
221
222 device_t *dev = hcd_ddf_fun_create(hcd, USB_SPEED_MAX);
223 if (!dev) {
224 usb_log_error("Failed to create function for the root hub.");
225 return ENOMEM;
226 }
227
228 ddf_fun_set_name(dev->fun, "roothub");
229
230 /* Assign an address to the device */
231 if ((err = bus_device_enumerate(dev))) {
232 usb_log_error("Failed to enumerate roothub device: %s", str_error(err));
233 goto err_usb_dev;
234 }
235
236 if ((err = ddf_fun_bind(dev->fun))) {
237 usb_log_error("Failed to register roothub: %s.", str_error(err));
238 goto err_enumerated;
239 }
240
241 return EOK;
242
243err_enumerated:
244 bus_device_gone(dev);
245err_usb_dev:
246 hcd_ddf_fun_destroy(dev);
247 return err;
248}
249
250/**
251 * @}
252 */
Note: See TracBrowser for help on using the repository browser.