git: f3d75bed5475 - stable/12 - MFC r368659 and r368664: Improve handling of alternate settings in the USB stack.

Hans Petter Selasky hselasky at FreeBSD.org
Mon Dec 28 13:05:56 UTC 2020


The branch stable/12 has been updated by hselasky:

URL: https://cgit.FreeBSD.org/src/commit/?id=f3d75bed5475b15f21edf4052665b1212b548bd0

commit f3d75bed5475b15f21edf4052665b1212b548bd0
Author:     Hans Petter Selasky <hselasky at FreeBSD.org>
AuthorDate: 2020-12-15 12:05:07 +0000
Commit:     Hans Petter Selasky <hselasky at FreeBSD.org>
CommitDate: 2020-12-28 13:04:56 +0000

    MFC r368659 and r368664:
    Improve handling of alternate settings in the USB stack.
    
    Allow setting the alternate interface number to fail when there is only
    one alternate setting present, to comply with the USB specification.
    
    Refactor how iface->num_altsetting is computed.
    
    Bump the __FreeBSD_version due to change of core USB structure.
    
    PR:             251856
    Submitted by:   Ma, Horse <Shichun.Ma at dell.com>
    Sponsored by:   Mellanox Technologies // NVIDIA Networking
---
 sys/compat/linuxkpi/common/src/linux_usb.c |  5 -----
 sys/dev/usb/usb_device.c                   |  6 +++++-
 sys/dev/usb/usb_request.c                  | 15 +++++++++++++--
 sys/dev/usb/usbdi.h                        |  4 +++-
 sys/sys/param.h                            |  2 +-
 5 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_usb.c b/sys/compat/linuxkpi/common/src/linux_usb.c
index abef31e20a07..1875bbfa5e11 100644
--- a/sys/compat/linuxkpi/common/src/linux_usb.c
+++ b/sys/compat/linuxkpi/common/src/linux_usb.c
@@ -937,17 +937,12 @@ usb_linux_create_usb_device(struct usb_device *udev, device_t dev)
 					if (p_ui) {
 						p_ui->altsetting = p_uhi - 1;
 						p_ui->cur_altsetting = p_uhi - 1;
-						p_ui->num_altsetting = 1;
 						p_ui->bsd_iface_index = iface_index;
 						p_ui->linux_udev = udev;
 						p_ui++;
 					}
 					iface_no_curr = iface_no;
 					iface_index++;
-				} else {
-					if (p_ui) {
-						(p_ui - 1)->num_altsetting++;
-					}
 				}
 				break;
 
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index ba49bef533c5..d6e4c0663aff 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
@@ -900,6 +900,9 @@ usb_config_parse(struct usb_device *udev, uint8_t iface_index, uint8_t cmd)
 				/* initialise interface */
 				do_init = 1;
 			}
+			/* update number of alternate settings, if any */
+			if (iface_index == USB_IFACE_INDEX_ANY)
+				iface->num_altsetting = ips.iface_index_alt + 1;
 		} else
 			do_init = 0;
 
@@ -908,6 +911,7 @@ usb_config_parse(struct usb_device *udev, uint8_t iface_index, uint8_t cmd)
 			/* update current number of endpoints */
 			ep_curr = ep_max;
 		}
+
 		/* 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 e0475efeb081..13117c0b9c77 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
@@ -1439,6 +1439,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);
@@ -1450,7 +1451,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 8d4ed43a132f..885a19fcfbe2 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -175,6 +175,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;
 
@@ -184,7 +187,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;
 };
 
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 857274424f6c..1473009481e0 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -60,7 +60,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1202504	/* Master, propagated to newvers */
+#define __FreeBSD_version 1202505	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,


More information about the dev-commits-src-all mailing list