diff options
Diffstat (limited to 'usr/src/uts/common')
21 files changed, 832 insertions, 180 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index aeec9b59c3..52b9f08c74 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -832,7 +832,7 @@ SATA_OBJS += sata.o USBA_OBJS += hcdi.o usba.o usbai.o hubdi.o parser.o genconsole.o \ usbai_pipe_mgmt.o usbai_req.o usbai_util.o usbai_register.o \ - usba_devdb.o usba10_calls.o usba_ugen.o + usba_devdb.o usba10_calls.o usba_ugen.o usba_bos.o USBA10_OBJS += usba10.o diff --git a/usr/src/uts/common/io/usb/usba/genconsole.c b/usr/src/uts/common/io/usb/usba/genconsole.c index 609c1d7456..5e48a2e672 100644 --- a/usr/src/uts/common/io/usb/usba/genconsole.c +++ b/usr/src/uts/common/io/usb/usba/genconsole.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019, Joyent, Inc. */ /* @@ -40,10 +41,8 @@ * layers to initialize any state information. */ int -usb_console_input_init(dev_info_t *dip, - usb_pipe_handle_t pipe_handle, - uchar_t **state_buf, - usb_console_info_t *console_input_info) +usb_console_input_init(dev_info_t *dip, usb_pipe_handle_t pipe_handle, + uchar_t **state_buf, usb_console_info_t *console_input_info) { int ret; usba_device_t *usba_device; @@ -168,10 +167,8 @@ usb_console_input_enter(usb_console_info_t console_input_info) /* * Call the lower layer to save state information. */ - usba_device->usb_hcdi_ops->usba_hcdi_console_input_enter( - usb_console_input); - - return (USB_SUCCESS); + return (usba_device->usb_hcdi_ops->usba_hcdi_console_input_enter( + usb_console_input)); } @@ -235,10 +232,8 @@ usb_console_input_exit(usb_console_info_t console_input_info) /* * Restore the state information. */ - usba_device->usb_hcdi_ops->usba_hcdi_console_input_exit( - usb_console_input); - - return (USB_SUCCESS); + return (usba_device->usb_hcdi_ops->usba_hcdi_console_input_exit( + usb_console_input)); } /* @@ -345,10 +340,8 @@ usb_console_output_enter(usb_console_info_t console_output_info) /* * Call the lower layer to save state information. */ - usb_device->usb_hcdi_ops->usba_hcdi_console_output_enter( - usb_console_output); - - return (USB_SUCCESS); + return (usb_device->usb_hcdi_ops->usba_hcdi_console_output_enter( + usb_console_output)); } /* @@ -358,7 +351,7 @@ usb_console_output_enter(usb_console_info_t console_output_info) */ int usb_console_write(usb_console_info_t console_output_info, - uchar_t *buf, uint_t num_characters, uint_t *num_characters_written) + uchar_t *buf, uint_t num_characters, uint_t *num_characters_written) { usba_device_t *usb_device; usb_console_info_impl_t *usb_console_output; @@ -402,8 +395,6 @@ usb_console_output_exit(usb_console_info_t console_output_info) /* * Restore the state information. */ - usb_device->usb_hcdi_ops->usba_hcdi_console_output_exit( - usb_console_output); - - return (USB_SUCCESS); + return (usb_device->usb_hcdi_ops->usba_hcdi_console_output_exit( + usb_console_output)); } diff --git a/usr/src/uts/common/io/usb/usba/hubdi.c b/usr/src/uts/common/io/usb/usba/hubdi.c index e3f3722de8..99d75edce3 100644 --- a/usr/src/uts/common/io/usb/usba/hubdi.c +++ b/usr/src/uts/common/io/usb/usba/hubdi.c @@ -22,7 +22,7 @@ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2018, Joyent, Inc. + * Copyright 2019, Joyent, Inc. */ /* @@ -1797,6 +1797,10 @@ usba_hubdi_power(dev_info_t *dip, int comp, int level) retval = hubd_pwrlvl3(hubd); break; + default: + retval = USB_FAILURE; + + break; } mutex_exit(HUBD_MUTEX(hubd)); @@ -2133,11 +2137,11 @@ fail: kmem_free(pathname, MAXPATHLEN); } - mutex_enter(HUBD_MUTEX(hubd)); - hubd_pm_idle_component(hubd, dip, 0); - mutex_exit(HUBD_MUTEX(hubd)); + if (hubd != NULL) { + mutex_enter(HUBD_MUTEX(hubd)); + hubd_pm_idle_component(hubd, dip, 0); + mutex_exit(HUBD_MUTEX(hubd)); - if (hubd) { rval = hubd_cleanup(dip, hubd); if (rval != USB_SUCCESS) { USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubdi_log_handle, @@ -2180,7 +2184,7 @@ usba_hubdi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) static int hubd_setdevaddr(hubd_t *hubd, usb_port_t port) { - int rval; + int rval = USB_FAILURE; usb_cr_t completion_reason; usb_cb_flags_t cb_flags; usb_pipe_handle_t ph; @@ -2235,8 +2239,8 @@ hubd_setdevaddr(hubd_t *hubd, usb_port_t port) for (retry = 0; retry < hubd_retry_enumerate; retry++) { /* open child's default pipe with USBA_DEFAULT_ADDR */ - if (usb_pipe_open(child_dip, NULL, NULL, - USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED, &ph) != + if ((rval = usb_pipe_open(child_dip, NULL, NULL, + USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED, &ph)) != USB_SUCCESS) { USB_DPRINTF_L2(DPRINT_MASK_ATTA, hubd->h_log_handle, "hubd_setdevaddr: Unable to open default pipe"); @@ -6071,7 +6075,6 @@ hubd_ready_device(hubd_t *hubd, dev_info_t *child_dip, usba_device_t *child_ud, return (child_dip); } - /* * hubd_create_child * - create child dip @@ -6480,6 +6483,8 @@ hubd_create_child(dev_info_t *dip, goto fail_cleanup; } + /* Read the BOS data */ + usba_get_binary_object_store(child_dip, child_ud); /* get the device string descriptor(s) */ usba_get_dev_string_descrs(child_dip, child_ud); @@ -9198,7 +9203,7 @@ usba_hubdi_reset_device(dev_info_t *dip, usb_dev_reset_lvl_t reset_level) usb_port_t port = 0; dev_info_t *hdip; usb_pipe_state_t prev_pipe_state = 0; - usba_device_t *usba_device; + usba_device_t *usba_device = NULL; hubd_reset_arg_t *arg; int i, ph_open_cnt; int rval = USB_FAILURE; @@ -9372,6 +9377,7 @@ usba_hubdi_reset_device(dev_info_t *dip, usb_dev_reset_lvl_t reset_level) == USB_SUCCESS) { mutex_exit(HUBD_MUTEX(hubd)); /* re-open the default pipe */ + ASSERT3P(usba_device, !=, NULL); rval = usba_persistent_pipe_open(usba_device); mutex_enter(HUBD_MUTEX(hubd)); if (rval != USB_SUCCESS) { diff --git a/usr/src/uts/common/io/usb/usba/parser.c b/usr/src/uts/common/io/usb/usba/parser.c index 965113374c..f81bcfdb39 100644 --- a/usr/src/uts/common/io/usb/usba/parser.c +++ b/usr/src/uts/common/io/usb/usba/parser.c @@ -23,6 +23,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> + * Copyright 2019, Joyent, Inc. */ @@ -45,16 +46,13 @@ extern usba_cfg_pwr_descr_t default_cfg_power; extern usba_if_pwr_descr_t default_if_power; size_t -usb_parse_data(char *format, - uchar_t *data, - size_t datalen, - void *structure, - size_t structlen) +usb_parse_data(char *format, const uchar_t *data, size_t datalen, + void *structure, size_t structlen) { int fmt; int counter = 1; int multiplier = 0; - uchar_t *dataend = data + datalen; + const uchar_t *dataend = data + datalen; char *structstart = (char *)structure; void *structend = (void *)((intptr_t)structstart + structlen); @@ -170,11 +168,8 @@ usb_parse_data(char *format, size_t -usb_parse_CV_descr(char *format, - uchar_t *data, - size_t datalen, - void *structure, - size_t structlen) +usb_parse_CV_descr(char *format, const uchar_t *data, size_t datalen, + void *structure, size_t structlen) { return (usb_parse_data(format, data, datalen, structure, structlen)); @@ -186,16 +181,12 @@ usb_parse_CV_descr(char *format, * type descr_type, unless the end of the buffer or a descriptor * of type stop_descr_type1 or stop_descr_type2 is encountered first. */ -static uchar_t * -usb_nth_descr(uchar_t *buf, - size_t buflen, - int descr_type, - uint_t n, - int stop_descr_type1, - int stop_descr_type2) +static const uchar_t * +usb_nth_descr(const uchar_t *buf, size_t buflen, int descr_type, uint_t n, + int stop_descr_type1, int stop_descr_type2) { - uchar_t *bufstart = buf; - uchar_t *bufend = buf + buflen; + const uchar_t *bufstart = buf; + const uchar_t *bufend = buf + buflen; if (buf == NULL) { @@ -229,10 +220,8 @@ usb_nth_descr(uchar_t *buf, size_t -usb_parse_dev_descr(uchar_t *buf, /* from GET_DESCRIPTOR(DEVICE) */ - size_t buflen, - usb_dev_descr_t *ret_descr, - size_t ret_buf_len) +usb_parse_dev_descr(const uchar_t *buf, size_t buflen, + usb_dev_descr_t *ret_descr, size_t ret_buf_len) { if ((buf == NULL) || (ret_descr == NULL) || (buflen < 2) || (buf[1] != USB_DESCR_TYPE_DEV)) { @@ -246,10 +235,8 @@ usb_parse_dev_descr(uchar_t *buf, /* from GET_DESCRIPTOR(DEVICE) */ size_t -usb_parse_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - usb_cfg_descr_t *ret_descr, - size_t ret_buf_len) +usb_parse_cfg_descr(const uchar_t *buf, size_t buflen, + usb_cfg_descr_t *ret_descr, size_t ret_buf_len) { if ((buf == NULL) || (ret_descr == NULL) || (buflen < 2) || (buf[1] != USB_DESCR_TYPE_CFG)) { @@ -263,13 +250,10 @@ usb_parse_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t -usba_parse_cfg_pwr_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - usba_cfg_pwr_descr_t *ret_descr, - size_t ret_buf_len) +usba_parse_cfg_pwr_descr(const uchar_t *buf, size_t buflen, + usba_cfg_pwr_descr_t *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL)) { @@ -298,13 +282,10 @@ usba_parse_cfg_pwr_descr( size_t -usb_parse_ia_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - size_t first_if, - usb_ia_descr_t *ret_descr, - size_t ret_buf_len) +usb_parse_ia_descr(const uchar_t *buf, size_t buflen, size_t first_if, + usb_ia_descr_t *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL)) { @@ -332,14 +313,10 @@ usb_parse_ia_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t -usb_parse_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - uint_t if_number, - uint_t alt_if_setting, - usb_if_descr_t *ret_descr, - size_t ret_buf_len) +usb_parse_if_descr(const uchar_t *buf, size_t buflen, uint_t if_number, + uint_t alt_if_setting, usb_if_descr_t *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL)) { @@ -367,14 +344,10 @@ usb_parse_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ } size_t -usba_parse_if_pwr_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - uint_t if_number, - uint_t alt_if_setting, - usba_if_pwr_descr_t *ret_descr, - size_t ret_buf_len) +usba_parse_if_pwr_descr(const uchar_t *buf, size_t buflen, uint_t if_number, + uint_t alt_if_setting, usba_if_pwr_descr_t *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL)) { @@ -422,15 +395,11 @@ usba_parse_if_pwr_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ * the first endpoint */ size_t -usb_parse_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - uint_t if_number, - uint_t alt_if_setting, - uint_t ep_index, - usb_ep_descr_t *ret_descr, - size_t ret_buf_len) +usb_parse_ep_descr(const uchar_t *buf, size_t buflen, uint_t if_number, + uint_t alt_if_setting, uint_t ep_index, usb_ep_descr_t *ret_descr, + size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL)) { @@ -473,14 +442,12 @@ usb_parse_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ */ /*ARGSUSED*/ size_t -usba_ascii_string_descr(uchar_t *buf, /* from GET_DESCRIPTOR(STRING) */ - size_t buflen, - char *ret_descr, - size_t ret_buf_len) +usba_ascii_string_descr(const uchar_t *buf, size_t buflen, char *ret_descr, + size_t ret_buf_len) { - int i = 1; - char *retstart = ret_descr; - uchar_t *bufend = buf + buflen; + int i = 1; + char *retstart = ret_descr; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL) || (ret_buf_len == 0) || (buflen < 2) || @@ -501,15 +468,10 @@ usba_ascii_string_descr(uchar_t *buf, /* from GET_DESCRIPTOR(STRING) */ size_t -usb_parse_CV_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - char *fmt, - uint_t descr_type, - uint_t descr_index, - void *ret_descr, - size_t ret_buf_len) +usb_parse_CV_cfg_descr(const uchar_t *buf, size_t buflen, char *fmt, + uint_t descr_type, uint_t descr_index, void *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL) || (buflen < 2) || ((buf = usb_nth_descr(buf, buflen, descr_type, @@ -525,17 +487,11 @@ usb_parse_CV_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t -usb_parse_CV_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - char *fmt, - uint_t if_number, - uint_t alt_if_setting, - uint_t descr_type, - uint_t descr_index, - void *ret_descr, - size_t ret_buf_len) +usb_parse_CV_if_descr(const uchar_t *buf, size_t buflen, char *fmt, + uint_t if_number, uint_t alt_if_setting, uint_t descr_type, + uint_t descr_index, void *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL)) { @@ -570,18 +526,11 @@ usb_parse_CV_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t -usb_parse_CV_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ - size_t buflen, - char *fmt, - uint_t if_number, - uint_t alt_if_setting, - uint_t ep_index, - uint_t descr_type, - uint_t descr_index, - void *ret_descr, - size_t ret_buf_len) +usb_parse_CV_ep_descr(const uchar_t *buf, size_t buflen, char *fmt, + uint_t if_number, uint_t alt_if_setting, uint_t ep_index, uint_t descr_type, + uint_t descr_index, void *ret_descr, size_t ret_buf_len) { - uchar_t *bufend = buf + buflen; + const uchar_t *bufend = buf + buflen; if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL)) { diff --git a/usr/src/uts/common/io/usb/usba/usba.c b/usr/src/uts/common/io/usb/usba/usba.c index 7cc68e79df..6a37f8430a 100644 --- a/usr/src/uts/common/io/usb/usba/usba.c +++ b/usr/src/uts/common/io/usb/usba/usba.c @@ -24,6 +24,7 @@ * * Copyright 2014 Garrett D'Amore <garrett@damore.org> * Copyright 2016 James S. Blachly, MD <james.blachly@gmail.com> + * Copyright 2019 Joyent, Inc. */ @@ -776,6 +777,8 @@ usba_free_usba_device(usba_device_t *usba_device) strlen(usba_device->usb_serialno_str) + 1); } + usba_free_binary_object_store(usba_device); + usba_unset_usb_address(usba_device); } @@ -2262,6 +2265,17 @@ usba_ready_device_node(dev_info_t *child_dip) } } + if (usba_device->usb_port_status == USBA_FULL_SPEED_DEV) { + /* create boolean property */ + rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, child_dip, + "full-speed"); + if (rval != DDI_PROP_SUCCESS) { + USB_DPRINTF_L2(DPRINT_MASK_USBA, usba_log_handle, + "usba_ready_device_node: " + "full speed prop update failed"); + } + } + if (usba_device->usb_port_status == USBA_HIGH_SPEED_DEV) { /* create boolean property */ rval = ndi_prop_create_boolean(DDI_DEV_T_NONE, child_dip, @@ -2283,6 +2297,8 @@ usba_ready_device_node(dev_info_t *child_dip) } } + usba_add_binary_object_store_props(child_dip, usba_device); + USB_DPRINTF_L4(DPRINT_MASK_USBA, usba_log_handle, "%s%d at port %d: %s, dip=0x%p", ddi_node_name(ddi_get_parent(child_dip)), @@ -2906,7 +2922,6 @@ usba_get_mfg_prod_sn_str( return (buffer); } - /* * USB enumeration statistic functions */ diff --git a/usr/src/uts/common/io/usb/usba/usba10_calls.c b/usr/src/uts/common/io/usb/usba/usba10_calls.c index 2bdcfd11c4..9fe39418e8 100644 --- a/usr/src/uts/common/io/usb/usba/usba10_calls.c +++ b/usr/src/uts/common/io/usb/usba/usba10_calls.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019, Joyent, Inc. */ @@ -80,7 +81,7 @@ usba10_usb_free_descr_tree( size_t usba10_usb_parse_data( char *format, - uchar_t *data, + const uchar_t *data, size_t datalen, void *structure, size_t structlen) diff --git a/usr/src/uts/common/io/usb/usba/usba_bos.c b/usr/src/uts/common/io/usb/usba/usba_bos.c new file mode 100644 index 0000000000..df8bd00680 --- /dev/null +++ b/usr/src/uts/common/io/usb/usba/usba_bos.c @@ -0,0 +1,420 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +/* + * Routines to access, parse, and manage the USB Binary Object Store + */ + +#define USBA_FRAMEWORK +#include <sys/usb/usba/usba_impl.h> +#include <sys/strsun.h> +#include <sys/sysmacros.h> + +static size_t +usba_bos_parse_bos_descr(const uchar_t *buf, size_t buflen, + usb_bos_descr_t *bosp, size_t rlen) +{ + if (buf == NULL || bosp == NULL || buflen < USB_BOS_PACKED_SIZE || + buf[1] != USB_DESCR_TYPE_BOS) { + return (USB_PARSE_ERROR); + } + + return (usb_parse_data("ccsc", buf, buflen, bosp, rlen)); +} + +static boolean_t +usba_bos_parse_usb2ext(const uchar_t *buf, size_t buflen, usb_bos_t *bosp) +{ + size_t len; + + if (buflen != USB_BOS_USB2EXT_PACKED_SIZE) { + return (B_FALSE); + } + + len = usb_parse_data("cccl", buf, buflen, &bosp->ubos_caps.ubos_usb2, + sizeof (usb_bos_usb2ext_t)); + return (len == sizeof (usb_bos_usb2ext_t)); +} + +static boolean_t +usba_bos_parse_superspeed(const uchar_t *buf, size_t buflen, usb_bos_t *bosp) +{ + size_t len; + + if (buflen != USB_BOS_SSUSB_PACKED_SIZE) { + return (B_FALSE); + } + + len = usb_parse_data("ccccsccs", buf, buflen, + &bosp->ubos_caps.ubos_ssusb, sizeof (usb_bos_ssusb_t)); + return (len == sizeof (usb_bos_ssusb_t)); +} + +static boolean_t +usba_bos_parse_container(const uchar_t *buf, size_t buflen, usb_bos_t *bosp) +{ + size_t len; + + if (buflen != USB_BOS_CONTAINER_PACKED_SIZE) { + return (B_FALSE); + } + + len = usb_parse_data("cccc16c", buf, buflen, + &bosp->ubos_caps.ubos_container, sizeof (usb_bos_container_t)); + return (len == sizeof (usb_bos_container_t)); +} + +static boolean_t +usba_bos_parse_precision_time(const uchar_t *buf, size_t buflen, + usb_bos_t *bosp) +{ + size_t len; + + if (buflen != USB_BOS_PRECISION_TIME_PACKED_SIZE) { + return (B_FALSE); + } + + len = usb_parse_data("ccc", buf, buflen, &bosp->ubos_caps.ubos_time, + sizeof (usb_bos_precision_time_t)); + /* + * The actual size of this structure will usually be rounded up to four + * bytes by the compiler, therefore we need to compare against the + * packed size. + */ + return (len == USB_BOS_PRECISION_TIME_PACKED_SIZE); +} + +/* + * Validate that the BOS looks reasonable. This means the following: + * + * - We read the whole length of the descriptor + * - The total number of capabilities doesn't exceed the expected value + * - The length of each device capabilities fits within our expected range + * + * After we finish that up, go through and save all of the valid BOS + * descriptors, unpacking the ones that we actually understand. + */ +static boolean_t +usba_bos_save(usba_device_t *ud, const mblk_t *mp, usb_bos_descr_t *bdesc) +{ + size_t len = MBLKL(mp); + const uchar_t *buf = mp->b_rptr; + uint_t ncaps, nalloc; + usb_bos_t *bos; + + if (bdesc->bLength != USB_BOS_PACKED_SIZE || + bdesc->bNumDeviceCaps == 0 || len < USB_BOS_PACKED_SIZE || + len < bdesc->wTotalLength) { + return (B_FALSE); + } + + len = MIN(len, bdesc->wTotalLength); + buf += USB_BOS_PACKED_SIZE; + len -= USB_BOS_PACKED_SIZE; + + if (len < USB_DEV_CAP_PACKED_SIZE) { + return (B_FALSE); + } + + ncaps = 0; + while (len > 0) { + usb_dev_cap_descr_t dev; + + if (usb_parse_data("ccc", buf, len, &dev, sizeof (dev)) != + USB_DEV_CAP_PACKED_SIZE) { + return (B_FALSE); + } + + if (dev.bDescriptorType != USB_DESCR_TYPE_DEV_CAPABILITY || + dev.bLength > len) { + return (B_FALSE); + } + + ncaps++; + len -= dev.bLength; + buf += dev.bLength; + } + + if (ncaps != bdesc->bNumDeviceCaps) { + return (B_FALSE); + } + + nalloc = ncaps; + bos = kmem_zalloc(sizeof (usb_bos_t) * nalloc, KM_SLEEP); + buf = mp->b_rptr + USB_BOS_PACKED_SIZE; + len = MIN(MBLKL(mp), bdesc->wTotalLength) - USB_BOS_PACKED_SIZE; + ncaps = 0; + while (len > 0) { + usb_dev_cap_descr_t dev; + boolean_t valid; + + if (usb_parse_data("ccc", buf, len, &dev, sizeof (dev)) != + USB_DEV_CAP_PACKED_SIZE) { + goto fail; + } + + bos[ncaps].ubos_length = dev.bLength; + bos[ncaps].ubos_type = dev.bDevCapabilityType; + + valid = B_FALSE; + switch (dev.bDevCapabilityType) { + case USB_BOS_TYPE_USB2_EXT: + valid = usba_bos_parse_usb2ext(buf, dev.bLength, + &bos[ncaps]); + break; + case USB_BOS_TYPE_SUPERSPEED: + valid = usba_bos_parse_superspeed(buf, dev.bLength, + &bos[ncaps]); + break; + case USB_BOS_TYPE_CONTAINER: + valid = usba_bos_parse_container(buf, dev.bLength, + &bos[ncaps]); + break; + case USB_BOS_TYPE_PRECISION_TIME: + valid = usba_bos_parse_precision_time(buf, dev.bLength, + &bos[ncaps]); + break; + default: + /* + * Override the type to one that we know isn't used to + * indicate that the caller can't rely on the type + * that's present here. + */ + bos[ncaps].ubos_type = USB_BOS_TYPE_INVALID; + bcopy(buf, bos[ncaps].ubos_caps.ubos_raw, dev.bLength); + valid = B_TRUE; + break; + } + + if (valid) { + ncaps++; + } else { + bos[ncaps].ubos_length = 0; + bos[ncaps].ubos_type = USB_BOS_TYPE_INVALID; + bzero(bos[ncaps].ubos_caps.ubos_raw, + sizeof (bos[ncaps].ubos_caps.ubos_raw)); + } + len -= dev.bLength; + buf += dev.bLength; + } + + ud->usb_bos_nalloc = nalloc; + ud->usb_bos_nents = ncaps; + ud->usb_bos = bos; + + return (B_TRUE); + +fail: + kmem_free(bos, sizeof (usb_bos_t) * nalloc); + return (B_FALSE); +} + +/* + * Read the Binary Object Store (BOS) data from the device and attempt to parse + * it. Do not fail to attach the device if we cannot get all of the information + * at this time. While certain aspects of the BOS are required for Windows, + * which suggests that we could actually rely on it, we haven't historically. + */ +void +usba_get_binary_object_store(dev_info_t *dip, usba_device_t *ud) +{ + int rval; + mblk_t *mp = NULL; + usb_cr_t completion_reason; + usb_cb_flags_t cb_flags; + usb_pipe_handle_t ph; + size_t size; + usb_bos_descr_t bos; + + /* + * The BOS is only supported on USB 3.x devices. Therefore if the bcdUSB + * is greater than USB 2.0, we can check this. Note, USB 3.x devices + * that are linked on a USB device will report version 2.1 in the bcdUSB + * field. + */ + if (ud->usb_dev_descr->bcdUSB <= 0x200) { + return; + } + + ph = usba_get_dflt_pipe_handle(dip); + + /* + * First get just the BOS descriptor itself. + */ + rval = usb_pipe_sync_ctrl_xfer(dip, ph, + USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, + USB_REQ_GET_DESCR, /* bRequest */ + (USB_DESCR_TYPE_BOS << 8), /* wValue */ + 0, /* wIndex */ + USB_BOS_PACKED_SIZE, /* wLength */ + &mp, USB_ATTRS_SHORT_XFER_OK, + &completion_reason, &cb_flags, 0); + + if (rval != USB_SUCCESS) { + return; + } + + size = usba_bos_parse_bos_descr(mp->b_rptr, MBLKL(mp), &bos, + sizeof (bos)); + freemsg(mp); + mp = NULL; + if (size < USB_BOS_PACKED_SIZE) { + return; + } + + /* + * Check to see if there are any capabilities and if it's worth getting + * the whole BOS. + */ + if (bos.bLength != USB_BOS_PACKED_SIZE || bos.bNumDeviceCaps == 0) { + return; + } + + rval = usb_pipe_sync_ctrl_xfer(dip, ph, + USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_TYPE_STANDARD, + USB_REQ_GET_DESCR, /* bRequest */ + (USB_DESCR_TYPE_BOS << 8), /* wValue */ + 0, /* wIndex */ + bos.wTotalLength, /* wLength */ + &mp, USB_ATTRS_SHORT_XFER_OK, + &completion_reason, &cb_flags, 0); + + if (rval != USB_SUCCESS) { + return; + } + + size = usba_bos_parse_bos_descr(mp->b_rptr, MBLKL(mp), &bos, + sizeof (bos)); + if (size < USB_BOS_PACKED_SIZE) { + freemsg(mp); + return; + } + + if (!usba_bos_save(ud, mp, &bos)) { + freemsg(mp); + return; + } + + ud->usb_bos_mp = mp; +} + +static void +usba_add_superspeed_props(dev_info_t *dip, usb_bos_ssusb_t *ssusb) +{ + char *supported[4]; + uint_t nsup = 0; + char *min; + + if (ssusb->wSpeedsSupported & USB_BOS_SSUSB_SPEED_LOW) { + supported[nsup++] = "low-speed"; + } + + if (ssusb->wSpeedsSupported & USB_BOS_SSUSB_SPEED_FULL) { + supported[nsup++] = "full-speed"; + } + + if (ssusb->wSpeedsSupported & USB_BOS_SSUSB_SPEED_HIGH) { + supported[nsup++] = "high-speed"; + } + + if (ssusb->wSpeedsSupported & USB_BOS_SSUSB_SPEED_SUPER) { + supported[nsup++] = "super-speed"; + } + + if (nsup != 0 && ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, + "usb-supported-speeds", supported, nsup) != DDI_PROP_SUCCESS) { + USB_DPRINTF_L2(DPRINT_MASK_USBA, NULL, "failed to add " + "usb-supported-speeds property"); + } + + switch (ssusb->bFunctionalitySupport) { + case 0: + min = "low-speed"; + break; + case 1: + min = "full-speed"; + break; + case 2: + min = "high-speed"; + break; + case 3: + min = "super-speed"; + break; + default: + min = NULL; + } + + if (min != NULL && ndi_prop_update_string(DDI_DEV_T_NONE, dip, + "usb-minimum-speed", min) != DDI_PROP_SUCCESS) { + USB_DPRINTF_L2(DPRINT_MASK_USBA, NULL, "failed to add " + "usb-minimum-speed property"); + } +} + +static void +usba_add_container_props(dev_info_t *dip, usb_bos_container_t *cp) +{ + if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip, "usb-container-id", + cp->ContainerId, sizeof (cp->ContainerId)) != DDI_PROP_SUCCESS) { + USB_DPRINTF_L2(DPRINT_MASK_USBA, NULL, "failed to add " + "usb-container-id property"); + } +} + +void +usba_add_binary_object_store_props(dev_info_t *dip, usba_device_t *ud) +{ + uint_t i; + + if (ud->usb_bos == NULL) { + return; + } + + for (i = 0; i < ud->usb_bos_nents; i++) { + usb_bos_t *bos = &ud->usb_bos[i]; + + switch (bos->ubos_type) { + case USB_BOS_TYPE_SUPERSPEED: + usba_add_superspeed_props(dip, + &bos->ubos_caps.ubos_ssusb); + break; + case USB_BOS_TYPE_CONTAINER: + usba_add_container_props(dip, + &bos->ubos_caps.ubos_container); + break; + default: + /* + * This is a capability that we're not going to add + * devinfo properties to describe. + */ + continue; + } + } +} + +void +usba_free_binary_object_store(usba_device_t *ud) +{ + if (ud->usb_bos_mp != NULL) { + freemsg(ud->usb_bos_mp); + ud->usb_bos_mp = NULL; + } + + if (ud->usb_bos != NULL) { + kmem_free(ud->usb_bos, sizeof (usb_bos_t) * ud->usb_bos_nalloc); + ud->usb_bos = NULL; + ud->usb_bos_nalloc = ud->usb_bos_nents = 0; + } +} diff --git a/usr/src/uts/common/io/usb/usba/usba_devdb.c b/usr/src/uts/common/io/usb/usba/usba_devdb.c index 4fd1748bf0..e3d14f90c6 100644 --- a/usr/src/uts/common/io/usb/usba/usba_devdb.c +++ b/usr/src/uts/common/io/usb/usba/usba_devdb.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019, Joyent, Inc. */ @@ -140,13 +141,13 @@ usba_devdb_get_conf_rec(struct _buf *file, usba_configrec_t **rec) token_t token; char tokval[MAXPATHLEN]; usba_configrec_t *cfgrec; - config_field_t cfgvar; + config_field_t cfgvar = USB_NONE; u_longlong_t llptr; u_longlong_t value; enum { USB_NEWVAR, USB_CONFIG_VAR, USB_VAR_EQUAL, USB_VAR_VALUE, USB_ERROR - } parse_state = USB_NEWVAR; + } parse_state = USB_NEWVAR; cfgrec = (usba_configrec_t *)kmem_zalloc( sizeof (usba_configrec_t), KM_SLEEP); diff --git a/usr/src/uts/common/io/usb/usba/usba_ugen.c b/usr/src/uts/common/io/usb/usba/usba_ugen.c index 745497f590..bcc658a001 100644 --- a/usr/src/uts/common/io/usb/usba/usba_ugen.c +++ b/usr/src/uts/common/io/usb/usba/usba_ugen.c @@ -24,7 +24,7 @@ */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ /* @@ -409,11 +409,9 @@ usb_ugen_attach(usb_ugen_hdl_t usb_ugen_hdl, ddi_attach_cmd_t cmd) return (DDI_SUCCESS); fail: - if (ugenp) { - USB_DPRINTF_L2(UGEN_PRINT_ATTA, ugenp->ug_log_hdl, - "attach fail"); - (void) ugen_cleanup(ugenp); - } + USB_DPRINTF_L2(UGEN_PRINT_ATTA, ugenp->ug_log_hdl, + "attach fail"); + (void) ugen_cleanup(ugenp); return (DDI_FAILURE); } @@ -2545,7 +2543,7 @@ ugen_epx_ctrl_req(ugen_state_t *ugenp, ugen_ep_t *epp, goto fail; } -done: + *wait = B_TRUE; return (USB_SUCCESS); diff --git a/usr/src/uts/common/io/usb/usba/usbai.c b/usr/src/uts/common/io/usb/usba/usbai.c index 1ff8507ff1..f6ac391bd8 100644 --- a/usr/src/uts/common/io/usb/usba/usbai.c +++ b/usr/src/uts/common/io/usb/usba/usbai.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2019, Joyent, Inc. */ @@ -115,8 +116,8 @@ usba_usbai_destroy() */ usb_log_handle_t usb_alloc_log_hdl(dev_info_t *dip, char *name, - uint_t *errlevel, uint_t *mask, uint_t *instance_filter, - usb_flags_t flags) + uint_t *errlevel, uint_t *mask, uint_t *instance_filter, + usb_flags_t flags) { usba_log_handle_impl_t *hdl; @@ -147,8 +148,8 @@ usb_alloc_log_hdl(dev_info_t *dip, char *name, /*ARGSUSED*/ usb_log_handle_t usb_alloc_log_handle(dev_info_t *dip, char *name, - uint_t *errlevel, uint_t *mask, uint_t *instance_filter, - uint_t reserved, usb_flags_t flags) + uint_t *errlevel, uint_t *mask, uint_t *instance_filter, + uint_t reserved, usb_flags_t flags) { return (usb_alloc_log_hdl(dip, name, errlevel, mask, instance_filter, flags)); @@ -215,7 +216,7 @@ static void usb_vprintf(dev_info_t *dip, int level, char *label, char *fmt, va_list ap) { size_t len; - int instance; + int instance = 0; char driver_name[USBA_DRVNAME_LEN]; char *msg_ptr; @@ -383,7 +384,7 @@ usb_vprintf(dev_info_t *dip, int level, char *label, char *fmt, va_list ap) int usba_vlog(usb_log_handle_t, uint_t, uint_t, char *, va_list) - __KVPRINTFLIKE(4); + __KVPRINTFLIKE(4); /* When usba10_calls.c goes away, this function can be made static again. */ int @@ -579,7 +580,7 @@ usba_async_req_raise_power(void *arg) /* usb function to perform async pm_request_power_change */ int usb_req_raise_power(dev_info_t *dip, int comp, int level, - void (*callback)(void *, int), void *arg, usb_flags_t flags) + void (*callback)(void *, int), void *arg, usb_flags_t flags) { usba_pm_req_t *pmrq; @@ -633,7 +634,7 @@ usba_async_req_lower_power(void *arg) /* usb function to perform async pm_request_power_change */ int usb_req_lower_power(dev_info_t *dip, int comp, int level, - void (*callback)(void *, int), void *arg, usb_flags_t flags) + void (*callback)(void *, int), void *arg, usb_flags_t flags) { usba_pm_req_t *pmrq; @@ -1100,7 +1101,7 @@ usb_unregister_hotplug_cbs(dev_info_t *dip) /*ARGSUSED*/ int usb_register_event_cbs(dev_info_t *dip, usb_event_t *usb_evdata, - usb_flags_t flags) + usb_flags_t flags) { usba_device_t *usba_device; usba_evdata_t *evdata; diff --git a/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c b/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c index 296fcab878..455774b1b4 100644 --- a/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c +++ b/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c @@ -23,7 +23,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> - * Copyright 2016 Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ @@ -540,7 +540,7 @@ usba_init_pipe_handle(dev_info_t *dip, } /* fix up the MaxPacketSize if it is the default endpoint descr */ - if ((ep == &usba_default_ep_descr) && usba_device) { + if (ep == &usba_default_ep_descr) { uint16_t maxpktsize; maxpktsize = usba_device->usb_dev_descr->bMaxPacketSize0; diff --git a/usr/src/uts/common/io/usb/usba/usbai_register.c b/usr/src/uts/common/io/usb/usba/usbai_register.c index 6d22a188df..8b75a7619b 100644 --- a/usr/src/uts/common/io/usb/usba/usbai_register.c +++ b/usr/src/uts/common/io/usb/usba/usbai_register.c @@ -23,7 +23,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> - * Copyright (c) 2017, Joyent, Inc. + * Copyright 2019, Joyent, Inc. */ /* @@ -1313,7 +1313,7 @@ usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements) uint8_t largest_value; uint8_t curr_value; uint_t in_order = 0; - usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */ + usb_alt_if_data_t *orig_addr; /* Non-sparse array base ptr */ usb_alt_if_data_t *repl_array; /* Base ptr to sparse array */ uint_t n_repl_elements; /* Number elements in the new array */ uint_t i; @@ -1328,6 +1328,7 @@ usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements) "make_sparse: array=0x%p, n_orig_elements=%d", (void *)array, n_orig_elements); + orig_addr = *array; curr_value = orig_addr[0].altif_descr.bAlternateSetting; smallest_value = largest_value = curr_value; @@ -1635,7 +1636,7 @@ usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg, usb_cfg_descr_t *config_descr; /* and its USB descriptor. */ char *string; char *name_string = NULL; - int name_string_size; + int name_string_size = 0; if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) { diff --git a/usr/src/uts/common/io/usb/usba/usbai_req.c b/usr/src/uts/common/io/usb/usba/usbai_req.c index 4792d32efb..3a99185225 100644 --- a/usr/src/uts/common/io/usb/usba/usbai_req.c +++ b/usr/src/uts/common/io/usb/usba/usbai_req.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019 Joyent, Inc. */ @@ -113,7 +114,7 @@ _usba_check_req(usba_pipe_handle_data_t *ph_data, usb_opaque_t req, mblk_t *data; usb_cr_t *cr; usb_req_attrs_t attrs; - usb_opaque_t cb, exc_cb; + usb_opaque_t cb = NULL, exc_cb = NULL; uint_t timeout = 0; uchar_t direction = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; @@ -144,6 +145,8 @@ _usba_check_req(usba_pipe_handle_data_t *ph_data, usb_opaque_t req, case USB_EP_ATTR_ISOCH: cr = &isoc_req->isoc_completion_reason; break; + default: + return (USB_INVALID_REQUEST); } *cr = USB_CR_UNSPECIFIED_ERR; @@ -220,6 +223,8 @@ _usba_check_req(usba_pipe_handle_data_t *ph_data, usb_opaque_t req, cb = (usb_opaque_t)isoc_req->isoc_cb; exc_cb = (usb_opaque_t)isoc_req->isoc_exc_cb; break; + default: + return (USB_INVALID_REQUEST); } USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, diff --git a/usr/src/uts/common/io/usb/usba/usbai_util.c b/usr/src/uts/common/io/usb/usba/usbai_util.c index dd942e35f2..58fbd472ae 100644 --- a/usr/src/uts/common/io/usb/usba/usbai_util.c +++ b/usr/src/uts/common/io/usb/usba/usbai_util.c @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019 Joyent, Inc. */ @@ -301,7 +302,7 @@ usb_get_string_descr(dev_info_t *dip, usba_get_dflt_pipe_handle(dip), USB_DEV_REQ_DEV_TO_HOST, USB_REQ_GET_DESCR, - USB_DESCR_TYPE_STRING << 8 | index & 0xff, + (USB_DESCR_TYPE_STRING << 8) | (index & 0xff), langid, 4, &data, USB_ATTRS_SHORT_XFER_OK, @@ -345,7 +346,7 @@ usb_get_string_descr(dev_info_t *dip, usba_get_dflt_pipe_handle(dip), USB_DEV_REQ_DEV_TO_HOST, USB_REQ_GET_DESCR, - USB_DESCR_TYPE_STRING << 8 | index & 0xff, + (USB_DESCR_TYPE_STRING << 8) | (index & 0xff), langid, length, &data, USB_ATTRS_SHORT_XFER_OK, @@ -2009,7 +2010,7 @@ usb_serialize_access( usb_serialization_t tokenp, uint_t how_to_wait, uint_t delta_timeout) { int rval = 1; /* Must be initialized > 0 */ - clock_t abs_timeout; + clock_t abs_timeout = 0; usba_serialization_impl_t *impl_tokenp; impl_tokenp = (usba_serialization_impl_t *)tokenp; diff --git a/usr/src/uts/common/io/usb/usba10/usba10.c b/usr/src/uts/common/io/usb/usba10/usba10.c index 9c8b0bed49..0c8e4af630 100644 --- a/usr/src/uts/common/io/usb/usba10/usba10.c +++ b/usr/src/uts/common/io/usb/usba10/usba10.c @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019, Joyent, Inc. */ @@ -107,7 +108,7 @@ usb_free_descr_tree( size_t usb_parse_data( char *format, - uchar_t *data, + const uchar_t *data, size_t datalen, void *structure, size_t structlen) diff --git a/usr/src/uts/common/sys/usb/usba/bos.h b/usr/src/uts/common/sys/usb/usba/bos.h new file mode 100644 index 0000000000..417dd1e60c --- /dev/null +++ b/usr/src/uts/common/sys/usb/usba/bos.h @@ -0,0 +1,242 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2019 Joyent, Inc. + */ + +#ifndef _SYS_USB_BOS_H +#define _SYS_USB_BOS_H + +/* + * This header contains definitions that relate to the USB Binary Object Store. + * While this functionality was originally introduced with WUSB, it was used in + * USB 3.x as a way to provide additional device related information. This is + * currently separate from the primary usbai headers as this functionality is + * not currently used by client device drivers themselves, but only by the hub + * driver for private functionality. + * + * This data is all derived from the USB 3.1 specification, Chapter 9.6.2 Binary + * Device Object Store (BOS). + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Capability list, see USB 3.1 r1.0, Table 9-14. + */ +#define USB_BOS_TYPE_INVALID 0x00 /* Internal, synthetic value */ +#define USB_BOS_TYPE_WUSB 0x01 +#define USB_BOS_TYPE_USB2_EXT 0x02 +#define USB_BOS_TYPE_SUPERSPEED 0x03 +#define USB_BOS_TYPE_CONTAINER 0x04 +#define USB_BOS_TYPE_PLATFORM 0x05 +#define USB_BOS_TYPE_PD_CAP 0x06 +#define USB_BOS_TYPE_BATTERY_INFO 0x07 +#define USB_BOS_TYPE_PD_CONSUMER_CAP 0x08 +#define USB_BOS_TYPE_PD_PRODUCER_CAP 0x09 +#define USB_BOS_TYPE_SUPERSPEED_PLUS 0x0a +#define USB_BOS_TYPE_PRECISION_TIME 0x0b +#define USB_BOS_TYPE_WUSB_EXT 0x0c + +/* + * General Binary Object Store (BOS) descriptor. This is returned at the start + * of the BOS tree. See USB 3.1/Table 9-12. + */ +typedef struct usb_bos_descr { + uint8_t bLength; /* Descriptor size */ + uint8_t bDescriptorType; /* Set to USB_DESCR_TYPE_BOS */ + uint16_t wTotalLength; /* Total length */ + uint8_t bNumDeviceCaps; /* Number of caps that follow */ +} usb_bos_descr_t; + +/* + * This is the size of the usb_bos_descr_t in terms of packed bytes. + */ +#define USB_BOS_PACKED_SIZE 5 + +/* + * This represents a Device Capability Descriptor. bNumDeviceCaps of these + * follow the usb_bos_descr_t. This structure is the generic header of each + * device capability. Capability specific ones follow this. See USB 3.1/Table + * 9-14. + */ +typedef struct usb_dev_cap_descr { + uint8_t bLength; /* Descriptor size */ + uint8_t bDescriptorType; /* USB_TYPE_DEV_CAPABILITY */ + uint8_t bDevCapabilityType; /* USB_BOS_TYPE_* value */ +} usb_dev_cap_descr_t; + +#define USB_DEV_CAP_PACKED_SIZE 3 + +/* + * SuperSpeed devices include this descriptor to describe additional + * capabilities that they have when operating in USB 2.0 High-Speed mode. See + * USB 3.1/9.6.2.1 USB 2.0 Extension. + */ +typedef struct usb_bos_usb2ext { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint32_t bmAttributes; /* Bitfield defined below */ +} usb_bos_usb2ext_t; + +#define USB_BOS_USB2EXT_PACKED_SIZE 7 + +#define USB_BOS_USB2EXT_LPM 0x02 + +/* + * SuperSpeed devices include this descriptor to describe various hardware + * attributes related to basic USB 3.0 SuperSpeed functionality. See USB + * 3.1/9.6.2.2 SuperSpeed USB Device Capability. + */ +typedef struct usb_bos_ssusb { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bmAttributes; /* Capability bitfield */ + uint16_t wSpeedsSupported; /* speed bitmap defined below */ + uint8_t bFunctionalitySupport; /* Minimum supported speed */ + uint8_t bU1DevExitLat; /* Exit latency in us */ + uint16_t bU2DevExitLat; /* Exit latency in us */ +} usb_bos_ssusb_t; + +#define USB_BOS_SSUSB_PACKED_SIZE 10 + +#define USB_BOS_SSUB_CAP_LTM 0x02 + +#define USB_BOS_SSUSB_SPEED_LOW (1 << 0) +#define USB_BOS_SSUSB_SPEED_FULL (1 << 1) +#define USB_BOS_SSUSB_SPEED_HIGH (1 << 2) +#define USB_BOS_SSUSB_SPEED_SUPER (1 << 3) + +/* + * This structure is used to indicate a UUID for a given device that could + * register on multiple ports. For example, a hub that appears on both a USB 2.x + * and USB 3.x port like a hub. This UUID allows one to know that the device is + * the same. See USB 3.1/9.6.2.3 Container ID. + */ +typedef struct usb_bos_container { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t ContainerId[16]; +} usb_bos_container_t; + +#define USB_BOS_CONTAINER_PACKED_SIZE 20 + +/* + * This structure is used to indicate a platform-specific capability. For more + * information, see USB 3.1/9.6.2.4 Platform Descriptor. + */ +typedef struct usb_bos_platform { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t PlatformCapabilityUUID[16]; + uint8_t CapabilityData[]; +} usb_bos_platform_t; + +#define USB_BOS_PLATFORM_MIN_PACKED_SIZE 20 + +/* + * This structure is used to indicate capabilities and attributes of a + * SuperSpeedPlus link. This describes the USB 3.1+ speed needs and minimum + * attributes of the device. See USB 3.1/9.6.2.5 SuperSpeedPlus USB Device + * Capability. + */ +typedef struct usb_bos_ssplus { + uint8_t bLength; + uint8_t bDescriptortype; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint32_t bmAttributes; + uint16_t wFunctionalitySupport; + uint16_t wReserved; + uint32_t bmSublinkSpeedAttr[]; +} usb_bos_ssplus_t; + +#define USB_BOS_SSPLUS_MIN_PACKED_SIZE 16 + +/* + * These macros take apart the bmAttributes fields. + */ +#define USB_BOS_SSPLUS_NSSAC(x) (((x) & 0xf) + 1) +#define USB_BOS_SSPLUS_NSSIC(x) ((((x) & 0xf0) >> 4) + 1) + +/* + * These macros take apart the wFunctionalitySupport member. + */ +#define USB_BOS_SSPLUS_MIN_SSAI(x) ((x) & 0x0f) +#define USB_BOS_SSPLUS_MIN_RX_LANE(x) (((x) >> 8) & 0xf) +#define USB_BOS_SSPLUS_MIN_TX_LANE(x) (((x) >> 12) & 0xf) + +/* + * These macros are used to take apart the bmSublinkSpeedAttr members. There is + * always at least one of them that exist in each attribute; however, there + * could be more based on the value in NSSAC. + */ +#define USB_BOS_SSPLUS_ATTR_SSID(x) ((x) & 0xf) +#define USB_BOS_SSPLUS_ATTR_LSE(x) (((x) >> 4) & 0x3) +#define USB_BOS_SSPLUS_ATTR_LSE_BITPS 0 +#define USB_BOS_SSPLUS_ATTR_LSE_KBITPS 1 +#define USB_BOS_SSPLUS_ATTR_LSE_GBITPS 2 + +/* + * These two macros take apart the sublink type. bit 6 indicates whether or not + * the links are symmetric or asymmetric. It is asymmetric if the value is set + * to one (USB_BOS_SSPLUS_ATTR_ST_ASYM), symmetric otherwise. If it is + * asymmetric, then bit 7 indicates whether or not it's a tx or rx link. + */ +#define USB_BOS_SSPLUS_ATTR_ST_ASYM (1 << 6) +#define USB_BOS_SSPLUS_ATTR_ST_TX (1 << 7) + +#define USB_BOS_SSPLUS_ATTR_LP(x) (((x) >> 14) & 0x3) +#define USB_BOS_SSPLUS_ATTR_LP_SS 0x0 +#define USB_BOS_SSPLUS_ATTR_LP_SSPLUS 0x1 + +#define USB_BOS_SSPLUS_ATTR_LSM(x) ((x) >> 16) + +typedef struct usb_bos_precision_time { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; +} usb_bos_precision_time_t; + +#define USB_BOS_PRECISION_TIME_PACKED_SIZE 3 + +/* + * This structure serves as an internal, parsed representation of a USB bos + * descriptor. + */ +typedef struct usb_bos { + uint8_t ubos_length; + uint8_t ubos_type; + union { + usb_bos_usb2ext_t ubos_usb2; + usb_bos_ssusb_t ubos_ssusb; + usb_bos_container_t ubos_container; + usb_bos_platform_t ubos_platform; + usb_bos_ssplus_t ubos_ssplus; + usb_bos_precision_time_t ubos_time; + uint8_t ubos_raw[256]; + } ubos_caps; +} usb_bos_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_USB_BOS_H */ diff --git a/usr/src/uts/common/sys/usb/usba/usba10.h b/usr/src/uts/common/sys/usb/usba/usba10.h index 947dd65379..42e78cd35e 100644 --- a/usr/src/uts/common/sys/usb/usba/usba10.h +++ b/usr/src/uts/common/sys/usb/usba/usba10.h @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2019, Joyent, Inc. */ #ifndef _SYS_USB_USBA10_H @@ -139,7 +140,7 @@ usba10_usb_free_descr_tree( size_t usba10_usb_parse_data( char *format, - uchar_t *data, + const uchar_t *data, size_t datalen, void *structure, size_t structlen); diff --git a/usr/src/uts/common/sys/usb/usba/usba_impl.h b/usr/src/uts/common/sys/usb/usba/usba_impl.h index 784bb32d44..ddb6f7346d 100644 --- a/usr/src/uts/common/sys/usb/usba/usba_impl.h +++ b/usr/src/uts/common/sys/usb/usba/usba_impl.h @@ -23,6 +23,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> + * Copyright 2019, Joyent, Inc. */ #ifndef _SYS_USB_USBA_USBA_IMPL_H @@ -34,6 +35,7 @@ #include <sys/usb/usba/hubdi.h> #include <sys/usb/usba/usba_private.h> #include <sys/usb/usba/usba_types.h> +#include <sys/usb/usba/bos.h> #include <sys/taskq.h> #include <sys/disp.h> @@ -301,6 +303,13 @@ void usba_rem_root_hub(dev_info_t *dip); void usba_get_dev_string_descrs(dev_info_t *, usba_device_t *); /* + * Retrieve the binary object store for the device. + */ +void usba_get_binary_object_store(dev_info_t *, usba_device_t *); +void usba_add_binary_object_store_props(dev_info_t *, usba_device_t *); +void usba_free_binary_object_store(usba_device_t *); + +/* * Check if we are not in interrupt context and have * USB_FLAGS_SLEEP flags set. */ diff --git a/usr/src/uts/common/sys/usb/usba/usba_private.h b/usr/src/uts/common/sys/usb/usba/usba_private.h index 4e56e4aa47..406ee3824c 100644 --- a/usr/src/uts/common/sys/usb/usba/usba_private.h +++ b/usr/src/uts/common/sys/usb/usba/usba_private.h @@ -23,6 +23,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> + * Copyright 2019, Joyent, Inc. */ #ifndef _SYS_USB_USBA_USBA_PRIVATE_H @@ -88,21 +89,21 @@ extern "C" { * extended in a later rev of the spec. */ size_t usb_parse_dev_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(DEVICE) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(DEVICE) */ size_t buflen, usb_dev_descr_t *ret_descr, size_t ret_buf_len); size_t usb_parse_cfg_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, usb_cfg_descr_t *ret_descr, size_t ret_buf_len); size_t usb_parse_ia_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, size_t first_if, usb_ia_descr_t *ret_descr, @@ -110,7 +111,7 @@ size_t usb_parse_ia_descr( size_t usb_parse_if_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, uint_t if_index, uint_t alt_if_setting, @@ -123,7 +124,7 @@ size_t usb_parse_if_descr( * the first endpoint */ size_t usb_parse_ep_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, uint_t if_index, uint_t alt_if_setting, @@ -160,7 +161,7 @@ size_t usb_parse_ep_descr( #define USB_DESCR_TYPE_ANY -1 /* Wild card */ size_t usb_parse_CV_cfg_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, char *fmt, uint_t descr_type, @@ -170,7 +171,7 @@ size_t usb_parse_CV_cfg_descr( size_t usb_parse_CV_if_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, char *fmt, uint_t if_index, @@ -182,7 +183,7 @@ size_t usb_parse_CV_if_descr( size_t usb_parse_CV_ep_descr( - uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ + const uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ size_t buflen, char *fmt, uint_t if_index, @@ -199,7 +200,7 @@ size_t usb_parse_CV_ep_descr( */ size_t usb_parse_CV_descr( char *format, - uchar_t *data, + const uchar_t *data, size_t datalen, void *structure, size_t structlen); @@ -270,8 +271,7 @@ typedef enum usba_event { USBA_EVENT_TAG_HOT_REMOVAL = 0, USBA_EVENT_TAG_HOT_INSERTION = 1, USBA_EVENT_TAG_PRE_SUSPEND = 2, - USBA_EVENT_TAG_POST_RESUME = 3, - USBA_EVENT_TAG_CPR = -1 + USBA_EVENT_TAG_POST_RESUME = 3 } usba_event_t; #define USBA_PRE_SUSPEND_EVENT "SUNW,USBA:USBA_PRE_SUSPEND" @@ -409,11 +409,11 @@ typedef struct usba_if_pwr_descr { uint16_t TransitionTimeFromD3; /* D3 -> D0 transition time */ } usba_if_pwr_descr_t; -size_t usba_parse_cfg_pwr_descr(uchar_t *, size_t, usba_cfg_pwr_descr_t *, - size_t); +size_t usba_parse_cfg_pwr_descr(const uchar_t *, size_t, usba_cfg_pwr_descr_t *, + size_t); -size_t usba_parse_if_pwr_descr(uchar_t *, size_t buflen, uint_t, - uint_t, usba_if_pwr_descr_t *, size_t); +size_t usba_parse_if_pwr_descr(const uchar_t *, size_t buflen, uint_t, + uint_t, usba_if_pwr_descr_t *, size_t); /* * Returns (at ret_descr) a null-terminated string. Null termination is @@ -423,7 +423,7 @@ size_t usba_parse_if_pwr_descr(uchar_t *, size_t buflen, uint_t, * XXX is this needed when there is usb_get_string_descriptor * If so, then more comments about how it differs? */ -size_t usba_ascii_string_descr(uchar_t *, size_t, char *, size_t); +size_t usba_ascii_string_descr(const uchar_t *, size_t, char *, size_t); /* diff --git a/usr/src/uts/common/sys/usb/usba/usba_types.h b/usr/src/uts/common/sys/usb/usba/usba_types.h index c99a958c1a..e09bacb860 100644 --- a/usr/src/uts/common/sys/usb/usba/usba_types.h +++ b/usr/src/uts/common/sys/usb/usba/usba_types.h @@ -22,6 +22,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> + * Copyright 2019, Joyent, Inc. */ #ifndef _SYS_USB_USBA_USBA_TYPES_H @@ -31,6 +32,7 @@ #include <sys/taskq.h> #include <sys/usb/usba/usba_private.h> #include <sys/usb/usba/usbai_private.h> +#include <sys/usb/usba/bos.h> #ifdef __cplusplus extern "C" { @@ -241,7 +243,7 @@ typedef struct usb_client_dev_data_list { } usb_client_dev_data_list_t; /* - * This structure uniquely identifies a USB device + * This structure uniquely identifies a USB device * with all interfaces, or just one interface of a USB device. * usba_device is associated with a devinfo node * @@ -363,6 +365,14 @@ typedef struct usba_device { * Private data for HCD drivers */ void *usb_hcd_private; + + /* + * Binary Object Store data + */ + mblk_t *usb_bos_mp; + uint_t usb_bos_nalloc; + uint_t usb_bos_nents; + usb_bos_t *usb_bos; } usba_device_t; #define USBA_CLIENT_FLAG_SIZE 1 diff --git a/usr/src/uts/common/sys/usb/usbai.h b/usr/src/uts/common/sys/usb/usbai.h index b37d8f230f..6c90a50b81 100644 --- a/usr/src/uts/common/sys/usb/usbai.h +++ b/usr/src/uts/common/sys/usb/usbai.h @@ -23,7 +23,7 @@ * Use is subject to license terms. * * Copyright 2014 Garrett D'Amore <garrett@damore.org> - * Copyright 2016 Joyent, Inc. + * Copyright 2019 Joyent, Inc. */ #ifndef _SYS_USB_USBAI_H @@ -789,7 +789,7 @@ void usb_client_detach( size_t usb_parse_data( char *format, - uchar_t *data, + const uchar_t *data, size_t datalen, void *structure, size_t structlen); |