Exemplo n.º 1
0
static void ch341_read_int_callback(struct urb *urb)
{
	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
	unsigned char *data = urb->transfer_buffer;
	unsigned int actual_length = urb->actual_length;
	int status;

	dbg("%s (%d)", __func__, port->number);

	switch (urb->status) {
	case 0:
		/* success */
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		/* this urb is terminated, clean up */
		dbg("%s - urb shutting down with status: %d", __func__,
		    urb->status);
		return;
	default:
		dbg("%s - nonzero urb status received: %d", __func__,
		    urb->status);
		goto exit;
	}

	usb_serial_debug_data(debug, &port->dev, __func__,
			      urb->actual_length, urb->transfer_buffer);

	if (actual_length >= 4) {
		struct ch341_private *priv = usb_get_serial_port_data(port);
		unsigned long flags;
		u8 prev_line_status = priv->line_status;

		spin_lock_irqsave(&priv->lock, flags);
		priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
		if ((data[1] & CH341_MULT_STAT))
			priv->multi_status_change = 1;
		spin_unlock_irqrestore(&priv->lock, flags);

		if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) {
			struct tty_struct *tty = tty_port_tty_get(&port->port);
			if (tty)
				usb_serial_handle_dcd_change(port, tty,
					    priv->line_status & CH341_BIT_DCD);
			tty_kref_put(tty);
		}

		wake_up_interruptible(&priv->delta_msr_wait);
	}

exit:
	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status)
		dev_err(&urb->dev->dev,
			"%s - usb_submit_urb failed with result %d\n",
			__func__, status);
}
Exemplo n.º 2
0
static void spcp8x5_process_read_urb(struct urb *urb)
{
	struct usb_serial_port *port = urb->context;
	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
	unsigned char *data = urb->transfer_buffer;
	unsigned long flags;
	u8 status;
	char tty_flag;

	/* get tty_flag from status */
	tty_flag = TTY_NORMAL;

	spin_lock_irqsave(&priv->lock, flags);
	status = priv->line_status;
	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
	spin_unlock_irqrestore(&priv->lock, flags);
	/* wake up the wait for termios */
	wake_up_interruptible(&port->delta_msr_wait);

	if (!urb->actual_length)
		return;


	if (status & UART_STATE_TRANSIENT_MASK) {
		/* break takes precedence over parity, which takes precedence
		 * over framing errors */
		if (status & UART_BREAK_ERROR)
			tty_flag = TTY_BREAK;
		else if (status & UART_PARITY_ERROR)
			tty_flag = TTY_PARITY;
		else if (status & UART_FRAME_ERROR)
			tty_flag = TTY_FRAME;
		dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);

		/* overrun is special, not associated with a char */
		if (status & UART_OVERRUN_ERROR)
			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);

		if (status & UART_DCD) {
			struct tty_struct *tty = tty_port_tty_get(&port->port);
			if (tty) {
				usb_serial_handle_dcd_change(port, tty,
				       priv->line_status & MSR_STATUS_LINE_DCD);
				tty_kref_put(tty);
			}
		}
	}

	tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
							urb->actual_length);
	tty_flip_buffer_push(&port->port);
}
Exemplo n.º 3
0
static void pl2303_update_line_status(struct usb_serial_port *port,
				      unsigned char *data,
				      unsigned int actual_length)
{

	struct pl2303_private *priv = usb_get_serial_port_data(port);
	struct tty_struct *tty;
	unsigned long flags;
	u8 status_idx = UART_STATE;
	u8 length = UART_STATE + 1;
	u8 prev_line_status;
	u16 idv, idp;

	idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
	idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);


	if (idv == SIEMENS_VENDOR_ID) {
		if (idp == SIEMENS_PRODUCT_ID_X65 ||
		    idp == SIEMENS_PRODUCT_ID_SX1 ||
		    idp == SIEMENS_PRODUCT_ID_X75) {

			length = 1;
			status_idx = 0;
		}
	}

	if (actual_length < length)
		return;

	/* Save off the uart status for others to look at */
	spin_lock_irqsave(&priv->lock, flags);
	prev_line_status = priv->line_status;
	priv->line_status = data[status_idx];
	spin_unlock_irqrestore(&priv->lock, flags);
	if (priv->line_status & UART_BREAK_ERROR)
		usb_serial_handle_break(port);
	wake_up_interruptible(&port->port.delta_msr_wait);

	tty = tty_port_tty_get(&port->port);
	if (!tty)
		return;
	if ((priv->line_status ^ prev_line_status) & UART_DCD)
		usb_serial_handle_dcd_change(port, tty,
				priv->line_status & UART_DCD);
	tty_kref_put(tty);
}
Exemplo n.º 4
0
static void ch341_update_line_status(struct usb_serial_port *port,
					unsigned char *data, size_t len)
{
	struct ch341_private *priv = usb_get_serial_port_data(port);
	struct tty_struct *tty;
	unsigned long flags;
	u8 status;
	u8 delta;

	if (len < 4)
		return;

	status = ~data[2] & CH341_BITS_MODEM_STAT;

	spin_lock_irqsave(&priv->lock, flags);
	delta = status ^ priv->line_status;
	priv->line_status = status;
	spin_unlock_irqrestore(&priv->lock, flags);

	if (data[1] & CH341_MULT_STAT)
		dev_dbg(&port->dev, "%s - multiple status change\n", __func__);

	if (!delta)
		return;

	if (delta & CH341_BIT_CTS)
		port->icount.cts++;
	if (delta & CH341_BIT_DSR)
		port->icount.dsr++;
	if (delta & CH341_BIT_RI)
		port->icount.rng++;
	if (delta & CH341_BIT_DCD) {
		port->icount.dcd++;
		tty = tty_port_tty_get(&port->port);
		if (tty) {
			usb_serial_handle_dcd_change(port, tty,
						status & CH341_BIT_DCD);
			tty_kref_put(tty);
		}
	}

	wake_up_interruptible(&port->port.delta_msr_wait);
}
Exemplo n.º 5
0
/* bulk read call back function. check the status of the urb. if transfer
 * failed return. then update the status and the tty send data to tty subsys.
 * submit urb again.
 */
static void spcp8x5_read_bulk_callback(struct urb *urb)
{
    struct usb_serial_port *port = urb->context;
    struct spcp8x5_private *priv = usb_get_serial_port_data(port);
    struct tty_struct *tty;
    unsigned char *data = urb->transfer_buffer;
    unsigned long flags;
    int result = urb->status;
    u8 status;
    char tty_flag;

    dev_dbg(&port->dev, "start, result = %d, urb->actual_length = %d\n,",
            result, urb->actual_length);

    /* check the urb status */
    if (result) {
        if (result == -EPROTO) {
            /* spcp8x5 mysteriously fails with -EPROTO */
            /* reschedule the read */
            urb->dev = port->serial->dev;
            result = usb_submit_urb(urb , GFP_ATOMIC);
            if (result)
                dev_dbg(&port->dev,
                        "failed submitting read urb %d\n",
                        result);
            return;
        }
        dev_dbg(&port->dev, "unable to handle the error, exiting.\n");
        return;
    }

    /* get tty_flag from status */
    tty_flag = TTY_NORMAL;

    spin_lock_irqsave(&priv->lock, flags);
    status = priv->line_status;
    priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
    spin_unlock_irqrestore(&priv->lock, flags);
    /* wake up the wait for termios */
    wake_up_interruptible(&priv->delta_msr_wait);

    /* break takes precedence over parity, which takes precedence over
     * framing errors */
    if (status & UART_BREAK_ERROR)
        tty_flag = TTY_BREAK;
    else if (status & UART_PARITY_ERROR)
        tty_flag = TTY_PARITY;
    else if (status & UART_FRAME_ERROR)
        tty_flag = TTY_FRAME;
    dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);

    tty = tty_port_tty_get(&port->port);
    if (tty && urb->actual_length) {
        /* overrun is special, not associated with a char */
        if (status & UART_OVERRUN_ERROR)
            tty_insert_flip_char(tty, 0, TTY_OVERRUN);
        tty_insert_flip_string_fixed_flag(tty, data, tty_flag,
                                          urb->actual_length);
        tty_flip_buffer_push(tty);
    }

    if (status & UART_DCD)
        usb_serial_handle_dcd_change(port, tty,
                                     priv->line_status & MSR_STATUS_LINE_DCD);
    tty_kref_put(tty);

    /* Schedule the next read */
    urb->dev = port->serial->dev;
    result = usb_submit_urb(urb , GFP_ATOMIC);
    if (result)
        dev_dbg(&port->dev, "failed submitting read urb %d\n", result);
}