Ejemplo n.º 1
0
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__);
        }
    }
}
Ejemplo n.º 3
0
/**
 * 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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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;
	}
}
Ejemplo n.º 6
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 (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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
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;
	}
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
	}
}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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;
	}
}
Ejemplo n.º 19
0
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");
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
0
Archivo: f_uvc.c Proyecto: 7799/linux
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;
	}
}
Ejemplo n.º 25
0
/**
 * 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;
}
Ejemplo n.º 26
0
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;
}
Ejemplo n.º 27
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;
}
Ejemplo n.º 28
0
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;
}
Ejemplo n.º 29
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);
}
Ejemplo n.º 30
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 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;
}