usbroothub.c revision 1.14 1 1.14 riastrad /* $NetBSD: usbroothub.c,v 1.14 2022/03/09 22:17:41 riastradh Exp $ */
2 1.2 skrll
3 1.2 skrll /*-
4 1.2 skrll * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc.
5 1.2 skrll * All rights reserved.
6 1.2 skrll *
7 1.2 skrll * This code is derived from software contributed to The NetBSD Foundation
8 1.2 skrll * by Lennart Augustsson (lennart (at) augustsson.net) at
9 1.2 skrll * Carlstedt Research & Technology, Jared D. McNeill (jmcneill (at) invisible.ca),
10 1.2 skrll * Matthew R. Green (mrg (at) eterna.com.au) and Nick Hudson.
11 1.2 skrll *
12 1.2 skrll * Redistribution and use in source and binary forms, with or without
13 1.2 skrll * modification, are permitted provided that the following conditions
14 1.2 skrll * are met:
15 1.2 skrll * 1. Redistributions of source code must retain the above copyright
16 1.2 skrll * notice, this list of conditions and the following disclaimer.
17 1.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
18 1.2 skrll * notice, this list of conditions and the following disclaimer in the
19 1.2 skrll * documentation and/or other materials provided with the distribution.
20 1.2 skrll *
21 1.2 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 1.2 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 1.2 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 1.2 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 1.2 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 1.2 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 1.2 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 1.2 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 1.2 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 1.2 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 1.2 skrll * POSSIBILITY OF SUCH DAMAGE.
32 1.2 skrll */
33 1.2 skrll
34 1.2 skrll /*
35 1.2 skrll * Copyright (c) 2008
36 1.2 skrll * Matthias Drochner. All rights reserved.
37 1.2 skrll *
38 1.2 skrll * Redistribution and use in source and binary forms, with or without
39 1.2 skrll * modification, are permitted provided that the following conditions
40 1.2 skrll * are met:
41 1.2 skrll * 1. Redistributions of source code must retain the above copyright
42 1.2 skrll * notice, this list of conditions and the following disclaimer.
43 1.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
44 1.2 skrll * notice, this list of conditions and the following disclaimer in the
45 1.2 skrll * documentation and/or other materials provided with the distribution.
46 1.2 skrll *
47 1.2 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
48 1.2 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 1.2 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
50 1.2 skrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
51 1.2 skrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52 1.2 skrll * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
53 1.2 skrll * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
54 1.2 skrll * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55 1.2 skrll * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
56 1.2 skrll * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57 1.2 skrll *
58 1.2 skrll */
59 1.2 skrll
60 1.6 rin #include <sys/cdefs.h>
61 1.14 riastrad __KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.14 2022/03/09 22:17:41 riastradh Exp $");
62 1.10 skrll
63 1.10 skrll #include <sys/param.h>
64 1.10 skrll #include <sys/systm.h> /* for ostype */
65 1.6 rin
66 1.2 skrll #include <dev/usb/usb.h>
67 1.2 skrll #include <dev/usb/usbdi.h>
68 1.2 skrll #include <dev/usb/usbdivar.h>
69 1.2 skrll #include <dev/usb/usbroothub.h>
70 1.2 skrll #include <dev/usb/usbhist.h>
71 1.2 skrll
72 1.2 skrll /* helper functions for USB root hub emulation */
73 1.2 skrll
74 1.2 skrll static usbd_status roothub_ctrl_transfer(struct usbd_xfer *);
75 1.2 skrll static usbd_status roothub_ctrl_start(struct usbd_xfer *);
76 1.2 skrll static void roothub_ctrl_abort(struct usbd_xfer *);
77 1.2 skrll static void roothub_ctrl_close(struct usbd_pipe *);
78 1.2 skrll static void roothub_ctrl_done(struct usbd_xfer *);
79 1.2 skrll static void roothub_noop(struct usbd_pipe *pipe);
80 1.2 skrll
81 1.2 skrll const struct usbd_pipe_methods roothub_ctrl_methods = {
82 1.2 skrll .upm_transfer = roothub_ctrl_transfer,
83 1.2 skrll .upm_start = roothub_ctrl_start,
84 1.2 skrll .upm_abort = roothub_ctrl_abort,
85 1.2 skrll .upm_close = roothub_ctrl_close,
86 1.2 skrll .upm_cleartoggle = roothub_noop,
87 1.2 skrll .upm_done = roothub_ctrl_done,
88 1.2 skrll };
89 1.2 skrll
90 1.2 skrll int
91 1.2 skrll usb_makestrdesc(usb_string_descriptor_t *p, int l, const char *s)
92 1.2 skrll {
93 1.2 skrll int i;
94 1.2 skrll
95 1.2 skrll if (l == 0)
96 1.2 skrll return 0;
97 1.2 skrll p->bLength = 2 * strlen(s) + 2;
98 1.2 skrll if (l == 1)
99 1.2 skrll return 1;
100 1.2 skrll p->bDescriptorType = UDESC_STRING;
101 1.2 skrll l -= 2;
102 1.2 skrll /* poor man's utf-16le conversion */
103 1.2 skrll for (i = 0; s[i] && l > 1; i++, l -= 2)
104 1.2 skrll USETW2(p->bString[i], 0, s[i]);
105 1.2 skrll return 2 * i + 2;
106 1.2 skrll }
107 1.2 skrll
108 1.2 skrll int
109 1.2 skrll usb_makelangtbl(usb_string_descriptor_t *p, int l)
110 1.2 skrll {
111 1.2 skrll
112 1.2 skrll if (l == 0)
113 1.2 skrll return 0;
114 1.2 skrll p->bLength = 4;
115 1.2 skrll if (l == 1)
116 1.2 skrll return 1;
117 1.2 skrll p->bDescriptorType = UDESC_STRING;
118 1.2 skrll if (l < 4)
119 1.2 skrll return 2;
120 1.2 skrll USETW(p->bString[0], 0x0409); /* english/US */
121 1.2 skrll return 4;
122 1.2 skrll }
123 1.2 skrll
124 1.2 skrll /*
125 1.2 skrll * Data structures and routines to emulate the root hub.
126 1.2 skrll */
127 1.2 skrll static const usb_device_descriptor_t usbroothub_devd1 = {
128 1.2 skrll .bLength = sizeof(usb_device_descriptor_t),
129 1.2 skrll .bDescriptorType = UDESC_DEVICE,
130 1.2 skrll .bcdUSB = {0x00, 0x01},
131 1.2 skrll .bDeviceClass = UDCLASS_HUB,
132 1.2 skrll .bDeviceSubClass = UDSUBCLASS_HUB,
133 1.2 skrll .bDeviceProtocol = UDPROTO_FSHUB,
134 1.2 skrll .bMaxPacketSize = 64,
135 1.2 skrll .idVendor = {0},
136 1.2 skrll .idProduct = {0},
137 1.2 skrll .bcdDevice = {0x00, 0x01},
138 1.2 skrll .iManufacturer = 1,
139 1.2 skrll .iProduct = 2,
140 1.2 skrll .iSerialNumber = 0,
141 1.2 skrll .bNumConfigurations = 1
142 1.2 skrll };
143 1.2 skrll
144 1.2 skrll static const struct usb_roothub_descriptors usbroothub_confd1 = {
145 1.2 skrll .urh_confd = {
146 1.2 skrll .bLength = USB_CONFIG_DESCRIPTOR_SIZE,
147 1.2 skrll .bDescriptorType = UDESC_CONFIG,
148 1.2 skrll .wTotalLength = USETWD(sizeof(usbroothub_confd1)),
149 1.2 skrll .bNumInterface = 1,
150 1.2 skrll .bConfigurationValue = 1,
151 1.2 skrll .iConfiguration = 0,
152 1.2 skrll .bmAttributes = UC_ATTR_MBO | UC_SELF_POWERED,
153 1.2 skrll .bMaxPower = 0,
154 1.2 skrll },
155 1.2 skrll .urh_ifcd = {
156 1.2 skrll .bLength = USB_INTERFACE_DESCRIPTOR_SIZE,
157 1.2 skrll .bDescriptorType = UDESC_INTERFACE,
158 1.2 skrll .bInterfaceNumber = 0,
159 1.2 skrll .bAlternateSetting = 0,
160 1.2 skrll .bNumEndpoints = 1,
161 1.2 skrll .bInterfaceClass = UICLASS_HUB,
162 1.2 skrll .bInterfaceSubClass = UISUBCLASS_HUB,
163 1.2 skrll .bInterfaceProtocol = UIPROTO_FSHUB,
164 1.2 skrll .iInterface = 0
165 1.2 skrll },
166 1.2 skrll .urh_endpd = {
167 1.2 skrll .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE,
168 1.2 skrll .bDescriptorType = UDESC_ENDPOINT,
169 1.2 skrll .bEndpointAddress = UE_DIR_IN | USBROOTHUB_INTR_ENDPT,
170 1.2 skrll .bmAttributes = UE_INTERRUPT,
171 1.2 skrll .wMaxPacketSize = USETWD(8), /* max packet */
172 1.2 skrll .bInterval = 255,
173 1.2 skrll },
174 1.2 skrll };
175 1.2 skrll
176 1.4 skrll /* USB 3.0 10.15.1 */
177 1.4 skrll static const usb_device_descriptor_t usbroothub_devd3 = {
178 1.4 skrll .bLength = sizeof(usb_device_descriptor_t),
179 1.4 skrll .bDescriptorType = UDESC_DEVICE,
180 1.4 skrll .bcdUSB = {0x00, 0x03},
181 1.4 skrll .bDeviceClass = UDCLASS_HUB,
182 1.4 skrll .bDeviceSubClass = UDSUBCLASS_HUB,
183 1.4 skrll .bDeviceProtocol = UDPROTO_SSHUB,
184 1.4 skrll .bMaxPacketSize = 9,
185 1.4 skrll .idVendor = {0},
186 1.4 skrll .idProduct = {0},
187 1.4 skrll .bcdDevice = {0x00, 0x01},
188 1.4 skrll .iManufacturer = 1,
189 1.4 skrll .iProduct = 2,
190 1.4 skrll .iSerialNumber = 0,
191 1.4 skrll .bNumConfigurations = 1
192 1.4 skrll };
193 1.4 skrll
194 1.2 skrll static const usb_device_descriptor_t usbroothub_devd2 = {
195 1.2 skrll .bLength = sizeof(usb_device_descriptor_t),
196 1.2 skrll .bDescriptorType = UDESC_DEVICE,
197 1.2 skrll .bcdUSB = {0x00, 0x02},
198 1.2 skrll .bDeviceClass = UDCLASS_HUB,
199 1.2 skrll .bDeviceSubClass = UDSUBCLASS_HUB,
200 1.2 skrll .bDeviceProtocol = UDPROTO_HSHUBSTT,
201 1.2 skrll .bMaxPacketSize = 64,
202 1.2 skrll .idVendor = {0},
203 1.2 skrll .idProduct = {0},
204 1.2 skrll .bcdDevice = {0x00, 0x01},
205 1.2 skrll .iManufacturer = 1,
206 1.2 skrll .iProduct = 2,
207 1.2 skrll .iSerialNumber = 0,
208 1.2 skrll .bNumConfigurations = 1
209 1.2 skrll };
210 1.2 skrll
211 1.2 skrll static const usb_device_qualifier_t usbroothub_odevd2 = {
212 1.2 skrll .bLength = USB_DEVICE_QUALIFIER_SIZE,
213 1.2 skrll .bDescriptorType = UDESC_DEVICE_QUALIFIER,
214 1.2 skrll .bcdUSB = {0x00, 0x02},
215 1.2 skrll .bDeviceClass = UDCLASS_HUB,
216 1.2 skrll .bDeviceSubClass = UDSUBCLASS_HUB,
217 1.2 skrll .bDeviceProtocol = UDPROTO_FSHUB,
218 1.2 skrll .bMaxPacketSize0 = 64,
219 1.2 skrll .bNumConfigurations = 1,
220 1.2 skrll };
221 1.2 skrll
222 1.2 skrll static const struct usb_roothub_descriptors usbroothub_confd2 = {
223 1.2 skrll .urh_confd = {
224 1.2 skrll .bLength = USB_CONFIG_DESCRIPTOR_SIZE,
225 1.2 skrll .bDescriptorType = UDESC_CONFIG,
226 1.2 skrll .wTotalLength = USETWD(sizeof(usbroothub_confd2)),
227 1.2 skrll .bNumInterface = 1,
228 1.2 skrll .bConfigurationValue = 1,
229 1.2 skrll .iConfiguration = 0,
230 1.2 skrll .bmAttributes = UC_ATTR_MBO | UC_SELF_POWERED,
231 1.2 skrll .bMaxPower = 0,
232 1.2 skrll },
233 1.2 skrll .urh_ifcd = {
234 1.2 skrll .bLength = USB_INTERFACE_DESCRIPTOR_SIZE,
235 1.2 skrll .bDescriptorType = UDESC_INTERFACE,
236 1.2 skrll .bInterfaceNumber = 0,
237 1.2 skrll .bAlternateSetting = 0,
238 1.2 skrll .bNumEndpoints = 1,
239 1.2 skrll .bInterfaceClass = UICLASS_HUB,
240 1.2 skrll .bInterfaceSubClass = UISUBCLASS_HUB,
241 1.2 skrll .bInterfaceProtocol = UIPROTO_HSHUBSTT,
242 1.2 skrll .iInterface = 0
243 1.2 skrll },
244 1.2 skrll .urh_endpd = {
245 1.2 skrll .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE,
246 1.2 skrll .bDescriptorType = UDESC_ENDPOINT,
247 1.2 skrll .bEndpointAddress = UE_DIR_IN | USBROOTHUB_INTR_ENDPT,
248 1.2 skrll .bmAttributes = UE_INTERRUPT,
249 1.2 skrll .wMaxPacketSize = USETWD(8), /* max packet */
250 1.2 skrll .bInterval = 12,
251 1.2 skrll },
252 1.2 skrll };
253 1.2 skrll
254 1.4 skrll static const struct usb3_roothub_descriptors usbroothub_confd3 = {
255 1.4 skrll .urh_confd = {
256 1.4 skrll .bLength = USB_CONFIG_DESCRIPTOR_SIZE,
257 1.4 skrll .bDescriptorType = UDESC_CONFIG,
258 1.4 skrll .wTotalLength = USETWD(sizeof(usbroothub_confd3)),
259 1.4 skrll .bNumInterface = 1,
260 1.4 skrll .bConfigurationValue = 1,
261 1.4 skrll .iConfiguration = 0,
262 1.4 skrll .bmAttributes = UC_SELF_POWERED, /* 10.13.1 */
263 1.4 skrll .bMaxPower = 0,
264 1.4 skrll },
265 1.4 skrll .urh_ifcd = {
266 1.4 skrll .bLength = USB_INTERFACE_DESCRIPTOR_SIZE,
267 1.4 skrll .bDescriptorType = UDESC_INTERFACE,
268 1.4 skrll .bInterfaceNumber = 0,
269 1.4 skrll .bAlternateSetting = 0,
270 1.4 skrll .bNumEndpoints = 1,
271 1.4 skrll .bInterfaceClass = UICLASS_HUB,
272 1.4 skrll .bInterfaceSubClass = UISUBCLASS_HUB,
273 1.4 skrll .bInterfaceProtocol = 0, /* UIPROTO_SSHUB ??? */
274 1.4 skrll .iInterface = 0
275 1.4 skrll },
276 1.4 skrll .urh_endpd = {
277 1.4 skrll .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE,
278 1.4 skrll .bDescriptorType = UDESC_ENDPOINT,
279 1.4 skrll .bEndpointAddress = UE_DIR_IN | USBROOTHUB_INTR_ENDPT,
280 1.4 skrll .bmAttributes = UE_INTERRUPT,
281 1.4 skrll .wMaxPacketSize = USETWD(2), /* max packet */
282 1.4 skrll .bInterval = 8,
283 1.4 skrll },
284 1.4 skrll .urh_endpssd = {
285 1.4 skrll .bLength = USB_ENDPOINT_SS_COMP_DESCRIPTOR_SIZE,
286 1.4 skrll .bDescriptorType = UDESC_ENDPOINT_SS_COMP,
287 1.4 skrll .bMaxBurst = 0,
288 1.4 skrll .bmAttributes = 0,
289 1.4 skrll .wBytesPerInterval = USETWD(2)
290 1.4 skrll },
291 1.4 skrll };
292 1.4 skrll
293 1.4 skrll static const struct usb3_roothub_bos_descriptors usbroothub_bosd3 = {
294 1.4 skrll .urh_bosd = {
295 1.4 skrll .bLength = USB_BOS_DESCRIPTOR_SIZE,
296 1.4 skrll .bDescriptorType = UDESC_BOS,
297 1.4 skrll .wTotalLength = USETWD(sizeof(usbroothub_bosd3)),
298 1.4 skrll .bNumDeviceCaps = 3,
299 1.4 skrll },
300 1.4 skrll /* 9.6.2.1 USB 2.0 Extension */
301 1.4 skrll .urh_usb2extd = {
302 1.4 skrll .bLength = USB_DEVCAP_USB2EXT_DESCRIPTOR_SIZE,
303 1.4 skrll .bDescriptorType = 1,
304 1.4 skrll .bDevCapabilityType = 2,
305 1.4 skrll .bmAttributes[0] = 2,
306 1.4 skrll },
307 1.4 skrll /* 9.6.2.2 Superspeed device capability */
308 1.4 skrll .urh_ssd = {
309 1.4 skrll .bLength = USB_DEVCAP_SS_DESCRIPTOR_SIZE,
310 1.4 skrll .bDescriptorType = UDESC_DEVICE_CAPABILITY,
311 1.4 skrll .bDevCapabilityType = USB_DEVCAP_SUPER_SPEED,
312 1.4 skrll .bmAttributes = 0, /* USB_DEVCAP_SS_LTM */
313 1.4 skrll .wSpeedsSupported = USETWD(
314 1.4 skrll USB_DEVCAP_SS_SPEED_LS | USB_DEVCAP_SS_SPEED_FS |
315 1.4 skrll USB_DEVCAP_SS_SPEED_HS | USB_DEVCAP_SS_SPEED_SS),
316 1.4 skrll .bFunctionalitySupport = 8, /* SS is 3, i.e. 1 << 3? */
317 1.4 skrll .bU1DevExitLat = 255, /* Dummy... 0? */
318 1.4 skrll .wU2DevExitLat = USETWD(8), /* Also dummy... 0? */
319 1.4 skrll },
320 1.4 skrll /* 9.6.2.3 Container ID - see RFC 4122 */
321 1.4 skrll .urh_containerd = {
322 1.4 skrll .bLength = USB_DEVCAP_CONTAINER_ID_DESCRIPTOR_SIZE,
323 1.4 skrll .bDescriptorType = 1,
324 1.4 skrll .bDevCapabilityType = 4,
325 1.4 skrll .bReserved = 0,
326 1.4 skrll // ContainerID will be zero
327 1.4 skrll },
328 1.4 skrll };
329 1.4 skrll
330 1.2 skrll static const usb_hub_descriptor_t usbroothub_hubd = {
331 1.2 skrll .bDescLength = USB_HUB_DESCRIPTOR_SIZE,
332 1.2 skrll .bDescriptorType = UDESC_HUB,
333 1.2 skrll .bNbrPorts = 1,
334 1.2 skrll .wHubCharacteristics = USETWD(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL),
335 1.2 skrll .bPwrOn2PwrGood = 50,
336 1.2 skrll .bHubContrCurrent = 0,
337 1.2 skrll .DeviceRemovable = {0}, /* port is removable */
338 1.2 skrll };
339 1.2 skrll
340 1.2 skrll /*
341 1.2 skrll * Simulate a hardware hub by handling all the necessary requests.
342 1.2 skrll */
343 1.2 skrll usbd_status
344 1.2 skrll roothub_ctrl_transfer(struct usbd_xfer *xfer)
345 1.2 skrll {
346 1.2 skrll
347 1.2 skrll /* Pipe isn't running, start first */
348 1.2 skrll return roothub_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
349 1.2 skrll }
350 1.2 skrll
351 1.2 skrll static usbd_status
352 1.2 skrll roothub_ctrl_start(struct usbd_xfer *xfer)
353 1.2 skrll {
354 1.2 skrll struct usbd_pipe *pipe = xfer->ux_pipe;
355 1.2 skrll struct usbd_bus *bus = pipe->up_dev->ud_bus;
356 1.2 skrll usb_device_request_t *req;
357 1.2 skrll usbd_status err = USBD_IOERROR; /* XXX STALL? */
358 1.2 skrll uint16_t len, value;
359 1.9 mrg int buflen, actlen = -1;
360 1.2 skrll void *buf;
361 1.2 skrll
362 1.9 mrg USBHIST_FUNC();
363 1.2 skrll
364 1.13 riastrad /*
365 1.13 riastrad * XXX Should really assert pipe lock, in case ever have
366 1.13 riastrad * per-pipe locking instead of using the bus lock for all
367 1.13 riastrad * pipes.
368 1.13 riastrad */
369 1.13 riastrad KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
370 1.13 riastrad
371 1.2 skrll KASSERT(xfer->ux_rqflags & URQ_REQUEST);
372 1.2 skrll req = &xfer->ux_request;
373 1.2 skrll
374 1.2 skrll len = UGETW(req->wLength);
375 1.2 skrll value = UGETW(req->wValue);
376 1.2 skrll
377 1.9 mrg USBHIST_CALLARGS(usbdebug, "type=%#jx request=%#jx len=%#jx value=%#jx",
378 1.9 mrg req->bmRequestType, req->bRequest, len, value);
379 1.9 mrg
380 1.2 skrll buf = len ? usbd_get_buffer(xfer) : NULL;
381 1.2 skrll buflen = 0;
382 1.2 skrll
383 1.2 skrll #define C(x,y) ((x) | ((y) << 8))
384 1.2 skrll switch (C(req->bRequest, req->bmRequestType)) {
385 1.2 skrll case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
386 1.2 skrll case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
387 1.2 skrll case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
388 1.2 skrll /*
389 1.2 skrll * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
390 1.2 skrll * for the integrated root hub.
391 1.2 skrll */
392 1.2 skrll break;
393 1.2 skrll case C(UR_GET_CONFIG, UT_READ_DEVICE):
394 1.2 skrll if (len > 0) {
395 1.2 skrll uint8_t *out = buf;
396 1.2 skrll
397 1.2 skrll *out = bus->ub_rhconf;
398 1.2 skrll buflen = sizeof(*out);
399 1.2 skrll }
400 1.2 skrll break;
401 1.2 skrll case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
402 1.3 pgoyette USBHIST_LOG(usbdebug, "wValue=%#4jx", value, 0, 0, 0);
403 1.2 skrll
404 1.2 skrll if (len == 0)
405 1.2 skrll break;
406 1.2 skrll switch (value) {
407 1.2 skrll case C(0, UDESC_DEVICE):
408 1.4 skrll if (bus->ub_revision >= USBREV_3_0) {
409 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_devd3));
410 1.4 skrll memcpy(buf, &usbroothub_devd3, buflen);
411 1.4 skrll } else if (bus->ub_revision == USBREV_2_0) {
412 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_devd2));
413 1.2 skrll memcpy(buf, &usbroothub_devd2, buflen);
414 1.2 skrll } else {
415 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_devd1));
416 1.2 skrll memcpy(buf, &usbroothub_devd1, buflen);
417 1.2 skrll }
418 1.2 skrll break;
419 1.2 skrll case C(0, UDESC_CONFIG):
420 1.4 skrll if (bus->ub_revision >= USBREV_3_0) {
421 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd3));
422 1.4 skrll memcpy(buf, &usbroothub_confd3, buflen);
423 1.4 skrll } else if (bus->ub_revision == USBREV_2_0) {
424 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd2));
425 1.2 skrll memcpy(buf, &usbroothub_confd2, buflen);
426 1.2 skrll } else {
427 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd1));
428 1.2 skrll memcpy(buf, &usbroothub_confd1, buflen);
429 1.2 skrll }
430 1.2 skrll break;
431 1.2 skrll case C(0, UDESC_DEVICE_QUALIFIER):
432 1.2 skrll if (bus->ub_revision == USBREV_2_0) {
433 1.2 skrll /*
434 1.2 skrll * We can't really operate at another speed,
435 1.2 skrll * but the spec says we need this descriptor.
436 1.2 skrll */
437 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_odevd2));
438 1.2 skrll memcpy(buf, &usbroothub_odevd2, buflen);
439 1.2 skrll } else
440 1.2 skrll goto fail;
441 1.2 skrll break;
442 1.2 skrll case C(0, UDESC_OTHER_SPEED_CONFIGURATION):
443 1.2 skrll if (bus->ub_revision == USBREV_2_0) {
444 1.2 skrll struct usb_roothub_descriptors confd;
445 1.2 skrll
446 1.2 skrll /*
447 1.2 skrll * We can't really operate at another speed,
448 1.2 skrll * but the spec says we need this descriptor.
449 1.2 skrll */
450 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd2));
451 1.2 skrll memcpy(&confd, &usbroothub_confd2, buflen);
452 1.2 skrll confd.urh_confd.bDescriptorType =
453 1.2 skrll UDESC_OTHER_SPEED_CONFIGURATION;
454 1.2 skrll memcpy(buf, &confd, buflen);
455 1.2 skrll } else
456 1.2 skrll goto fail;
457 1.2 skrll break;
458 1.4 skrll case C(0, UDESC_BOS):
459 1.4 skrll if (bus->ub_revision >= USBREV_3_0) {
460 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_bosd3));
461 1.4 skrll memcpy(buf, &usbroothub_bosd3, buflen);
462 1.4 skrll } else
463 1.4 skrll goto fail;
464 1.4 skrll break;
465 1.2 skrll #define sd ((usb_string_descriptor_t *)buf)
466 1.2 skrll case C(0, UDESC_STRING):
467 1.2 skrll /* Language table */
468 1.2 skrll buflen = usb_makelangtbl(sd, len);
469 1.2 skrll break;
470 1.2 skrll case C(1, UDESC_STRING):
471 1.2 skrll /* Vendor */
472 1.5 jakllsch buflen = usb_makestrdesc(sd, len, ostype);
473 1.2 skrll break;
474 1.2 skrll case C(2, UDESC_STRING):
475 1.2 skrll /* Product */
476 1.2 skrll buflen = usb_makestrdesc(sd, len, "Root hub");
477 1.2 skrll break;
478 1.2 skrll #undef sd
479 1.2 skrll default:
480 1.2 skrll /* Default to error */
481 1.2 skrll buflen = -1;
482 1.2 skrll }
483 1.2 skrll break;
484 1.2 skrll case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
485 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_hubd));
486 1.2 skrll memcpy(buf, &usbroothub_hubd, buflen);
487 1.2 skrll break;
488 1.2 skrll case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
489 1.2 skrll /* Get Interface, 9.4.4 */
490 1.2 skrll if (len > 0) {
491 1.2 skrll uint8_t *out = buf;
492 1.2 skrll
493 1.2 skrll *out = 0;
494 1.2 skrll buflen = sizeof(*out);
495 1.2 skrll }
496 1.2 skrll break;
497 1.2 skrll case C(UR_GET_STATUS, UT_READ_DEVICE):
498 1.2 skrll /* Get Status from device, 9.4.5 */
499 1.2 skrll if (len > 1) {
500 1.2 skrll usb_status_t *out = buf;
501 1.2 skrll
502 1.2 skrll USETW(out->wStatus, UDS_SELF_POWERED);
503 1.2 skrll buflen = sizeof(*out);
504 1.2 skrll }
505 1.2 skrll break;
506 1.2 skrll case C(UR_GET_STATUS, UT_READ_INTERFACE):
507 1.2 skrll case C(UR_GET_STATUS, UT_READ_ENDPOINT):
508 1.2 skrll /* Get Status from interface, endpoint, 9.4.5 */
509 1.2 skrll if (len > 1) {
510 1.2 skrll usb_status_t *out = buf;
511 1.2 skrll
512 1.2 skrll USETW(out->wStatus, 0);
513 1.2 skrll buflen = sizeof(*out);
514 1.2 skrll }
515 1.2 skrll break;
516 1.2 skrll case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
517 1.2 skrll /* Set Address, 9.4.6 */
518 1.3 pgoyette USBHIST_LOG(usbdebug, "UR_SET_ADDRESS, UT_WRITE_DEVICE: "
519 1.3 pgoyette "addr %jd", value, 0, 0, 0);
520 1.2 skrll if (value >= USB_MAX_DEVICES) {
521 1.2 skrll goto fail;
522 1.2 skrll }
523 1.2 skrll bus->ub_rhaddr = value;
524 1.2 skrll break;
525 1.2 skrll case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
526 1.2 skrll /* Set Configuration, 9.4.7 */
527 1.2 skrll if (value != 0 && value != 1) {
528 1.2 skrll goto fail;
529 1.2 skrll }
530 1.2 skrll bus->ub_rhconf = value;
531 1.2 skrll break;
532 1.2 skrll case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
533 1.2 skrll /* Set Descriptor, 9.4.8, not supported */
534 1.2 skrll break;
535 1.2 skrll case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
536 1.2 skrll case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
537 1.2 skrll case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
538 1.2 skrll /* Set Feature, 9.4.9, not supported */
539 1.2 skrll goto fail;
540 1.2 skrll case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
541 1.2 skrll /* Set Interface, 9.4.10, not supported */
542 1.2 skrll break;
543 1.2 skrll case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
544 1.2 skrll /* Synch Frame, 9.4.11, not supported */
545 1.2 skrll break;
546 1.2 skrll default:
547 1.2 skrll /* Default to error */
548 1.2 skrll buflen = -1;
549 1.2 skrll break;
550 1.2 skrll }
551 1.2 skrll
552 1.14 riastrad /*
553 1.14 riastrad * XXX This needs some mechanism for concurrent
554 1.14 riastrad * roothub_ctrl_abort to wait for ubm_rhctrl to finish. We
555 1.14 riastrad * can't use the bus lock because many ubm_rhctrl methods do
556 1.14 riastrad * usb_delay_ms and many bus locks are taken in softint
557 1.14 riastrad * context, leading to deadlock in the softclock needed to wake
558 1.14 riastrad * up usb_delay_ms.
559 1.14 riastrad */
560 1.14 riastrad if (!bus->ub_usepolling)
561 1.14 riastrad mutex_exit(bus->ub_lock);
562 1.2 skrll actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen);
563 1.14 riastrad if (!bus->ub_usepolling)
564 1.14 riastrad mutex_enter(bus->ub_lock);
565 1.2 skrll if (actlen < 0)
566 1.2 skrll goto fail;
567 1.2 skrll
568 1.2 skrll xfer->ux_actlen = actlen;
569 1.2 skrll err = USBD_NORMAL_COMPLETION;
570 1.2 skrll
571 1.2 skrll fail:
572 1.9 mrg USBHIST_LOG(usbdebug, "xfer %#jx buflen %jd actlen %jd err %jd",
573 1.9 mrg (uintptr_t)xfer, buflen, actlen, err);
574 1.2 skrll
575 1.2 skrll xfer->ux_status = err;
576 1.2 skrll usb_transfer_complete(xfer);
577 1.2 skrll
578 1.2 skrll return USBD_NORMAL_COMPLETION;
579 1.2 skrll }
580 1.2 skrll
581 1.2 skrll /* Abort a root control request. */
582 1.2 skrll Static void
583 1.2 skrll roothub_ctrl_abort(struct usbd_xfer *xfer)
584 1.2 skrll {
585 1.2 skrll
586 1.2 skrll /* Nothing to do, all transfers are synchronous. */
587 1.2 skrll }
588 1.2 skrll
589 1.2 skrll /* Close the root pipe. */
590 1.2 skrll Static void
591 1.2 skrll roothub_ctrl_close(struct usbd_pipe *pipe)
592 1.2 skrll {
593 1.2 skrll
594 1.2 skrll /* Nothing to do. */
595 1.2 skrll }
596 1.2 skrll
597 1.2 skrll Static void
598 1.2 skrll roothub_ctrl_done(struct usbd_xfer *xfer)
599 1.2 skrll {
600 1.2 skrll
601 1.2 skrll /* Nothing to do. */
602 1.2 skrll }
603 1.2 skrll
604 1.2 skrll static void
605 1.2 skrll roothub_noop(struct usbd_pipe *pipe)
606 1.2 skrll {
607 1.2 skrll
608 1.2 skrll }
609