From 072de836f53be56a70cecf70b43ae43b7ce17376 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 10:08:36 +0000
Subject: [PATCH] mk-rootfs.sh
---
kernel/drivers/usb/gadget/configfs.c | 249 +++++++++++++++++++++++++++++--------------------
1 files changed, 145 insertions(+), 104 deletions(-)
diff --git a/kernel/drivers/usb/gadget/configfs.c b/kernel/drivers/usb/gadget/configfs.c
index f0d8dc1..81f6808 100644
--- a/kernel/drivers/usb/gadget/configfs.c
+++ b/kernel/drivers/usb/gadget/configfs.c
@@ -16,7 +16,7 @@
#include <linux/usb/ch9.h>
#ifdef CONFIG_USB_CONFIGFS_F_ACC
-extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
+extern int acc_ctrlrequest_composite(struct usb_composite_dev *cdev,
const struct usb_ctrlrequest *ctrl);
void acc_disconnect(void);
#endif
@@ -39,8 +39,6 @@
int check_user_usb_string(const char *name,
struct usb_gadget_strings *stringtab_dev)
{
- unsigned primary_lang;
- unsigned sub_lang;
u16 num;
int ret;
@@ -48,17 +46,7 @@
if (ret)
return ret;
- primary_lang = num & 0x3ff;
- sub_lang = num >> 10;
-
- /* simple sanity check for valid langid */
- switch (primary_lang) {
- case 0:
- case 0x62 ... 0xfe:
- case 0x100 ... 0x3ff:
- return -EINVAL;
- }
- if (!sub_lang)
+ if (!usb_validate_langid(num))
return -EINVAL;
stringtab_dev->language = num;
@@ -341,6 +329,47 @@
return ret;
}
+static ssize_t gadget_dev_desc_max_speed_show(struct config_item *item,
+ char *page)
+{
+ enum usb_device_speed speed = to_gadget_info(item)->composite.max_speed;
+
+ return sprintf(page, "%s\n", usb_speed_string(speed));
+}
+
+static ssize_t gadget_dev_desc_max_speed_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct gadget_info *gi = to_gadget_info(item);
+
+ mutex_lock(&gi->lock);
+
+ /* Prevent changing of max_speed after the driver is binded */
+ if (gi->composite.gadget_driver.udc_name)
+ goto err;
+
+ if (strncmp(page, "super-speed-plus", 16) == 0)
+ gi->composite.max_speed = USB_SPEED_SUPER_PLUS;
+ else if (strncmp(page, "super-speed", 11) == 0)
+ gi->composite.max_speed = USB_SPEED_SUPER;
+ else if (strncmp(page, "high-speed", 10) == 0)
+ gi->composite.max_speed = USB_SPEED_HIGH;
+ else if (strncmp(page, "full-speed", 10) == 0)
+ gi->composite.max_speed = USB_SPEED_FULL;
+ else if (strncmp(page, "low-speed", 9) == 0)
+ gi->composite.max_speed = USB_SPEED_LOW;
+ else
+ goto err;
+
+ gi->composite.gadget_driver.max_speed = gi->composite.max_speed;
+
+ mutex_unlock(&gi->lock);
+ return len;
+err:
+ mutex_unlock(&gi->lock);
+ return -EINVAL;
+}
+
CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
@@ -350,6 +379,7 @@
CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
CONFIGFS_ATTR(gadget_dev_desc_, UDC);
+CONFIGFS_ATTR(gadget_dev_desc_, max_speed);
static struct configfs_attribute *gadget_root_attrs[] = {
&gadget_dev_desc_attr_bDeviceClass,
@@ -361,6 +391,7 @@
&gadget_dev_desc_attr_bcdDevice,
&gadget_dev_desc_attr_bcdUSB,
&gadget_dev_desc_attr_UDC,
+ &gadget_dev_desc_attr_max_speed,
NULL,
};
@@ -1408,6 +1439,10 @@
goto err_purge_funcs;
}
}
+ ret = usb_gadget_check_config(cdev->gadget);
+ if (ret)
+ goto err_purge_funcs;
+
usb_ep_autoconfig_reset(cdev->gadget);
}
if (cdev->use_os_string) {
@@ -1498,11 +1533,66 @@
usb_ep_autoconfig_reset(cdev->gadget);
spin_lock_irqsave(&gi->spinlock, flags);
cdev->gadget = NULL;
+ cdev->deactivations = 0;
+ gadget->deactivated = false;
set_gadget_data(gadget, NULL);
spin_unlock_irqrestore(&gi->spinlock, flags);
}
-#ifndef CONFIG_USB_CONFIGFS_UEVENT
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+static int android_setup(struct usb_gadget *gadget,
+ const struct usb_ctrlrequest *c)
+{
+ struct usb_composite_dev *cdev;
+ unsigned long flags;
+ struct gadget_info *gi;
+ int value = -EOPNOTSUPP;
+ struct usb_function_instance *fi;
+
+ if (!android_device)
+ return 0;
+
+ gi = dev_get_drvdata(android_device);
+ spin_lock_irqsave(&gi->spinlock, flags);
+ cdev = get_gadget_data(gadget);
+ if (!cdev || gi->unbind) {
+ spin_unlock_irqrestore(&gi->spinlock, flags);
+ return 0;
+ }
+
+ if (c->bRequest == USB_REQ_GET_DESCRIPTOR &&
+ (c->wValue >> 8) == USB_DT_CONFIG && !gi->connected) {
+ gi->connected = 1;
+ schedule_work(&gi->work);
+ }
+
+ list_for_each_entry(fi, &gi->available_func, cfs_list) {
+ if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) {
+ value = fi->f->setup(fi->f, c);
+ if (value >= 0)
+ break;
+ }
+ }
+
+#ifdef CONFIG_USB_CONFIGFS_F_ACC
+ if (value < 0)
+ value = acc_ctrlrequest_composite(cdev, c);
+#endif
+
+ if (value < 0)
+ value = composite_setup(gadget, c);
+
+ if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
+ cdev->config) {
+ schedule_work(&gi->work);
+ }
+ spin_unlock_irqrestore(&gi->spinlock, flags);
+
+ return value;
+}
+
+#else // CONFIG_USB_CONFIGFS_UEVENT
+
static int configfs_composite_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl)
{
@@ -1528,7 +1618,43 @@
return ret;
}
+#endif // CONFIG_USB_CONFIGFS_UEVENT
+
static void configfs_composite_disconnect(struct usb_gadget *gadget)
+{
+ struct usb_composite_dev *cdev;
+ struct gadget_info *gi;
+ unsigned long flags;
+
+ cdev = get_gadget_data(gadget);
+ if (!cdev)
+ return;
+
+#ifdef CONFIG_USB_CONFIGFS_F_ACC
+ /*
+ * accessory HID support can be active while the
+ * accessory function is not actually enabled,
+ * so we need to inform it when we are disconnected.
+ */
+ acc_disconnect();
+#endif
+ gi = container_of(cdev, struct gadget_info, cdev);
+ spin_lock_irqsave(&gi->spinlock, flags);
+ cdev = get_gadget_data(gadget);
+ if (!cdev || gi->unbind) {
+ spin_unlock_irqrestore(&gi->spinlock, flags);
+ return;
+ }
+
+#ifdef CONFIG_USB_CONFIGFS_UEVENT
+ gi->connected = 0;
+ schedule_work(&gi->work);
+#endif
+ composite_disconnect(gadget);
+ spin_unlock_irqrestore(&gi->spinlock, flags);
+}
+
+static void configfs_composite_reset(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev;
struct gadget_info *gi;
@@ -1546,10 +1672,9 @@
return;
}
- composite_disconnect(gadget);
+ composite_reset(gadget);
spin_unlock_irqrestore(&gi->spinlock, flags);
}
-#endif
static void configfs_composite_suspend(struct usb_gadget *gadget)
{
@@ -1595,101 +1720,17 @@
spin_unlock_irqrestore(&gi->spinlock, flags);
}
-#ifdef CONFIG_USB_CONFIGFS_UEVENT
-static int android_setup(struct usb_gadget *gadget,
- const struct usb_ctrlrequest *c)
-{
- struct usb_composite_dev *cdev;
- unsigned long flags;
- struct gadget_info *gi;
- int value = -EOPNOTSUPP;
- struct usb_function_instance *fi;
-
- if (!android_device)
- return 0;
-
- gi = dev_get_drvdata(android_device);
- spin_lock_irqsave(&gi->spinlock, flags);
- cdev = get_gadget_data(gadget);
- if (!cdev || gi->unbind) {
- spin_unlock_irqrestore(&gi->spinlock, flags);
- return 0;
- };
-
- if (c->bRequest == USB_REQ_GET_DESCRIPTOR &&
- (c->wValue >> 8) == USB_DT_CONFIG && !gi->connected) {
- gi->connected = 1;
- schedule_work(&gi->work);
- }
-
- list_for_each_entry(fi, &gi->available_func, cfs_list) {
- if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) {
- value = fi->f->setup(fi->f, c);
- if (value >= 0)
- break;
- }
- }
-
-#ifdef CONFIG_USB_CONFIGFS_F_ACC
- if (value < 0)
- value = acc_ctrlrequest(cdev, c);
-#endif
-
- if (value < 0)
- value = composite_setup(gadget, c);
-
- if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
- cdev->config) {
- schedule_work(&gi->work);
- }
- spin_unlock_irqrestore(&gi->spinlock, flags);
-
- return value;
-}
-
-static void android_disconnect(struct usb_gadget *gadget)
-{
- struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
-
- /* FIXME: There's a race between usb_gadget_udc_stop() which is likely
- * to set the gadget driver to NULL in the udc driver and this drivers
- * gadget disconnect fn which likely checks for the gadget driver to
- * be a null ptr. It happens that unbind (doing set_gadget_data(NULL))
- * is called before the gadget driver is set to NULL and the udc driver
- * calls disconnect fn which results in cdev being a null ptr.
- */
- if (cdev == NULL) {
- WARN(1, "%s: gadget driver already disconnected\n", __func__);
- return;
- }
-
- /* accessory HID support can be active while the
- accessory function is not actually enabled,
- so we need to inform it when we are disconnected.
- */
-
-#ifdef CONFIG_USB_CONFIGFS_F_ACC
- acc_disconnect();
-#endif
- gi->connected = 0;
- schedule_work(&gi->work);
- composite_disconnect(gadget);
-}
-#endif
-
static const struct usb_gadget_driver configfs_driver_template = {
.bind = configfs_composite_bind,
.unbind = configfs_composite_unbind,
+
#ifdef CONFIG_USB_CONFIGFS_UEVENT
.setup = android_setup,
- .reset = android_disconnect,
- .disconnect = android_disconnect,
#else
.setup = configfs_composite_setup,
- .reset = configfs_composite_disconnect,
- .disconnect = configfs_composite_disconnect,
#endif
+ .reset = configfs_composite_reset,
+ .disconnect = configfs_composite_disconnect,
.suspend = configfs_composite_suspend,
.resume = configfs_composite_resume,
--
Gitblit v1.6.2