Ejemplo n.º 1
0
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
{
	struct acm *acm = container_of(port, struct acm, port);
	int retval = -ENODEV;

	dev_dbg(&acm->control->dev, "%s\n", __func__);

	mutex_lock(&acm->mutex);
	if (acm->disconnected)
		goto disconnected;

	retval = usb_autopm_get_interface(acm->control);
	if (retval)
		goto error_get_interface;

	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
	acm->control->needs_remote_wakeup = 1;

	acm->ctrlurb->dev = acm->dev;
	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
		dev_err(&acm->control->dev,
			"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
		goto error_submit_urb;
	}

	acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
	if (acm_set_control(acm, acm->ctrlout) < 0 &&
	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
		goto error_set_control;

	usb_autopm_put_interface(acm->control);

	spin_lock_irq(&acm->read_lock);
	acm->throttled = 0;
	acm->throttle_req = 0;
	spin_unlock_irq(&acm->read_lock);

	if (acm_submit_read_urbs(acm, GFP_KERNEL))
		goto error_submit_read_urbs;

	mutex_unlock(&acm->mutex);

	return 0;

error_submit_read_urbs:
	acm->ctrlout = 0;
	acm_set_control(acm, acm->ctrlout);
error_set_control:
	usb_kill_urb(acm->ctrlurb);
error_submit_urb:
	usb_autopm_put_interface(acm->control);
error_get_interface:
disconnected:
	mutex_unlock(&acm->mutex);
	return retval;
}
Ejemplo n.º 2
0
static void acm_tty_unthrottle(struct tty_struct *tty)
{
	struct acm *acm = tty->driver_data;
	unsigned int was_throttled;

	spin_lock_irq(&acm->read_lock);
	was_throttled = acm->throttled;
	acm->throttled = 0;
	acm->throttle_req = 0;
	spin_unlock_irq(&acm->read_lock);

	if (was_throttled)
		acm_submit_read_urbs(acm, GFP_KERNEL);
}
Ejemplo n.º 3
0
static int acm_resume(struct usb_interface *intf)
{
	struct acm *acm = usb_get_intfdata(intf);
	struct acm_wb *wb;
	int rv = 0;
	int cnt;

	spin_lock_irq(&acm->read_lock);
	acm->susp_count -= 1;
	cnt = acm->susp_count;
	spin_unlock_irq(&acm->read_lock);

	if (cnt)
		return 0;

	mutex_lock(&acm->mutex);
	if (acm->port.count) {
		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);

		spin_lock_irq(&acm->write_lock);
		if (acm->delayed_wb) {
			wb = acm->delayed_wb;
			acm->delayed_wb = NULL;
			spin_unlock_irq(&acm->write_lock);
			acm_start_wb(acm, wb);
		} else {
			spin_unlock_irq(&acm->write_lock);
		}

		/*
		 * delayed error checking because we must
		 * do the write path at all cost
		 */
		if (rv < 0)
			goto err_out;

		rv = acm_submit_read_urbs(acm, GFP_NOIO);
	}

err_out:
	mutex_unlock(&acm->mutex);
	return rv;
}
Ejemplo n.º 4
0
static int acm_resume(struct usb_interface *intf)
{
	struct acm *acm = usb_get_intfdata(intf);
	struct urb *urb;
	int rv = 0;

	mutex_lock(&acm->mutex);
	spin_lock_irq(&acm->read_lock);
	spin_lock(&acm->write_lock);

	if (--acm->susp_count)
		goto out;

	if (acm->port.count) {
		rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC);

		for (;;) {
			urb = usb_get_from_anchor(&acm->delayed);
			if (!urb)
				break;

			acm_start_wb(acm, urb->context);
		}

		/*
		 * delayed error checking because we must
		 * do the write path at all cost
		 */
		if (rv < 0)
			goto out;

		rv = acm_submit_read_urbs(acm, GFP_ATOMIC);
	}
out:
	spin_unlock(&acm->write_lock);
	spin_unlock_irq(&acm->read_lock);
	mutex_unlock(&acm->mutex);

	return rv;
}
Ejemplo n.º 5
0
static int acm_resume(struct usb_interface *intf)
{
	struct acm *acm = usb_get_intfdata(intf);
	struct acm_wb *wb;
	int rv = 0;
	int cnt;

	spin_lock_irq(&acm->read_lock);
	acm->susp_count -= 1;
	cnt = acm->susp_count;
	spin_unlock_irq(&acm->read_lock);

	if (cnt)
		return 0;

	if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);

		spin_lock_irq(&acm->write_lock);
		if (acm->delayed_wb) {
			wb = acm->delayed_wb;
			acm->delayed_wb = NULL;
			spin_unlock_irq(&acm->write_lock);
			acm_start_wb(acm, wb);
		} else {
			spin_unlock_irq(&acm->write_lock);
		}

		if (rv < 0)
			goto err_out;

		rv = acm_submit_read_urbs(acm, GFP_NOIO);
	}

err_out:
	return rv;
}
Ejemplo n.º 6
0
static int acm_tty_open(struct tty_struct *tty, struct file *filp)
{
	struct acm *acm;
	int rv = -ENODEV;

	mutex_lock(&open_mutex);

	acm = acm_table[tty->index];
	if (!acm || !acm->dev)
		goto out;
	else
		rv = 0;

	dev_dbg(&acm->control->dev, "%s\n", __func__);

	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);

	tty->driver_data = acm;
	tty_port_tty_set(&acm->port, tty);

	if (usb_autopm_get_interface(acm->control) < 0)
		goto early_bail;
	else
		acm->control->needs_remote_wakeup = 1;

	mutex_lock(&acm->mutex);
	if (acm->port.count++) {
		mutex_unlock(&acm->mutex);
		usb_autopm_put_interface(acm->control);
		goto out;
	}

	acm->ctrlurb->dev = acm->dev;
	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
		dev_err(&acm->control->dev,
			"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
		goto bail_out;
	}

	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
		goto bail_out;

	usb_autopm_put_interface(acm->control);

	/*
	 * Unthrottle device in case the TTY was closed while throttled.
	 */
	spin_lock_irq(&acm->read_lock);
	acm->throttled = 0;
	acm->throttle_req = 0;
	spin_unlock_irq(&acm->read_lock);

	if (acm_submit_read_urbs(acm, GFP_KERNEL))
		goto bail_out;

	set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
	rv = tty_port_block_til_ready(&acm->port, tty, filp);

	mutex_unlock(&acm->mutex);
out:
	mutex_unlock(&open_mutex);
	return rv;

bail_out:
	acm->port.count--;
	mutex_unlock(&acm->mutex);
	usb_autopm_put_interface(acm->control);
early_bail:
	mutex_unlock(&open_mutex);
	tty_port_tty_set(&acm->port, NULL);
	return -EIO;
}
Ejemplo n.º 7
0
static int acm_tty_open(struct tty_struct *tty, struct file *filp)
{
	struct acm *acm;
	int rv = -ENODEV;

	mutex_lock(&open_mutex);

	acm = acm_table[tty->index];
	if (!acm || !acm->dev)
		goto out;
	else
		rv = 0;

	dev_dbg(&acm->control->dev, "%s\n", __func__);

	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);

	tty->driver_data = acm;
	tty_port_tty_set(&acm->port, tty);

	if (usb_autopm_get_interface(acm->control) < 0)
		goto early_bail;
	else
		acm->control->needs_remote_wakeup = 0;

	mutex_lock(&acm->mutex);
	if (acm->port.count++) {
		mutex_unlock(&acm->mutex);
		usb_autopm_put_interface(acm->control);
		goto out;
	}

	if (acm_submit_read_urbs(acm, GFP_KERNEL))
		goto bail_out;

	acm->ctrlurb->dev = acm->dev;
	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
		dev_err(&acm->control->dev,
			"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
		goto bail_out;
	}

	if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) &&
	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
		goto bail_out;

	// enorcar
	acm->state &= ~ACM_ABS_IDLE;
	if (0 > acm_set_comm_feature(acm, ACM_ABSTRACT_STATE, &acm->state) &&
	    (acm->ctrl_caps & USB_CDC_COMM_FEATURE))
		goto bail_out;

	usb_autopm_put_interface(acm->control);

	set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
	rv = tty_port_block_til_ready(&acm->port, tty, filp);

	mutex_unlock(&acm->mutex);
out:
	mutex_unlock(&open_mutex);
	return rv;

bail_out:
	acm->port.count--;
	mutex_unlock(&acm->mutex);
	usb_autopm_put_interface(acm->control);
early_bail:
	mutex_unlock(&open_mutex);
	tty_port_tty_set(&acm->port, NULL);
	return -EIO;
}
Ejemplo n.º 8
0
static int acm_resume(struct usb_interface *intf)
{
	struct acm *acm = usb_get_intfdata(intf);
	int rv = 0;
	int cnt;
#ifdef CONFIG_PM
	struct urb *res;
#else
	struct acm_wb *wb;
#endif

	if (!acm) {
		pr_err("%s: !acm\n", __func__);
		return -ENODEV;
	}

	spin_lock_irq(&acm->read_lock);
	if (acm->susp_count > 0) {
		acm->susp_count -= 1;
		cnt = acm->susp_count;
	} else {
		spin_unlock_irq(&acm->read_lock);
		return 0;
	}
	spin_unlock_irq(&acm->read_lock);

	if (cnt)
		return 0;


	mutex_lock(&acm->mutex);

	if (acm->port.count) {
		rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
		spin_lock_irq(&acm->write_lock);
#ifdef CONFIG_PM
		while ((res = usb_get_from_anchor(&acm->deferred))) {
			/* decrement ref count*/
			usb_put_urb(res);
			rv = usb_submit_urb(res, GFP_ATOMIC);
			if (rv < 0) {
				dbg("usb_submit_urb(pending request)"
					" failed: %d", rv);
				usb_unanchor_urb(res);
				acm_write_done(acm, res->context);
			}
		}
		spin_unlock_irq(&acm->write_lock);
#else
		if (acm->delayed_wb) {
			wb = acm->delayed_wb;
			acm->delayed_wb = NULL;
			spin_unlock_irq(&acm->write_lock);
			acm_start_wb(acm, wb);
		} else {
			spin_unlock_irq(&acm->write_lock);
		}
#endif

		/*
		 * delayed error checking because we must
		 * do the write path at all cost
		 */
		if (rv < 0)
			goto err_out;

		rv = acm_submit_read_urbs(acm, GFP_NOIO);
	}

err_out:
	mutex_unlock(&acm->mutex);
	return rv;
}
Ejemplo n.º 9
0
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
{
	struct acm *acm = container_of(port, struct acm, port);
	int retval = -ENODEV;
	int i;

	dev_dbg(&acm->control->dev, "%s\n", __func__);

	mutex_lock(&acm->mutex);
	if (acm->disconnected)
		goto disconnected;

	retval = usb_autopm_get_interface(acm->control);
	if (retval)
		goto error_get_interface;

	/*
	 * FIXME: Why do we need this? Allocating 64K of physically contiguous
	 * memory is really nasty...
	 */
	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
	acm->control->needs_remote_wakeup = 1;

	acm->ctrlurb->dev = acm->dev;
	if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
		dev_err(&acm->control->dev,
			"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
		goto error_submit_urb;
	}

	acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
	if (acm_set_control(acm, acm->ctrlout) < 0 &&
	    (acm->ctrl_caps & USB_CDC_CAP_LINE))
		goto error_set_control;

	usb_autopm_put_interface(acm->control);

	/*
	 * Unthrottle device in case the TTY was closed while throttled.
	 */
	spin_lock_irq(&acm->read_lock);
	acm->throttled = 0;
	acm->throttle_req = 0;
	spin_unlock_irq(&acm->read_lock);

	if (acm_submit_read_urbs(acm, GFP_KERNEL))
		goto error_submit_read_urbs;

	mutex_unlock(&acm->mutex);

	return 0;

error_submit_read_urbs:
	for (i = 0; i < acm->rx_buflimit; i++)
		usb_kill_urb(acm->read_urbs[i]);
	acm->ctrlout = 0;
	acm_set_control(acm, acm->ctrlout);
error_set_control:
	usb_kill_urb(acm->ctrlurb);
error_submit_urb:
	usb_autopm_put_interface(acm->control);
error_get_interface:
disconnected:
	mutex_unlock(&acm->mutex);
	return retval;
}