WORKAROUND: usb: gadget: f_acm: Add dummy mode 02/249002/2
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Fri, 4 Dec 2020 06:09:30 +0000 (15:09 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Mon, 7 Dec 2020 03:09:06 +0000 (12:09 +0900)
With amlogic dwc2, only fixed bytes for fifo can be used because
it is set as 2848 bytes in sram. But Tizen default usb gadget mode
enables mtp, acm, and sdb, and for those interfaces, 3104 bytes
are required. Disabling acm gadget causes usb mode setting fail in
Tizen deviced, so add acm gadget dummy mode which enables acm
gadget in configuration, but not really using any endpoint fifo.

Note: once gadget mode is properly fixed, this change will not be
necessary, so it will be reverted after gadget mode modification
is done in deviced.

Change-Id: I6148a714520642050133b6c32bce666971869826
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/usb/gadget/Kconfig
drivers/usb/gadget/function/f_acm.c

index f6cce5a..45e3cc3 100644 (file)
@@ -149,6 +149,14 @@ config USB_LIBCOMPOSITE
 config USB_F_ACM
        tristate
 
+config USB_F_ACM_DUMMY
+       bool "ACM gadget dummy mode"
+       default n
+       depends on USB_F_ACM
+       help
+          to disable acm as dummy even with acm config, enable this option.
+          If unsure, say N.
+
 config USB_F_SS_LB
        tristate
 
index 5e3828d..b923d71 100644 (file)
@@ -346,6 +346,10 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
        u16                     w_value = le16_to_cpu(ctrl->wValue);
        u16                     w_length = le16_to_cpu(ctrl->wLength);
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return 0;
+#endif
+
        /* composite driver infrastructure handles everything except
         * CDC class messages; interface activation uses set_alt().
         *
@@ -425,6 +429,9 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        struct f_acm            *acm = func_to_acm(f);
        struct usb_composite_dev *cdev = f->config->cdev;
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return 0;
+#endif
        /* we know alt == 0, so this is an activation or a reset */
 
        if (intf == acm->ctrl_id) {
@@ -469,6 +476,10 @@ static void acm_disable(struct usb_function *f)
        struct f_acm    *acm = func_to_acm(f);
        struct usb_composite_dev *cdev = f->config->cdev;
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return;
+#endif
+
        dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n", acm->port_num);
        gserial_disconnect(&acm->port);
        usb_ep_disable(acm->notify);
@@ -576,6 +587,10 @@ static void acm_connect(struct gserial *port)
 {
        struct f_acm            *acm = port_to_acm(port);
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return;
+#endif
+
        acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
        acm_notify_serial_state(acm);
 }
@@ -584,6 +599,9 @@ static void acm_disconnect(struct gserial *port)
 {
        struct f_acm            *acm = port_to_acm(port);
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return;
+#endif
        acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
        acm_notify_serial_state(acm);
 }
@@ -593,6 +611,9 @@ static int acm_send_break(struct gserial *port, int duration)
        struct f_acm            *acm = port_to_acm(port);
        u16                     state;
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return 0;
+#endif
        state = acm->serial_state;
        state &= ~ACM_CTRL_BRK;
        if (duration)
@@ -614,6 +635,9 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
        int                     status;
        struct usb_ep           *ep;
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return 0;
+#endif
        /* REVISIT might want instance-specific strings to help
         * distinguish instances ...
         */
@@ -713,6 +737,10 @@ static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_acm            *acm = func_to_acm(f);
 
+#ifdef CONFIG_USB_F_ACM_DUMMY
+       return;
+#endif
+
        acm_string_defs[0].id = 0;
        usb_free_all_descriptors(f);
        if (acm->notify_req)
@@ -786,7 +814,7 @@ static struct configfs_attribute *acm_attrs[] = {
        NULL,
 };
 
-static struct config_item_type acm_func_type = {
+static __maybe_unused struct config_item_type acm_func_type = {
        .ct_item_ops    = &acm_item_ops,
        .ct_attrs       = acm_attrs,
        .ct_owner       = THIS_MODULE,
@@ -797,24 +825,28 @@ static void acm_free_instance(struct usb_function_instance *fi)
        struct f_serial_opts *opts;
 
        opts = container_of(fi, struct f_serial_opts, func_inst);
+#ifndef CONFIG_USB_F_ACM_DUMMY
        gserial_free_line(opts->port_num);
+#endif
        kfree(opts);
 }
 
 static struct usb_function_instance *acm_alloc_instance(void)
 {
        struct f_serial_opts *opts;
-       int ret;
+       __maybe_unused int ret;
 
        opts = kzalloc(sizeof(*opts), GFP_KERNEL);
        if (!opts)
                return ERR_PTR(-ENOMEM);
        opts->func_inst.free_func_inst = acm_free_instance;
+#ifndef CONFIG_USB_F_ACM_DUMMY
        ret = gserial_alloc_line(&opts->port_num);
        if (ret) {
                kfree(opts);
                return ERR_PTR(ret);
        }
+#endif
        config_group_init_type_name(&opts->func_inst.group, "",
                        &acm_func_type);
        return &opts->func_inst;