static int eth_stop(struct net_device *net) { struct eth_dev *dev = netdev_priv(net); unsigned long flags; VDBG(dev, "%s\n", __func__); netif_stop_queue(net); DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", dev->net->stats.rx_packets, dev->net->stats.tx_packets, dev->net->stats.rx_errors, dev->net->stats.tx_errors ); /* ensure there are no more active requests */ spin_lock_irqsave(&dev->lock, flags); if (dev->port_usb) { struct gether *link = dev->port_usb; if (link->close) link->close(link); /* NOTE: we have no abort-queue primitive we could use * to cancel all pending I/O. Instead, we disable then * reenable the endpoints ... this idiom may leave toggle * wrong, but that's a self-correcting error. * * REVISIT: we *COULD* just let the transfers complete at * their own pace; the network stack can handle old packets. * For the moment we leave this here, since it works. */ usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); if (netif_carrier_ok(net)) { DBG(dev, "host still using in/out endpoints\n"); usb_ep_enable(link->in_ep, link->in); usb_ep_enable(link->out_ep, link->out); } } spin_unlock_irqrestore(&dev->lock, flags); return 0; }
void bam_data_disconnect(struct data_port *gr, u8 port_num) { struct bam_data_port *port; struct bam_data_ch_info *d; pr_debug("dev:%p port#%d\n", gr, port_num); if (port_num >= n_bam2bam_data_ports) { pr_err("invalid bam2bam portno#%d\n", port_num); return; } if (!gr) { pr_err("data port is null\n"); return; } port = bam2bam_data_ports[port_num]; if (port->port_usb && port->port_usb->in && port->port_usb->in->driver_data) { usb_ep_disable(port->port_usb->out); usb_ep_disable(port->port_usb->in); port->port_usb->in->driver_data = NULL; port->port_usb->out->driver_data = NULL; port->port_usb = 0; } d = &port->data_ch; if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) queue_work(bam_data_wq, &port->disconnect_w); else { if (usb_bam_client_ready(false)) { pr_err("%s: usb_bam_client_ready failed\n", __func__); } } }
/** * gserial_disconnect - notify TTY I/O glue that USB link is inactive * @gser: the function, on which gserial_connect() was called * Context: any (usually from irq) * * This is called to deactivate endpoints and let the TTY layer know * that the connection went inactive ... not unlike "hangup". * * On return, the state is as if gserial_connect() had never been called; * there is no active USB I/O on these endpoints. */ void gserial_disconnect(struct gserial *gser) { struct gs_port *port = gser->ioport; unsigned long flags; if (!port) return; /* tell the TTY glue not to do I/O here any more */ spin_lock_irqsave(&port->port_lock, flags); /* REVISIT as above: how best to track this? */ port->port_line_coding = gser->port_line_coding; port->port_usb = NULL; gser->ioport = NULL; if (port->port.count > 0 || port->openclose) { wake_up_interruptible(&port->drain_wait); if (port->port.tty) tty_hangup(port->port.tty); } spin_unlock_irqrestore(&port->port_lock, flags); /* disable endpoints, aborting down any active I/O */ usb_ep_disable(gser->out); usb_ep_disable(gser->in); /* finally, free any unused/unusable I/O buffers */ spin_lock_irqsave(&port->port_lock, flags); if (port->port.count == 0 && !port->openclose) kfifo_free(&port->port_write_buf); gs_free_requests(gser->out, &port->read_pool, NULL); gs_free_requests(gser->out, &port->read_queue, NULL); gs_free_requests(gser->in, &port->write_pool, NULL); port->read_allocated = port->read_started = port->write_allocated = port->write_started = 0; gs_console_disconnect(gser->in); spin_unlock_irqrestore(&port->port_lock, flags); }
void gserial_disconnect(struct gserial *gser) { struct gs_port *port = gser->ioport; unsigned long flags; if (!port) return; spin_lock_irqsave(&port->port_lock, flags); port->port_line_coding = gser->port_line_coding; port->port_usb = NULL; gser->ioport = NULL; if (port->open_count > 0 || port->openclose) { wake_up_interruptible(&port->drain_wait); if (port->port_tty) tty_hangup(port->port_tty); } spin_unlock_irqrestore(&port->port_lock, flags); usb_ep_fifo_flush(gser->out); usb_ep_fifo_flush(gser->in); usb_ep_disable(gser->out); gser->out->driver_data = NULL; usb_ep_disable(gser->in); gser->in->driver_data = NULL; spin_lock_irqsave(&port->port_lock, flags); if (port->open_count == 0 && !port->openclose) gs_buf_free(&port->port_write_buf); gs_free_requests(gser->out, &port->read_pool); gs_free_requests(gser->out, &port->read_queue); gs_free_requests(gser->in, &port->write_pool); spin_unlock_irqrestore(&port->port_lock, flags); }
static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) { int value; if (ep->driver_data) { value = usb_ep_disable(ep); if (value < 0) DBG(cdev, "disable %s --> %d\n", ep->name, value); ep->driver_data = NULL; } }
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; int rc = 0; /* we know alt == 0, so this is an activation or a reset */ #ifdef CONFIG_MODEM_SUPPORT if (intf == gser->ctrl_id) { if (gser->notify->driver_data) { DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num); usb_ep_disable(gser->notify); } if (!gser->notify->desc) { if (config_ep_by_speed(cdev->gadget, f, gser->notify)) { gser->notify->desc = NULL; return -EINVAL; } } rc = usb_ep_enable(gser->notify); if (rc) { ERROR(cdev, "can't enable %s, result %d\n", gser->notify->name, rc); return rc; } gser->notify->driver_data = gser; } else if (intf == gser->data_id) #endif { if (gser->port.in->driver_data) { DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num); gport_disconnect(gser); } if (!gser->port.in->desc || !gser->port.out->desc) { DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || config_ep_by_speed(cdev->gadget, f, gser->port.out)) { gser->port.in->desc = NULL; gser->port.out->desc = NULL; return -EINVAL; } } gport_connect(gser); gser->online = 1; } return rc; }
int gserial_connect(struct gserial *gser, u8 port_num) { struct gs_port *port; unsigned long flags; int status; if (!gs_tty_driver || port_num >= n_ports) return -ENXIO; port = ports[port_num].port; status = usb_ep_enable(gser->in, gser->in_desc); if (status < 0) return status; gser->in->driver_data = port; status = usb_ep_enable(gser->out, gser->out_desc); if (status < 0) goto fail_out; gser->out->driver_data = port; spin_lock_irqsave(&port->port_lock, flags); gser->ioport = port; port->port_usb = gser; gser->port_line_coding = port->port_line_coding; if (port->open_count) { pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); gs_start_io(port); if (gser->connect) gser->connect(gser); } else { if (gser->disconnect) gser->disconnect(gser); } spin_unlock_irqrestore(&port->port_lock, flags); return status; fail_out: usb_ep_disable(gser->in); gser->in->driver_data = NULL; return status; }
static void zero_reset_config(struct zero_dev *dev) { if (dev->config == 0) return; DBG(dev, "reset config\n"); /* just disable endpoints, forcing completion of pending i/o. * all our completion handlers free their requests in this case. */ if (dev->in_ep) { usb_ep_disable(dev->in_ep); dev->in_ep = NULL; } if (dev->out_ep) { usb_ep_disable(dev->out_ep); dev->out_ep = NULL; } dev->config = 0; del_timer(&dev->resume); }
void gsdio_disconnect(struct gserial *gser, u8 portno) { unsigned long flags; struct gsdio_port *port; if (portno >= n_ports) { pr_err("%s: invalid portno#%d\n", __func__, portno); return; } if (!gser) { pr_err("%s: gser is null\n", __func__); return; } port = ports[portno].port; /* send dtr zero to modem to notify disconnect */ port->cbits_to_modem = 0; queue_work(gsdio_wq, &port->notify_modem); spin_lock_irqsave(&port->port_lock, flags); port->port_usb = 0; port->nbytes_tomodem = 0; port->nbytes_tolaptop = 0; spin_unlock_irqrestore(&port->port_lock, flags); /* disable endpoints, aborting down any active I/O */ usb_ep_disable(gser->out); gser->out->driver_data = NULL; usb_ep_disable(gser->in); gser->in->driver_data = NULL; spin_lock_irqsave(&port->port_lock, flags); gsdio_free_requests(gser->out, &port->read_pool); gsdio_free_requests(gser->out, &port->read_queue); gsdio_free_requests(gser->in, &port->write_pool); spin_unlock_irqrestore(&port->port_lock, flags); }
int gsdio_connect(struct gserial *gser, u8 portno) { struct gsdio_port *port; int ret = 0; unsigned long flags; if (portno >= n_ports) { pr_err("%s: invalid portno#%d\n", __func__, portno); return -EINVAL; } if (!gser) { pr_err("%s: gser is null\n", __func__); return -EINVAL; } port = ports[portno].port; spin_lock_irqsave(&port->port_lock, flags); port->port_usb = gser; gser->notify_modem = gsdio_ctrl_notify_modem; spin_unlock_irqrestore(&port->port_lock, flags); ret = usb_ep_enable(gser->in, gser->in_desc); if (ret) { pr_err("%s: failed to enable in ep w/ err:%d\n", __func__, ret); port->port_usb = 0; return ret; } gser->in->driver_data = port; ret = usb_ep_enable(gser->out, gser->out_desc); if (ret) { pr_err("%s: failed to enable in ep w/ err:%d\n", __func__, ret); usb_ep_disable(gser->in); port->port_usb = 0; gser->in->driver_data = 0; return ret; } gser->out->driver_data = port; if (port->sdio_open) { pr_debug("%s: sdio is already open, start io\n", __func__); gsdio_start_io(port); if (gser->send_modem_ctrl_bits) gser->send_modem_ctrl_bits(gser, port->cbits_to_laptop); } return 0; }
static void disable_data_ep(struct bam_data_port *port) { struct bam_data_ch_info *d = &port->data_ch; if (!port->port_usb) return; if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) { port->port_usb->ipa_consumer_ep = -1; port->port_usb->ipa_producer_ep = -1; } if (port->port_usb->in && port->port_usb->in->driver_data) { /* disable endpoints */ usb_ep_disable(port->port_usb->out); usb_ep_disable(port->port_usb->in); /* * Set endless flag to false as USB Endpoint * is already disable. */ if (d->trans == USB_GADGET_XPORT_BAM2BAM || d->trans == USB_GADGET_XPORT_BAM2BAM_IPA || d->trans == USB_GADGET_XPORT_BAM) { if (d->dst_pipe_type == USB_BAM_PIPE_BAM2BAM) port->port_usb->in->endless = false; if (d->src_pipe_type == USB_BAM_PIPE_BAM2BAM) port->port_usb->out->endless = false; } port->port_usb->in->driver_data = NULL; port->port_usb->out->driver_data = NULL; port->port_usb = NULL; } }
static int set_fastboot_config(struct fastboot_dev *dev, gfp_t gfp_flags) { int result = 0; struct usb_gadget *gadget = dev->gadget; dev->in = ep_choose(gadget, &hs_source_desc, &fs_source_desc); dev->in_ep->driver_data = dev; dev->out = ep_choose(gadget, &hs_sink_desc, &fs_sink_desc); dev->out_ep->driver_data = dev; result = usb_ep_enable(dev->in_ep, dev->in); if (result != 0) { debug("enable %s --> %d\n", dev->in_ep->name, result); goto done; } result = usb_ep_enable(dev->out_ep, dev->out); if (result != 0) { debug("enable %s --> %d\n", dev->out_ep->name, result); goto done; } done: if (result == 0) result = alloc_requests(dev, 1, gfp_flags); /* on error, disable any endpoints */ if (result < 0) { (void)usb_ep_disable(dev->in_ep); (void)usb_ep_disable(dev->out_ep); dev->in = NULL; dev->out = NULL; } /* caller is responsible for cleanup on error */ return result; }
static void rockusb_disable(struct usb_function *f) { struct f_rockusb *f_rkusb = func_to_rockusb(f); usb_ep_disable(f_rkusb->out_ep); usb_ep_disable(f_rkusb->in_ep); if (f_rkusb->out_req) { free(f_rkusb->out_req->buf); usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req); f_rkusb->out_req = NULL; } if (f_rkusb->in_req) { free(f_rkusb->in_req->buf); usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req); f_rkusb->in_req = NULL; } if (f_rkusb->buf_head) { free(f_rkusb->buf_head); f_rkusb->buf_head = NULL; f_rkusb->buf = NULL; } }
static void mtp_function_disable(struct usb_function *f) { printk(KERN_DEBUG "%s(): disabled\n", __func__); g_usb_mtp_context.online = 0; g_usb_mtp_context.cancel = 1; g_usb_mtp_context.ctl_cancel = 1; g_usb_mtp_context.error = 1; usb_ep_fifo_flush(g_usb_mtp_context.bulk_in); usb_ep_fifo_flush(g_usb_mtp_context.bulk_out); usb_ep_fifo_flush(g_usb_mtp_context.intr_in); usb_ep_disable(g_usb_mtp_context.bulk_in); usb_ep_disable(g_usb_mtp_context.bulk_out); usb_ep_disable(g_usb_mtp_context.intr_in); g_usb_mtp_context.cur_read_req = 0; g_usb_mtp_context.read_buf = 0; g_usb_mtp_context.data_len = 0; /* readers may be blocked waiting for us to go online */ wake_up(&g_usb_mtp_context.rx_wq); wake_up(&g_usb_mtp_context.tx_wq); wake_up(&g_usb_mtp_context.ctl_rx_wq); wake_up(&g_usb_mtp_context.ctl_tx_wq); }
static void gser_disable(struct usb_function *f) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num); gport_disconnect(gser); #ifdef CONFIG_MODEM_SUPPORT usb_ep_fifo_flush(gser->notify); usb_ep_disable(gser->notify); #endif gser->online = 0; }
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; int rc = 0; /* we know alt == 0, so this is an activation or a reset */ #ifdef CONFIG_MODEM_SUPPORT if (gser->notify->driver_data) { DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num); usb_ep_disable(gser->notify); } gser->notify_desc = ep_choose(cdev->gadget, gser->hs.notify, gser->fs.notify); rc = usb_ep_enable(gser->notify, gser->notify_desc); if (rc) { ERROR(cdev, "can't enable %s, result %d\n", gser->notify->name, rc); return rc; } gser->notify->driver_data = gser; #endif if (gser->port.in->driver_data) { DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num); gport_disconnect(gser); } else { DBG(cdev, "activate generic data ttyGS%d\n", gser->port_num); } gser->port.in_desc = ep_choose(cdev->gadget, gser->hs.in, gser->fs.in); gser->port.out_desc = ep_choose(cdev->gadget, gser->hs.out, gser->fs.out); #ifdef FEATURE_PANTECH_MODEM_REOPEN_DELAY schedule_delayed_work(&gser->connect_work, msecs_to_jiffies(50)); #else gport_connect(gser); #endif gser->online = 1; #ifdef CONFIG_ANDROID_PANTECH_USB_MANAGER usb_interface_enum_cb(ACM_TYPE_FLAG); #endif return rc; }
static void rndis_disable(struct usb_function *f) { struct f_rndis *rndis = func_to_rndis(f); struct usb_composite_dev *cdev = f->config->cdev; if (!rndis->notify->driver_data) return; DBG(cdev, "rndis deactivated\n"); rndis_uninit(rndis->config); gether_disconnect(&rndis->port); usb_ep_disable(rndis->notify); rndis->notify->driver_data = NULL; }
static void ecm_disable(struct usb_function *f) { struct f_ecm *ecm = func_to_ecm(f); struct usb_composite_dev *cdev = f->config->cdev; DBG(cdev, "ecm deactivated\n"); if (ecm->port.in_ep->driver_data) gether_disconnect(&ecm->port); if (ecm->notify->driver_data) { usb_ep_disable(ecm->notify); ecm->notify->driver_data = NULL; ecm->notify_desc = NULL; } }
int sysfs_endpoint_disable(sysfs_endpoint* sys_ep) { int error = 0; if (!sys_ep) { return -EINVAL; } DBG(sys_ep, "%s\n", __func__); if (!sys_ep->enabled_desc) { return 0; } error = usb_ep_disable(sys_ep->ep); sys_ep->enabled_desc = 0; if (sys_ep->request) { /* This call will flag the request as "dead" if it's still in use. */ usb_ep_free_request(sys_ep->ep, sys_ep->request); } return error; }
static void acm_disable(struct usb_function *f) { struct f_acm *acm = func_to_acm(f); struct usb_composite_dev *cdev = f->config->cdev; D("+\n"); DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num); gacm_cdev_disconnect(&acm->port); if (acm->notify) { usb_ep_disable(acm->notify); acm->notify->driver_data = NULL; } bsp_usb_set_enum_stat(acm->data_id, 0); D("-\n"); }
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; /* we know alt == 0, so this is an activation or a reset */ if (intf == acm->ctrl_id) { if (acm->notify->driver_data) { VDBG(cdev, "reset acm control interface %d\n", intf); usb_ep_disable(acm->notify); } if (!acm->notify->desc) if (config_ep_by_speed(cdev->gadget, f, acm->notify)) return -EINVAL; usb_ep_enable(acm->notify); acm->notify->driver_data = acm; } else if (intf == acm->data_id) { if (acm->port.in->driver_data) { DBG(cdev, "reset acm ttyGS%d\n", acm->port_num); gserial_disconnect(&acm->port); } if (!acm->port.in->desc || !acm->port.out->desc) { DBG(cdev, "activate acm ttyGS%d\n", acm->port_num); if (config_ep_by_speed(cdev->gadget, f, acm->port.in) || config_ep_by_speed(cdev->gadget, f, acm->port.out)) { acm->port.in->desc = NULL; acm->port.out->desc = NULL; return -EINVAL; } } gserial_connect(&acm->port, acm->port_num); } else return -EINVAL; return 0; }
static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; int rc = 0; /* we know alt == 0, so this is an activation or a reset */ #ifdef CONFIG_MODEM_SUPPORT if (gser->notify->driver_data) { DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num); usb_ep_disable(gser->notify); } gser->notify_desc = ep_choose(cdev->gadget, gser->hs.notify, gser->fs.notify); rc = usb_ep_enable(gser->notify, gser->notify_desc); if (rc) { ERROR(cdev, "can't enable %s, result %d\n", gser->notify->name, rc); return rc; } gser->notify->driver_data = gser; #endif if (gser->port.in->driver_data) { DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num); gport_disconnect(gser); } else { DBG(cdev, "activate generic data ttyGS%d\n", gser->port_num); } gser->port.in_desc = ep_choose(cdev->gadget, gser->hs.in, gser->fs.in); gser->port.out_desc = ep_choose(cdev->gadget, gser->hs.out, gser->fs.out); gport_connect(gser); gser->online = 1; gserial_ports[gser->port_num].enable = gser->online; return rc; }
static int ep_release (struct inode *inode, struct file *fd) { struct ep_data *data = fd->private_data; int value; value = mutex_lock_interruptible(&data->lock); if (value < 0) return value; /* clean up if this can be reopened */ if (data->state != STATE_EP_UNBOUND) { data->state = STATE_EP_DISABLED; data->desc.bDescriptorType = 0; data->hs_desc.bDescriptorType = 0; usb_ep_disable(data->ep); } mutex_unlock(&data->lock); put_ep (data); return 0; }
static int uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) { struct uvc_device *uvc = to_uvc(f); struct v4l2_event v4l2_event; struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; int ret; INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); if (interface == uvc->control_intf) { if (alt) return -EINVAL; if (uvc->state == UVC_STATE_DISCONNECTED) { memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_CONNECT; uvc_event->speed = f->config->cdev->gadget->speed; v4l2_event_queue(uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; } return 0; } if (interface != uvc->streaming_intf) return -EINVAL; /* TODO if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep)) return alt ? -EINVAL : 0; */ switch (alt) { case 0: if (uvc->state != UVC_STATE_STREAMING) return 0; if (uvc->video.ep) usb_ep_disable(uvc->video.ep); memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMOFF; v4l2_event_queue(uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; return 0; case 1: if (uvc->state != UVC_STATE_CONNECTED) return 0; if (uvc->video.ep) { ret = config_ep_by_speed(f->config->cdev->gadget, &(uvc->func), uvc->video.ep); if (ret) return ret; usb_ep_enable(uvc->video.ep); } memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMON; v4l2_event_queue(uvc->vdev, &v4l2_event); return USB_GADGET_DELAYED_STATUS; default: return -EINVAL; } }
/** * gether_connect - notify network layer that USB link is active * @link: the USB link, set up with endpoints, descriptors matching * current device speed, and any framing wrapper(s) set up. * Context: irqs blocked * * This is called to activate endpoints and let the network layer know * the connection is active ("carrier detect"). It may cause the I/O * queues to open and start letting network packets flow, but will in * any case activate the endpoints so that they respond properly to the * USB host. * * Verify net_device pointer returned using IS_ERR(). If it doesn't * indicate some error code (negative errno), ep->driver_data values * have been overwritten. */ struct net_device *gether_connect(struct gether *link) { struct eth_dev *dev = the_dev; int result = 0; if (!dev) return ERR_PTR(-EINVAL); link->in_ep->driver_data = dev; result = usb_ep_enable(link->in_ep, link->in); if (result != 0) { DBG(dev, "enable %s --> %d\n", link->in_ep->name, result); goto fail0; } link->out_ep->driver_data = dev; result = usb_ep_enable(link->out_ep, link->out); if (result != 0) { DBG(dev, "enable %s --> %d\n", link->out_ep->name, result); goto fail1; } if (result == 0) result = alloc_requests(dev, link, qlen(dev->gadget)); if (result == 0) { dev->zlp = link->is_zlp_ok; DBG(dev, "qlen %d\n", qlen(dev->gadget)); dev->header_len = link->header_len; dev->unwrap = link->unwrap; dev->wrap = link->wrap; spin_lock(&dev->lock); dev->port_usb = link; link->ioport = dev; if (netif_running(dev->net)) { if (link->open) link->open(link); } else { if (link->close) link->close(link); } spin_unlock(&dev->lock); netif_carrier_on(dev->net); if (netif_running(dev->net)) eth_start(dev, GFP_ATOMIC); /* on error, disable any endpoints */ } else { (void) usb_ep_disable(link->out_ep); fail1: (void) usb_ep_disable(link->in_ep); } fail0: /* caller is responsible for cleanup on error */ if (result < 0) return ERR_PTR(result); return dev->net; }
static int dtf_function_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct dtf_dev *dev = func_to_dtf(f); struct usb_composite_dev *cdev = f->config->cdev; int ret; int set_alt_end = 0; int speed_check = 0; _dbgmsg("dtf_function_set_alt(intf=%d,alt=%d)\n", intf, alt); if( dev->pg.mCtrl_id == intf ) { _dbgmsg_gadget( "usb_ep_enable(%s)\n", dev->pg.ep_intr->name ); ret = config_ep_by_speed(cdev->gadget, f, dev->pg.ep_intr); if (ret) { dev->pg.ep_intr->desc = NULL; _dbgmsg("config_ep_by_speed failes for ep %s, result %d\n", dev->pg.ep_intr->name, ret); return ret; } ret = usb_ep_enable(dev->pg.ep_intr); if( ret ) { _dbgmsg( "usb_ep_enable error pg1 ep_intr ret = %d\n", ret ); return ret; } dev->mCtrl_ep_enbl = 1; } else if( dev->pg.mData_id == intf ) { _dbgmsg_gadget( "usb_ep_enable(%s)\n", dev->pg.ep_in->name ); ret = config_ep_by_speed(cdev->gadget, f, dev->pg.ep_in); if (ret) { dev->pg.ep_in->desc = NULL; _dbgmsg("config_ep_by_speed failes for ep %s, result %d\n", dev->pg.ep_in->name, ret); return ret; } ret = usb_ep_enable(dev->pg.ep_intr); if( ret ) { _dbgmsg( "usb_ep_enable error pg1 ep_in ret = %d\n", ret ); return ret; } _dbgmsg_gadget( "usb_ep_enable(%s)\n", dev->pg.ep_out->name ); ret = config_ep_by_speed(cdev->gadget, f, dev->pg.ep_out); if (ret) { dev->pg.ep_out->desc = NULL; _dbgmsg("config_ep_by_speed failes for ep %s, result %d\n", dev->pg.ep_intr->name, ret); return ret; } ret = usb_ep_enable(dev->pg.ep_out); if( ret ) { _dbgmsg( "usb_ep_enable error pg1 ep_out ret = %d\n", ret ); usb_ep_disable(dev->pg.ep_in); return ret; } dev->pg.mReq_out->length = 512; usb_ep_queue( dev->pg.ep_out, dev->pg.mReq_out, GFP_ATOMIC ); dev->mData_ep_enbl = 1; } else { _dbgmsg( "unknown interface number\n" ); } set_alt_end = ( (dev->mCtrl_ep_enbl) & (dev->mData_ep_enbl) ); speed_check = (dev->cdev->gadget->speed == USB_SPEED_HIGH)?(1):(0); if (set_alt_end == 1) { dtf_if_out_set_alt( speed_check ); } return 0; }
/** * gserial_connect - notify TTY I/O glue that USB link is active * @gser: the function, set up with endpoints and descriptors * @port_num: which port is active * Context: any (usually from irq) * * This is called activate endpoints and let the TTY layer know that * the connection is active ... not unlike "carrier detect". It won't * necessarily start I/O queues; unless the TTY is held open by any * task, there would be no point. However, the endpoints will be * activated so the USB host can perform I/O, subject to basic USB * hardware flow control. * * Caller needs to have set up the endpoints and USB function in @dev * before calling this, as well as the appropriate (speed-specific) * endpoint descriptors, and also have allocate @port_num by calling * @gserial_alloc_line(). * * Returns negative errno or zero. * On success, ep->driver_data will be overwritten. */ int gserial_connect(struct gserial *gser, u8 port_num) { struct gs_port *port; unsigned long flags; int status; if (port_num >= MAX_U_SERIAL_PORTS) return -ENXIO; port = ports[port_num].port; if (!port) { pr_err("serial line %d not allocated.\n", port_num); return -EINVAL; } if (port->port_usb) { pr_err("serial line %d is in use.\n", port_num); return -EBUSY; } /* activate the endpoints */ status = usb_ep_enable(gser->in); if (status < 0) return status; gser->in->driver_data = port; status = usb_ep_enable(gser->out); if (status < 0) goto fail_out; gser->out->driver_data = port; /* then tell the tty glue that I/O can work */ spin_lock_irqsave(&port->port_lock, flags); gser->ioport = port; port->port_usb = gser; /* REVISIT unclear how best to handle this state... * we don't really couple it with the Linux TTY. */ gser->port_line_coding = port->port_line_coding; /* REVISIT if waiting on "carrier detect", signal. */ /* if it's already open, start I/O ... and notify the serial * protocol about open/close status (connect/disconnect). */ if (port->port.count) { pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); gs_start_io(port); if (gser->connect) gser->connect(gser); } else { if (gser->disconnect) gser->disconnect(gser); } spin_unlock_irqrestore(&port->port_lock, flags); return status; fail_out: usb_ep_disable(gser->in); gser->in->driver_data = NULL; return status; }
static int bam_data_peer_reset_cb(void *param) { struct bam_data_port *port = (struct bam_data_port *)param; struct bam_data_ch_info *d; int ret; bool reenable_eps = false; d = &port->data_ch; pr_debug("%s: reset by peer\n", __func__); /* Disable the relevant EPs if currently EPs are enabled */ if (port->port_usb && port->port_usb->in && port->port_usb->in->driver_data) { usb_ep_disable(port->port_usb->out); usb_ep_disable(port->port_usb->in); port->port_usb->in->driver_data = NULL; port->port_usb->out->driver_data = NULL; reenable_eps = true; } /* Disable BAM */ msm_hw_bam_disable(1); /* Reset BAM */ ret = usb_bam_reset(); if (ret) { pr_err("%s: BAM reset failed %d\n", __func__, ret); goto reenable_eps; } /* Enable BAM */ msm_hw_bam_disable(0); reenable_eps: /* Re-Enable the relevant EPs, if EPs were originally enabled */ if (reenable_eps) { ret = usb_ep_enable(port->port_usb->in); if (ret) { pr_err("%s: usb_ep_enable failed eptype:IN ep:%p", __func__, port->port_usb->in); return ret; } port->port_usb->in->driver_data = port; ret = usb_ep_enable(port->port_usb->out); if (ret) { pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p", __func__, port->port_usb->out); port->port_usb->in->driver_data = 0; return ret; } port->port_usb->out->driver_data = port; bam_data_start_endless_rx(port); bam_data_start_endless_tx(port); } /* Unregister the peer reset callback */ usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL); return 0; }
/** * gether_disconnect - notify network layer that USB link is inactive * @link: the USB link, on which gether_connect() was called * Context: irqs blocked * * This is called to deactivate endpoints and let the network layer know * the connection went inactive ("no carrier"). * * On return, the state is as if gether_connect() had never been called. * The endpoints are inactive, and accordingly without active USB I/O. * Pointers to endpoint descriptors and endpoint private data are nulled. */ void gether_disconnect(struct gether *link) { struct eth_dev *dev = link->ioport; struct usb_request *req; if (!dev) return; DBG(dev, "%s\n", __func__); netif_stop_queue(dev->net); netif_carrier_off(dev->net); /* disable endpoints, forcing (synchronous) completion * of all pending i/o. then free the request objects * and forget about the endpoints. */ usb_ep_disable(link->in_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->tx_reqs)) { req = container_of(dev->tx_reqs.next, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); usb_ep_free_request(link->in_ep, req); spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); #ifndef CONFIG_USB_GADGET_DYNAMIC_ENDPOINT link->in_ep->driver_data = NULL; #endif link->in = NULL; usb_ep_disable(link->out_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->rx_reqs)) { req = container_of(dev->rx_reqs.next, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); usb_ep_free_request(link->out_ep, req); spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); #ifndef CONFIG_USB_GADGET_DYNAMIC_ENDPOINT link->out_ep->driver_data = NULL; #endif link->out = NULL; /* finish forgetting about this USB link episode */ dev->header_len = 0; dev->unwrap = NULL; dev->wrap = NULL; spin_lock(&dev->lock); dev->port_usb = NULL; link->ioport = NULL; spin_unlock(&dev->lock); }
/** * gserial_connect - notify TTY I/O glue that USB link is active * @gser: the function, set up with endpoints and descriptors * @port_num: which port is active * Context: any (usually from irq) * * This is called activate endpoints and let the TTY layer know that * the connection is active ... not unlike "carrier detect". It won't * necessarily start I/O queues; unless the TTY is held open by any * task, there would be no point. However, the endpoints will be * activated so the USB host can perform I/O, subject to basic USB * hardware flow control. * * Caller needs to have set up the endpoints and USB function in @dev * before calling this, as well as the appropriate (speed-specific) * endpoint descriptors, and also have set up the TTY driver by calling * @gserial_setup(). * * Returns negative errno or zero. * On success, ep->driver_data will be overwritten. */ int gserial_connect(struct gserial *gser, u8 port_num) { struct gs_port *port; unsigned long flags; int status; if (!gs_tty_driver || port_num >= n_ports) return -ENXIO; /* we "know" gserial_cleanup() hasn't been called */ port = ports[port_num].port; /* activate the endpoints */ status = usb_ep_enable(gser->in, gser->in_desc); if (status < 0) return status; gser->in->driver_data = port; status = usb_ep_enable(gser->out, gser->out_desc); if (status < 0) goto fail_out; gser->out->driver_data = port; /* then tell the tty glue that I/O can work */ spin_lock_irqsave(&port->port_lock, flags); gser->ioport = port; port->port_usb = gser; /* REVISIT unclear how best to handle this state... * we don't really couple it with the Linux TTY. */ gser->port_line_coding = port->port_line_coding; /* REVISIT if waiting on "carrier detect", signal. */ /* if it's already open, start I/O ... and notify the serial * protocol about open/close status (connect/disconnect). */ if (port->open_count) { pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); gs_start_io(port); if (gser->connect) gser->connect(gser); } else { if (gser->disconnect) gser->disconnect(gser); } #ifdef CONFIG_USB_ANDROID_SH_SERIALS if (port->port_usb) status = gs_start_tx(port); #endif /* CONFIG_USB_ANDROID_SH_SERIALS */ spin_unlock_irqrestore(&port->port_lock, flags); return status; fail_out: usb_ep_disable(gser->in); gser->in->driver_data = NULL; return status; }