aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2020-12-15 12:05:07 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2020-12-15 12:05:07 +0000
commitb8b3f4fdc31fb21b54f5f3104e318e1c342cb2d9 (patch)
tree1f5c014aeb2abb8fcb9e40518cbfe85b257e92fd /sys/dev/usb
parent6da5df470099fc55f20b03ef364af730e7be4ffe (diff)
Notes
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/usb_device.c6
-rw-r--r--sys/dev/usb/usb_request.c15
-rw-r--r--sys/dev/usb/usbdi.h4
3 files changed, 21 insertions, 4 deletions
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 3499516c91e6c..cc679611a832b 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2020 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -905,6 +905,10 @@ usb_config_parse(struct usb_device *udev, uint8_t iface_index, uint8_t cmd)
/* update current number of endpoints */
ep_curr = ep_max;
}
+ /* update number of alternate settings, if any */
+ if (iface_index == USB_IFACE_INDEX_ANY)
+ iface->num_altsetting = ips.iface_index_alt + 1;
+
/* check for init */
if (do_init) {
/* setup the USB interface structure */
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index 36c6a28124c59..a1781f3589a44 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
* Copyright (c) 1998 Lennart Augustsson. All rights reserved.
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2020 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1436,6 +1436,7 @@ usbd_req_set_alt_interface_no(struct usb_device *udev, struct mtx *mtx,
{
struct usb_interface *iface = usbd_get_iface(udev, iface_index);
struct usb_device_request req;
+ usb_error_t err;
if ((iface == NULL) || (iface->idesc == NULL))
return (USB_ERR_INVAL);
@@ -1447,7 +1448,17 @@ usbd_req_set_alt_interface_no(struct usb_device *udev, struct mtx *mtx,
req.wIndex[0] = iface->idesc->bInterfaceNumber;
req.wIndex[1] = 0;
USETW(req.wLength, 0);
- return (usbd_do_request(udev, mtx, &req, 0));
+ err = usbd_do_request(udev, mtx, &req, 0);
+ if (err == USB_ERR_STALLED && iface->num_altsetting == 1) {
+ /*
+ * The USB specification chapter 9.4.10 says that USB
+ * devices having only one alternate setting are
+ * allowed to STALL this request. Ignore this failure.
+ */
+ err = 0;
+ DPRINTF("Setting default alternate number failed. (ignored)\n");
+ }
+ return (err);
}
/*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index a8ba5408f5c4d..1b3b4af5f7170 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -174,6 +174,9 @@ struct usb_endpoint {
struct usb_interface {
struct usb_interface_descriptor *idesc;
device_t subdev;
+ /* Total number of alternate settings, from 1 to 256 */
+ uint16_t num_altsetting;
+ /* Current alternate interface index, from 0 to 255 */
uint8_t alt_index;
uint8_t parent_iface_index;
@@ -183,7 +186,6 @@ struct usb_interface {
struct usb_device *linux_udev;
void *bsd_priv_sc; /* device specific information */
char *pnpinfo; /* additional PnP-info for this interface */
- uint8_t num_altsetting; /* number of alternate settings */
uint8_t bsd_iface_index;
};