From 4d8eb154872af75c0f86860d41cd2cb5407a509d Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 26 Jun 2018 16:17:46 +0530 Subject: [PATCH 1/2] usb: gadget: Mark notify_modem as NULL on usb_cser_disconnect On some targets, f_serial switches transport path from char_bridge to TTY in DUN+SoftAP scenario. As a part of that, we call usb_cser_disconnect but notify_modem callback is still marked as usb_cser_notify_modem. Then on getting a SETUP req from host PC, usb_cser_notify_modem is called which can lead to NULL pointer dereference because port_usb is NULL. Fix this by marking notify_modem callback as NULL on usb_cser_disconnect. Change-Id: I4470030cde6f38b905f7a88e16ed9f261a8954d6 Signed-off-by: Ajay Agarwal Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/gadget/function/f_cdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 31ec75fed944..0e300b12979e 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -1556,8 +1556,10 @@ int usb_cser_connect(struct f_cdev *port) void usb_cser_disconnect(struct f_cdev *port) { + struct cserial *cser; unsigned long flags; + cser = &port->port_usb; usb_cser_stop_io(port); /* lower DTR to modem */ @@ -1565,6 +1567,7 @@ void usb_cser_disconnect(struct f_cdev *port) spin_lock_irqsave(&port->port_lock, flags); port->is_connected = false; + cser->notify_modem = NULL; port->nbytes_from_host = port->nbytes_to_host = 0; port->nbytes_to_port_bridge = 0; spin_unlock_irqrestore(&port->port_lock, flags); From 5fa858f5d45b9fd198c0bf804aa522fdafb4e5ba Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Tue, 26 Jun 2018 16:38:08 +0530 Subject: [PATCH 2/2] usb: gadget: Send BRK signal to host on flow disable ioctl Currently in f_cdev driver, we are not handling the TIOCM_CTS signal generared by SIO_IOCTL_INBOUND_FLOW IOCTL. Hence we are not able to send BRK signal to the host and it keeps sending data leading to data loss. Fix this by handling TIOCM_CTS in the driver. Change-Id: If8e4774e3e0772cb7189f3400d7e53e258b7d5a3 Signed-off-by: Ajay Agarwal Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/gadget/function/f_cdev.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 0e300b12979e..767b107216a0 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -1382,6 +1382,9 @@ static int f_cdev_tiocmget(struct f_cdev *port) if (cser->serial_state & TIOCM_DSR) result |= TIOCM_DSR; + + if (cser->serial_state & TIOCM_CTS) + result |= TIOCM_CTS; return result; } @@ -1428,6 +1431,18 @@ static int f_cdev_tiocmset(struct f_cdev *port, if (clear & TIOCM_DSR) cser->serial_state &= ~TIOCM_DSR; + if (set & TIOCM_CTS) { + if (cser->send_break) { + cser->serial_state |= TIOCM_CTS; + status = cser->send_break(cser, 0); + } + } + if (clear & TIOCM_CTS) { + if (cser->send_break) { + cser->serial_state &= ~TIOCM_CTS; + status = cser->send_break(cser, 1); + } + } return status; }