Home | History | Annotate | Line # | Download | only in usb
usbroothub.c revision 1.5.2.1
      1  1.5.2.1  christos /* $NetBSD: usbroothub.c,v 1.5.2.1 2019/06/10 22:07:35 christos 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.5.2.1  christos #include <sys/cdefs.h>
     61  1.5.2.1  christos __KERNEL_RCSID(0, "$NetBSD: usbroothub.c,v 1.5.2.1 2019/06/10 22:07:35 christos Exp $");
     62  1.5.2.1  christos 
     63      1.2     skrll #include <dev/usb/usb.h>
     64      1.2     skrll #include <dev/usb/usbdi.h>
     65      1.2     skrll #include <dev/usb/usbdivar.h>
     66      1.2     skrll #include <dev/usb/usbroothub.h>
     67      1.2     skrll #include <dev/usb/usbhist.h>
     68      1.5  jakllsch #include <sys/systm.h>		/* for ostype */
     69      1.2     skrll 
     70      1.2     skrll extern int usbdebug;
     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 	struct usbd_pipe *pipe = xfer->ux_pipe;
    347      1.2     skrll 	struct usbd_bus *bus = pipe->up_dev->ud_bus;
    348      1.2     skrll 	usbd_status err;
    349      1.2     skrll 
    350      1.2     skrll 	/* Insert last in queue. */
    351      1.2     skrll 	mutex_enter(bus->ub_lock);
    352      1.2     skrll 	err = usb_insert_transfer(xfer);
    353      1.2     skrll 	mutex_exit(bus->ub_lock);
    354      1.2     skrll 	if (err)
    355      1.2     skrll 		return err;
    356      1.2     skrll 
    357      1.2     skrll 	/* Pipe isn't running, start first */
    358      1.2     skrll 	return roothub_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
    359      1.2     skrll }
    360      1.2     skrll 
    361      1.2     skrll static usbd_status
    362      1.2     skrll roothub_ctrl_start(struct usbd_xfer *xfer)
    363      1.2     skrll {
    364      1.2     skrll 	struct usbd_pipe *pipe = xfer->ux_pipe;
    365      1.2     skrll 	struct usbd_bus *bus = pipe->up_dev->ud_bus;
    366      1.2     skrll 	usb_device_request_t *req;
    367      1.2     skrll 	usbd_status err = USBD_IOERROR;		/* XXX STALL? */
    368      1.2     skrll 	uint16_t len, value;
    369      1.2     skrll 	int buflen, actlen;
    370      1.2     skrll 	void *buf;
    371      1.2     skrll 
    372      1.2     skrll 	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
    373      1.2     skrll 
    374      1.2     skrll 	KASSERT(xfer->ux_rqflags & URQ_REQUEST);
    375      1.2     skrll 	req = &xfer->ux_request;
    376      1.2     skrll 
    377      1.3  pgoyette 	USBHIST_LOG(usbdebug, "type=%#2jx request=%#2jx", req->bmRequestType,
    378      1.2     skrll 	    req->bRequest, 0, 0);
    379      1.2     skrll 
    380      1.2     skrll 	len = UGETW(req->wLength);
    381      1.2     skrll 	value = UGETW(req->wValue);
    382      1.2     skrll 
    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.5.2.1  christos 				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.5.2.1  christos 				buflen = uimin(len, sizeof(usbroothub_devd2));
    416      1.2     skrll 				memcpy(buf, &usbroothub_devd2, buflen);
    417      1.2     skrll 			} else {
    418  1.5.2.1  christos 				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.5.2.1  christos 				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.5.2.1  christos 				buflen = uimin(len, sizeof(usbroothub_confd2));
    428      1.2     skrll 				memcpy(buf, &usbroothub_confd2, buflen);
    429      1.2     skrll 			} else {
    430  1.5.2.1  christos 				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.5.2.1  christos 				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.5.2.1  christos 				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.5.2.1  christos 				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.5.2.1  christos 		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.2     skrll 	actlen = bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen);
    556      1.3  pgoyette 	USBHIST_LOG(usbdebug, "xfer %#jx buflen %jd actlen %jd",
    557      1.3  pgoyette 	    (uintptr_t)xfer, buflen, actlen, 0);
    558      1.2     skrll 	if (actlen < 0)
    559      1.2     skrll 		goto fail;
    560      1.2     skrll 
    561      1.2     skrll 	xfer->ux_actlen = actlen;
    562      1.2     skrll 	err = USBD_NORMAL_COMPLETION;
    563      1.2     skrll 
    564      1.2     skrll  fail:
    565      1.3  pgoyette 	USBHIST_LOG(usbdebug, "xfer %#jx err %jd", (uintptr_t)xfer, err, 0, 0);
    566      1.2     skrll 
    567      1.2     skrll 	xfer->ux_status = err;
    568      1.2     skrll 	mutex_enter(bus->ub_lock);
    569      1.2     skrll 	usb_transfer_complete(xfer);
    570      1.2     skrll 	mutex_exit(bus->ub_lock);
    571      1.2     skrll 
    572      1.2     skrll 	return USBD_NORMAL_COMPLETION;
    573      1.2     skrll }
    574      1.2     skrll 
    575      1.2     skrll /* Abort a root control request. */
    576      1.2     skrll Static void
    577      1.2     skrll roothub_ctrl_abort(struct usbd_xfer *xfer)
    578      1.2     skrll {
    579      1.2     skrll 
    580      1.2     skrll 	/* Nothing to do, all transfers are synchronous. */
    581      1.2     skrll }
    582      1.2     skrll 
    583      1.2     skrll /* Close the root pipe. */
    584      1.2     skrll Static void
    585      1.2     skrll roothub_ctrl_close(struct usbd_pipe *pipe)
    586      1.2     skrll {
    587      1.2     skrll 
    588      1.2     skrll 	/* Nothing to do. */
    589      1.2     skrll }
    590      1.2     skrll 
    591      1.2     skrll Static void
    592      1.2     skrll roothub_ctrl_done(struct usbd_xfer *xfer)
    593      1.2     skrll {
    594      1.2     skrll 
    595      1.2     skrll 	/* Nothing to do. */
    596      1.2     skrll }
    597      1.2     skrll 
    598      1.2     skrll static void
    599      1.2     skrll roothub_noop(struct usbd_pipe *pipe)
    600      1.2     skrll {
    601      1.2     skrll 
    602      1.2     skrll }
    603