summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/Makefile.files2
-rw-r--r--usr/src/uts/common/io/usb/usba/genconsole.c33
-rw-r--r--usr/src/uts/common/io/usb/usba/hubdi.c26
-rw-r--r--usr/src/uts/common/io/usb/usba/parser.c145
-rw-r--r--usr/src/uts/common/io/usb/usba/usba.c17
-rw-r--r--usr/src/uts/common/io/usb/usba/usba10_calls.c3
-rw-r--r--usr/src/uts/common/io/usb/usba/usba_bos.c420
-rw-r--r--usr/src/uts/common/io/usb/usba/usba_devdb.c5
-rw-r--r--usr/src/uts/common/io/usb/usba/usba_ugen.c12
-rw-r--r--usr/src/uts/common/io/usb/usba/usbai.c19
-rw-r--r--usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c4
-rw-r--r--usr/src/uts/common/io/usb/usba/usbai_register.c7
-rw-r--r--usr/src/uts/common/io/usb/usba/usbai_req.c7
-rw-r--r--usr/src/uts/common/io/usb/usba/usbai_util.c7
-rw-r--r--usr/src/uts/common/io/usb/usba10/usba10.c3
-rw-r--r--usr/src/uts/common/sys/usb/usba/bos.h242
-rw-r--r--usr/src/uts/common/sys/usb/usba/usba10.h3
-rw-r--r--usr/src/uts/common/sys/usb/usba/usba_impl.h9
-rw-r--r--usr/src/uts/common/sys/usb/usba/usba_private.h32
-rw-r--r--usr/src/uts/common/sys/usb/usba/usba_types.h12
-rw-r--r--usr/src/uts/common/sys/usb/usbai.h4
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);