aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_acm.c')
-rw-r--r--drivers/usb/gadget/f_acm.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index bd6226c..0c3c3ea 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -366,6 +366,9 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
* that bit, we should return to that no-flow state.
*/
acm->port_handshake_bits = w_value;
+#ifdef CONFIG_USB_DUN_SUPPORT
+ notify_control_line_state((unsigned long)w_value);
+#endif
break;
default:
@@ -405,10 +408,10 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
usb_ep_disable(acm->notify);
} else {
VDBG(cdev, "init acm ctrl interface %d\n", intf);
- acm->notify_desc = ep_choose(cdev->gadget,
- acm->hs.notify,
- acm->fs.notify);
}
+ acm->notify_desc = ep_choose(cdev->gadget,
+ acm->hs.notify,
+ acm->fs.notify);
usb_ep_enable(acm->notify, acm->notify_desc);
acm->notify->driver_data = acm;
@@ -418,11 +421,11 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
gserial_disconnect(&acm->port);
} else {
DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
- acm->port.in_desc = ep_choose(cdev->gadget,
- acm->hs.in, acm->fs.in);
- acm->port.out_desc = ep_choose(cdev->gadget,
- acm->hs.out, acm->fs.out);
}
+ acm->port.in_desc = ep_choose(cdev->gadget,
+ acm->hs.in, acm->fs.in);
+ acm->port.out_desc = ep_choose(cdev->gadget,
+ acm->hs.out, acm->fs.out);
gserial_connect(&acm->port, acm->port_num);
} else
@@ -536,6 +539,21 @@ static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
acm_notify_serial_state(acm);
}
+#ifdef CONFIG_USB_DUN_SUPPORT
+int acm_notify(void *dev, u16 state)
+{
+ struct f_acm *acm;
+ if (dev) {
+ acm = (struct f_acm *)dev;
+ acm->serial_state = state;
+ acm_notify_serial_state(acm);
+ } else {
+ printk(KERN_DEBUG "usb: %s not ready\n", __func__);
+ return -EAGAIN;
+ }
+ return 0;
+}
+#endif
/* connect == the TTY link is open */
static void acm_connect(struct gserial *port)
@@ -669,6 +687,9 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
acm->port.in->name, acm->port.out->name,
acm->notify->name);
+#ifdef CONFIG_USB_DUN_SUPPORT
+ modem_register(acm);
+#endif
return 0;
fail:
@@ -697,7 +718,11 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
gs_free_req(acm->notify, acm->notify_req);
+ kfree(acm->port.func.name);
kfree(acm);
+#ifdef CONFIG_USB_DUN_SUPPORT
+ modem_unregister();
+#endif
}
/* Some controllers can't support CDC ACM ... */
@@ -768,7 +793,11 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
acm->port.disconnect = acm_disconnect;
acm->port.send_break = acm_send_break;
- acm->port.func.name = "acm";
+ acm->port.func.name = kasprintf(GFP_KERNEL, "acm%u", port_num);
+ if (!acm->port.func.name) {
+ kfree(acm);
+ return -ENOMEM;
+ }
acm->port.func.strings = acm_strings;
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;