SET_FEATURE request for DEBUG_MODE only worked the first time after module
initialisation. On USB host reset or cable disconnect gserial_disconnect()
clears the associations dbgp.serial->in->desc and dbgp_serial->out->desc.

Per the USB 2.0 debug device specification, SET_FEATURE with DEBUG_MODE
is to be treated as if it were a SET_CONFIGURATION request. Redo endpoint
configuration on this request.

Code has assumption that endpoint mapping remains unchanged from what was
previously returned as a GET_DESCRIPTOR DT_DEBUG response.

Signed-off-by: Kyösti Mälkki <kyosti.mal...@gmail.com>
---
 drivers/usb/gadget/legacy/dbgp.c | 39 ++++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index 1b07513..afb49ef 100644
--- a/drivers/usb/gadget/legacy/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
@@ -214,6 +214,7 @@ static void dbgp_disconnect(struct usb_gadget *gadget)
 #ifdef CONFIG_USB_G_DBGP_PRINTK
        dbgp_disable_ep();
 #else
+       dev_dbg(&dbgp.gadget->dev, "disconnected\n");
        gserial_disconnect(dbgp.serial);
 #endif
 }
@@ -237,7 +238,7 @@ static void dbgp_unbind(struct usb_gadget *gadget)
 static unsigned char tty_line;
 #endif
 
-static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
+static int dbgp_configure_endpoints(struct usb_gadget *gadget)
 {
        int stp;
 
@@ -273,19 +274,10 @@ static int __init dbgp_configure_endpoints(struct 
usb_gadget *gadget)
 
        dbgp.serial->in->desc = &i_desc;
        dbgp.serial->out->desc = &o_desc;
-
-       if (gserial_alloc_line(&tty_line)) {
-               stp = 3;
-               goto fail_3;
-       }
+#endif
 
        return 0;
 
-fail_3:
-       dbgp.o_ep->driver_data = NULL;
-#else
-       return 0;
-#endif
 fail_2:
        dbgp.i_ep->driver_data = NULL;
 fail_1:
@@ -324,10 +316,17 @@ static int __init dbgp_bind(struct usb_gadget *gadget,
                err = -ENOMEM;
                goto fail;
        }
+
+       if (gserial_alloc_line(&tty_line)) {
+               stp = 4;
+               err = -ENODEV;
+               goto fail;
+       }
 #endif
+
        err = dbgp_configure_endpoints(gadget);
        if (err < 0) {
-               stp = 4;
+               stp = 5;
                goto fail;
        }
 
@@ -379,12 +378,26 @@ static int dbgp_setup(struct usb_gadget *gadget,
                err = 0;
        } else if (request == USB_REQ_SET_FEATURE &&
                   value == USB_DEVICE_DEBUG_MODE) {
-               dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n");
 #ifdef CONFIG_USB_G_DBGP_PRINTK
                err = dbgp_enable_ep();
 #else
+               if (!(dbgp.serial->in && dbgp.serial->in->desc &&
+                       dbgp.serial->out && dbgp.serial->out->desc)) {
+                       dev_dbg(&dbgp.gadget->dev, "needs reconfiguration\n");
+                       err = dbgp_configure_endpoints(gadget);
+                       if (err < 0) {
+                               goto fail;
+                       }
+               }
+               if (dbgp.serial->in && dbgp.serial->in->desc &&
+                       dbgp.serial->out && dbgp.serial->out->desc) {
+                       dev_dbg(&dbgp.gadget->dev, "epIn %02x, epOut %02x\n",
+                               dbgp.serial->in->desc->bEndpointAddress,
+                               dbgp.serial->out->desc->bEndpointAddress);
+               }
                err = gserial_connect(dbgp.serial, tty_line);
 #endif
+               dev_dbg(&dbgp.gadget->dev, "setup: feat debug (%d)\n", err);
                if (err < 0)
                        goto fail;
        } else
-- 
1.8.1.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to