From 23fa18eaa71266feff7ba8d83022d9e1cc83c65a Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:42:03 +0000
Subject: [PATCH] disable pwm7

---
 kernel/drivers/usb/core/generic.c |  113 +++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/kernel/drivers/usb/core/generic.c b/kernel/drivers/usb/core/generic.c
index 761073d..26f9fb9 100644
--- a/kernel/drivers/usb/core/generic.c
+++ b/kernel/drivers/usb/core/generic.c
@@ -21,6 +21,7 @@
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <uapi/linux/usb/audio.h>
 #include "usb.h"
 
 static inline const char *plural(int n)
@@ -42,34 +43,14 @@
 		&& desc->bInterfaceProtocol == 1;
 }
 
-static int get_usb_audio_config(struct usb_host_bos *bos)
+static bool is_audio(struct usb_interface_descriptor *desc)
 {
-	unsigned int desc_cnt, num_cfg_desc, len = 0;
-	unsigned char *buffer;
-	struct usb_config_summary_descriptor *conf_summary;
+	return desc->bInterfaceClass == USB_CLASS_AUDIO;
+}
 
-	if (!bos || !bos->config_summary)
-		goto done;
-
-	num_cfg_desc = bos->num_config_summary_desc;
-	conf_summary = bos->config_summary;
-	buffer = (unsigned char *)conf_summary;
-	for (desc_cnt = 0; desc_cnt < num_cfg_desc; desc_cnt++) {
-		conf_summary =
-			(struct usb_config_summary_descriptor *)(buffer + len);
-
-		len += conf_summary->bLength;
-
-		if (conf_summary->bcdVersion != USB_CONFIG_SUMMARY_DESC_REV ||
-				conf_summary->bClass != USB_CLASS_AUDIO)
-			continue;
-
-		/* return 1st config as per device preference */
-		return conf_summary->bConfigurationIndex[0];
-	}
-
-done:
-	return -EINVAL;
+static bool is_uac3_config(struct usb_interface_descriptor *desc)
+{
+	return desc->bInterfaceProtocol == UAC_VERSION_3;
 }
 
 int usb_choose_configuration(struct usb_device *udev)
@@ -137,6 +118,31 @@
 			continue;
 		}
 
+		/*
+		 * Select first configuration as default for audio so that
+		 * devices that don't comply with UAC3 protocol are supported.
+		 * But, still iterate through other configurations and
+		 * select UAC3 compliant config if present.
+		 */
+		if (desc && is_audio(desc)) {
+			/* Always prefer the first found UAC3 config */
+			if (is_uac3_config(desc)) {
+				best = c;
+				break;
+			}
+
+			/* If there is no UAC3 config, prefer the first config */
+			else if (i == 0)
+				best = c;
+
+			/* Unconditional continue, because the rest of the code
+			 * in the loop is irrelevant for audio devices, and
+			 * because it can reassign best, which for audio devices
+			 * we don't want.
+			 */
+			continue;
+		}
+
 		/* When the first config's first interface is one of Microsoft's
 		 * pet nonstandard Ethernet-over-USB protocols, ignore it unless
 		 * this kernel has enabled the necessary host side driver.
@@ -175,10 +181,7 @@
 			insufficient_power, plural(insufficient_power));
 
 	if (best) {
-		/* choose device preferred config */
-		i = get_usb_audio_config(udev->bos);
-		if (i < 0)
-			i = best->desc.bConfigurationValue;
+		i = best->desc.bConfigurationValue;
 		dev_dbg(&udev->dev,
 			"configuration #%d chosen from %d choice%s\n",
 			i, num_configs, plural(num_configs));
@@ -192,7 +195,35 @@
 }
 EXPORT_SYMBOL_GPL(usb_choose_configuration);
 
-static int generic_probe(struct usb_device *udev)
+static int __check_for_non_generic_match(struct device_driver *drv, void *data)
+{
+	struct usb_device *udev = data;
+	struct usb_device_driver *udrv;
+
+	if (!is_usb_device_driver(drv))
+		return 0;
+	udrv = to_usb_device_driver(drv);
+	if (udrv == &usb_generic_driver)
+		return 0;
+	return usb_driver_applicable(udev, udrv);
+}
+
+static bool usb_generic_driver_match(struct usb_device *udev)
+{
+	if (udev->use_generic_driver)
+		return true;
+
+	/*
+	 * If any other driver wants the device, leave the device to this other
+	 * driver.
+	 */
+	if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_for_non_generic_match))
+		return false;
+
+	return true;
+}
+
+int usb_generic_driver_probe(struct usb_device *udev)
 {
 	int err, c;
 
@@ -219,7 +250,7 @@
 	return 0;
 }
 
-static void generic_disconnect(struct usb_device *udev)
+void usb_generic_driver_disconnect(struct usb_device *udev)
 {
 	usb_notify_remove_device(udev);
 
@@ -231,7 +262,7 @@
 
 #ifdef	CONFIG_PM
 
-static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+int usb_generic_driver_suspend(struct usb_device *udev, pm_message_t msg)
 {
 	int rc;
 
@@ -254,10 +285,12 @@
 	else
 		rc = usb_port_suspend(udev, msg);
 
+	if (rc == 0)
+		usbfs_notify_suspend(udev);
 	return rc;
 }
 
-static int generic_resume(struct usb_device *udev, pm_message_t msg)
+int usb_generic_driver_resume(struct usb_device *udev, pm_message_t msg)
 {
 	int rc;
 
@@ -270,6 +303,9 @@
 		rc = hcd_bus_resume(udev, msg);
 	else
 		rc = usb_port_resume(udev, msg);
+
+	if (rc == 0)
+		usbfs_notify_resume(udev);
 	return rc;
 }
 
@@ -277,11 +313,12 @@
 
 struct usb_device_driver usb_generic_driver = {
 	.name =	"usb",
-	.probe = generic_probe,
-	.disconnect = generic_disconnect,
+	.match = usb_generic_driver_match,
+	.probe = usb_generic_driver_probe,
+	.disconnect = usb_generic_driver_disconnect,
 #ifdef	CONFIG_PM
-	.suspend = generic_suspend,
-	.resume = generic_resume,
+	.suspend = usb_generic_driver_suspend,
+	.resume = usb_generic_driver_resume,
 #endif
 	.supports_autosuspend = 1,
 };

--
Gitblit v1.6.2