1 1.16 mrg /* $NetBSD: usbroothub.c,v 1.16 2024/02/04 05:43:06 mrg 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.16 mrg * Matthew R. Green (mrg (at) eterna23.net) 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.16 mrg __KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.16 2024/02/04 05:43:06 mrg 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.15 riastrad /* Roothub xfers are serialized through the pipe. */ 372 1.15 riastrad KASSERTMSG(bus->ub_rhxfer == NULL, "rhxfer=%p", bus->ub_rhxfer); 373 1.15 riastrad 374 1.2 skrll KASSERT(xfer->ux_rqflags & URQ_REQUEST); 375 1.2 skrll req = &xfer->ux_request; 376 1.2 skrll 377 1.2 skrll len = UGETW(req->wLength); 378 1.2 skrll value = UGETW(req->wValue); 379 1.2 skrll 380 1.9 mrg USBHIST_CALLARGS(usbdebug, "type=%#jx request=%#jx len=%#jx value=%#jx", 381 1.9 mrg req->bmRequestType, req->bRequest, len, value); 382 1.9 mrg 383 1.2 skrll buf = len ? usbd_get_buffer(xfer) : NULL; 384 1.2 skrll buflen = 0; 385 1.2 skrll 386 1.2 skrll #define C(x,y) ((x) | ((y) << 8)) 387 1.2 skrll switch (C(req->bRequest, req->bmRequestType)) { 388 1.2 skrll case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE): 389 1.2 skrll case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE): 390 1.2 skrll case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): 391 1.2 skrll /* 392 1.2 skrll * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops 393 1.2 skrll * for the integrated root hub. 394 1.2 skrll */ 395 1.2 skrll break; 396 1.2 skrll case C(UR_GET_CONFIG, UT_READ_DEVICE): 397 1.2 skrll if (len > 0) { 398 1.2 skrll uint8_t *out = buf; 399 1.2 skrll 400 1.2 skrll *out = bus->ub_rhconf; 401 1.2 skrll buflen = sizeof(*out); 402 1.2 skrll } 403 1.2 skrll break; 404 1.2 skrll case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE): 405 1.3 pgoyette USBHIST_LOG(usbdebug, "wValue=%#4jx", value, 0, 0, 0); 406 1.2 skrll 407 1.2 skrll if (len == 0) 408 1.2 skrll break; 409 1.2 skrll switch (value) { 410 1.2 skrll case C(0, UDESC_DEVICE): 411 1.4 skrll if (bus->ub_revision >= USBREV_3_0) { 412 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_devd3)); 413 1.4 skrll memcpy(buf, &usbroothub_devd3, buflen); 414 1.4 skrll } else if (bus->ub_revision == USBREV_2_0) { 415 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_devd2)); 416 1.2 skrll memcpy(buf, &usbroothub_devd2, buflen); 417 1.2 skrll } else { 418 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_devd1)); 419 1.2 skrll memcpy(buf, &usbroothub_devd1, buflen); 420 1.2 skrll } 421 1.2 skrll break; 422 1.2 skrll case C(0, UDESC_CONFIG): 423 1.4 skrll if (bus->ub_revision >= USBREV_3_0) { 424 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd3)); 425 1.4 skrll memcpy(buf, &usbroothub_confd3, buflen); 426 1.4 skrll } else if (bus->ub_revision == USBREV_2_0) { 427 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd2)); 428 1.2 skrll memcpy(buf, &usbroothub_confd2, buflen); 429 1.2 skrll } else { 430 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd1)); 431 1.2 skrll memcpy(buf, &usbroothub_confd1, buflen); 432 1.2 skrll } 433 1.2 skrll break; 434 1.2 skrll case C(0, UDESC_DEVICE_QUALIFIER): 435 1.2 skrll if (bus->ub_revision == USBREV_2_0) { 436 1.2 skrll /* 437 1.2 skrll * We can't really operate at another speed, 438 1.2 skrll * but the spec says we need this descriptor. 439 1.2 skrll */ 440 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_odevd2)); 441 1.2 skrll memcpy(buf, &usbroothub_odevd2, buflen); 442 1.2 skrll } else 443 1.2 skrll goto fail; 444 1.2 skrll break; 445 1.2 skrll case C(0, UDESC_OTHER_SPEED_CONFIGURATION): 446 1.2 skrll if (bus->ub_revision == USBREV_2_0) { 447 1.2 skrll struct usb_roothub_descriptors confd; 448 1.2 skrll 449 1.2 skrll /* 450 1.2 skrll * We can't really operate at another speed, 451 1.2 skrll * but the spec says we need this descriptor. 452 1.2 skrll */ 453 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_confd2)); 454 1.2 skrll memcpy(&confd, &usbroothub_confd2, buflen); 455 1.2 skrll confd.urh_confd.bDescriptorType = 456 1.2 skrll UDESC_OTHER_SPEED_CONFIGURATION; 457 1.2 skrll memcpy(buf, &confd, buflen); 458 1.2 skrll } else 459 1.2 skrll goto fail; 460 1.2 skrll break; 461 1.4 skrll case C(0, UDESC_BOS): 462 1.4 skrll if (bus->ub_revision >= USBREV_3_0) { 463 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_bosd3)); 464 1.4 skrll memcpy(buf, &usbroothub_bosd3, buflen); 465 1.4 skrll } else 466 1.4 skrll goto fail; 467 1.4 skrll break; 468 1.2 skrll #define sd ((usb_string_descriptor_t *)buf) 469 1.2 skrll case C(0, UDESC_STRING): 470 1.2 skrll /* Language table */ 471 1.2 skrll buflen = usb_makelangtbl(sd, len); 472 1.2 skrll break; 473 1.2 skrll case C(1, UDESC_STRING): 474 1.2 skrll /* Vendor */ 475 1.5 jakllsch buflen = usb_makestrdesc(sd, len, ostype); 476 1.2 skrll break; 477 1.2 skrll case C(2, UDESC_STRING): 478 1.2 skrll /* Product */ 479 1.2 skrll buflen = usb_makestrdesc(sd, len, "Root hub"); 480 1.2 skrll break; 481 1.2 skrll #undef sd 482 1.2 skrll default: 483 1.2 skrll /* Default to error */ 484 1.2 skrll buflen = -1; 485 1.2 skrll } 486 1.2 skrll break; 487 1.2 skrll case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): 488 1.7 riastrad buflen = uimin(len, sizeof(usbroothub_hubd)); 489 1.2 skrll memcpy(buf, &usbroothub_hubd, buflen); 490 1.2 skrll break; 491 1.2 skrll case C(UR_GET_INTERFACE, UT_READ_INTERFACE): 492 1.2 skrll /* Get Interface, 9.4.4 */ 493 1.2 skrll if (len > 0) { 494 1.2 skrll uint8_t *out = buf; 495 1.2 skrll 496 1.2 skrll *out = 0; 497 1.2 skrll buflen = sizeof(*out); 498 1.2 skrll } 499 1.2 skrll break; 500 1.2 skrll case C(UR_GET_STATUS, UT_READ_DEVICE): 501 1.2 skrll /* Get Status from device, 9.4.5 */ 502 1.2 skrll if (len > 1) { 503 1.2 skrll usb_status_t *out = buf; 504 1.2 skrll 505 1.2 skrll USETW(out->wStatus, UDS_SELF_POWERED); 506 1.2 skrll buflen = sizeof(*out); 507 1.2 skrll } 508 1.2 skrll break; 509 1.2 skrll case C(UR_GET_STATUS, UT_READ_INTERFACE): 510 1.2 skrll case C(UR_GET_STATUS, UT_READ_ENDPOINT): 511 1.2 skrll /* Get Status from interface, endpoint, 9.4.5 */ 512 1.2 skrll if (len > 1) { 513 1.2 skrll usb_status_t *out = buf; 514 1.2 skrll 515 1.2 skrll USETW(out->wStatus, 0); 516 1.2 skrll buflen = sizeof(*out); 517 1.2 skrll } 518 1.2 skrll break; 519 1.2 skrll case C(UR_SET_ADDRESS, UT_WRITE_DEVICE): 520 1.2 skrll /* Set Address, 9.4.6 */ 521 1.3 pgoyette USBHIST_LOG(usbdebug, "UR_SET_ADDRESS, UT_WRITE_DEVICE: " 522 1.3 pgoyette "addr %jd", value, 0, 0, 0); 523 1.2 skrll if (value >= USB_MAX_DEVICES) { 524 1.2 skrll goto fail; 525 1.2 skrll } 526 1.2 skrll bus->ub_rhaddr = value; 527 1.2 skrll break; 528 1.2 skrll case C(UR_SET_CONFIG, UT_WRITE_DEVICE): 529 1.2 skrll /* Set Configuration, 9.4.7 */ 530 1.2 skrll if (value != 0 && value != 1) { 531 1.2 skrll goto fail; 532 1.2 skrll } 533 1.2 skrll bus->ub_rhconf = value; 534 1.2 skrll break; 535 1.2 skrll case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE): 536 1.2 skrll /* Set Descriptor, 9.4.8, not supported */ 537 1.2 skrll break; 538 1.2 skrll case C(UR_SET_FEATURE, UT_WRITE_DEVICE): 539 1.2 skrll case C(UR_SET_FEATURE, UT_WRITE_INTERFACE): 540 1.2 skrll case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT): 541 1.2 skrll /* Set Feature, 9.4.9, not supported */ 542 1.2 skrll goto fail; 543 1.2 skrll case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE): 544 1.2 skrll /* Set Interface, 9.4.10, not supported */ 545 1.2 skrll break; 546 1.2 skrll case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT): 547 1.2 skrll /* Synch Frame, 9.4.11, not supported */ 548 1.2 skrll break; 549 1.2 skrll default: 550 1.2 skrll /* Default to error */ 551 1.2 skrll buflen = -1; 552 1.2 skrll break; 553 1.2 skrll } 554 1.2 skrll 555 1.15 riastrad KASSERTMSG(bus->ub_rhxfer == NULL, "rhxfer=%p", bus->ub_rhxfer); 556 1.15 riastrad bus->ub_rhxfer = xfer; 557 1.14 riastrad if (!bus->ub_usepolling) 558 1.14 riastrad mutex_exit(bus->ub_lock); 559 1.15 riastrad 560 1.2 skrll actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen); 561 1.15 riastrad 562 1.14 riastrad if (!bus->ub_usepolling) 563 1.14 riastrad mutex_enter(bus->ub_lock); 564 1.15 riastrad KASSERTMSG(bus->ub_rhxfer == xfer, "rhxfer=%p", bus->ub_rhxfer); 565 1.15 riastrad bus->ub_rhxfer = NULL; 566 1.15 riastrad cv_signal(&bus->ub_rhxfercv); 567 1.15 riastrad 568 1.2 skrll if (actlen < 0) 569 1.2 skrll goto fail; 570 1.2 skrll 571 1.2 skrll xfer->ux_actlen = actlen; 572 1.2 skrll err = USBD_NORMAL_COMPLETION; 573 1.2 skrll 574 1.2 skrll fail: 575 1.9 mrg USBHIST_LOG(usbdebug, "xfer %#jx buflen %jd actlen %jd err %jd", 576 1.9 mrg (uintptr_t)xfer, buflen, actlen, err); 577 1.2 skrll 578 1.2 skrll xfer->ux_status = err; 579 1.2 skrll usb_transfer_complete(xfer); 580 1.2 skrll 581 1.2 skrll return USBD_NORMAL_COMPLETION; 582 1.2 skrll } 583 1.2 skrll 584 1.2 skrll /* Abort a root control request. */ 585 1.2 skrll Static void 586 1.2 skrll roothub_ctrl_abort(struct usbd_xfer *xfer) 587 1.2 skrll { 588 1.15 riastrad struct usbd_bus *bus = xfer->ux_bus; 589 1.15 riastrad 590 1.15 riastrad KASSERT(mutex_owned(bus->ub_lock)); 591 1.15 riastrad KASSERTMSG(bus->ub_rhxfer == xfer, "rhxfer=%p", bus->ub_rhxfer); 592 1.2 skrll 593 1.15 riastrad /* 594 1.15 riastrad * No mechanism to abort the xfer (would have to coordinate 595 1.15 riastrad * with the bus's ubm_rhctrl to be useful, and usually at most 596 1.15 riastrad * there's some short bounded delays of a few tens of 597 1.15 riastrad * milliseconds), so just wait for it to complete. 598 1.15 riastrad */ 599 1.15 riastrad while (bus->ub_rhxfer == xfer) 600 1.15 riastrad cv_wait(&bus->ub_rhxfercv, bus->ub_lock); 601 1.2 skrll } 602 1.2 skrll 603 1.2 skrll /* Close the root pipe. */ 604 1.2 skrll Static void 605 1.2 skrll roothub_ctrl_close(struct usbd_pipe *pipe) 606 1.2 skrll { 607 1.2 skrll 608 1.2 skrll /* Nothing to do. */ 609 1.2 skrll } 610 1.2 skrll 611 1.2 skrll Static void 612 1.2 skrll roothub_ctrl_done(struct usbd_xfer *xfer) 613 1.2 skrll { 614 1.2 skrll 615 1.2 skrll /* Nothing to do. */ 616 1.2 skrll } 617 1.2 skrll 618 1.2 skrll static void 619 1.2 skrll roothub_noop(struct usbd_pipe *pipe) 620 1.2 skrll { 621 1.2 skrll 622 1.2 skrll } 623