コード例 #1
0
static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
{
	struct usb_serial *serial = port->serial;
	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
	int result;

	if (spriv->type != HX) {
		usb_clear_halt(serial->dev, port->write_urb->pipe);
		usb_clear_halt(serial->dev, port->read_urb->pipe);
	} else {
		/* reset upstream data pipes */
		pl2303_vendor_write(8, 0, serial);
		pl2303_vendor_write(9, 0, serial);
	}

	/* Setup termios */
	if (tty)
		pl2303_set_termios(tty, port, NULL);

	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
	if (result) {
		dev_err(&port->dev, "%s - failed submitting interrupt urb,"
			" error %d\n", __func__, result);
		return result;
	}

	result = usb_serial_generic_open(tty, port);
	if (result) {
		usb_kill_urb(port->interrupt_in_urb);
		return result;
	}

	return 0;
}
コード例 #2
0
static int pl2303_startup(struct usb_serial *serial)
{
	struct pl2303_serial_private *spriv;
	enum pl2303_type type = type_0;
	unsigned char *buf;

	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
	if (!spriv)
		return -ENOMEM;

	buf = kmalloc(10, GFP_KERNEL);
	if (!buf) {
		kfree(spriv);
		return -ENOMEM;
	}

	if (serial->dev->descriptor.bDeviceClass == 0x02)
		type = type_0;
	else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
		type = HX;
	else if (serial->dev->descriptor.bDeviceClass == 0x00)
		type = type_1;
	else if (serial->dev->descriptor.bDeviceClass == 0xFF)
		type = type_1;
	dev_dbg(&serial->interface->dev, "device type: %d\n", type);

	spriv->type = type;
	usb_set_serial_data(serial, spriv);

	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_write(0x0404, 0, serial);
	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_read(0x8383, 0, serial, buf);
	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_write(0x0404, 1, serial);
	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_read(0x8383, 0, serial, buf);
	pl2303_vendor_write(0, 1, serial);
	pl2303_vendor_write(1, 0, serial);
	if (type == HX)
		pl2303_vendor_write(2, 0x44, serial);
	else
		pl2303_vendor_write(2, 0x24, serial);

	kfree(buf);
	return 0;
}
コード例 #3
0
ファイル: pl2303.c プロジェクト: IIosTaJI/linux-2.6
static int pl2303_startup(struct usb_serial *serial)
{
	struct pl2303_serial_private *spriv;
	enum pl2303_type type = type_0;
	char *type_str = "unknown (treating as type_0)";
	unsigned char *buf;

	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
	if (!spriv)
		return -ENOMEM;

	buf = kmalloc(10, GFP_KERNEL);
	if (!buf) {
		kfree(spriv);
		return -ENOMEM;
	}

	if (serial->dev->descriptor.bDeviceClass == 0x02) {
		type = type_0;
		type_str = "type_0";
	} else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) {
		/*
		 * NOTE: The bcdDevice version is the only difference between
		 * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB
		 */
		if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) {
			type = HX_TA;
			type_str = "X/HX/TA";
		} else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
								     == 0x400) {
			type = HXD_EA_RA_SA;
			type_str = "HXD/EA/RA/SA";
		} else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
								     == 0x500) {
			type = TB;
			type_str = "TB";
		} else {
			dev_info(&serial->interface->dev,
					   "unknown/unsupported device type\n");
			kfree(spriv);
			kfree(buf);
			return -ENODEV;
		}
	} else if (serial->dev->descriptor.bDeviceClass == 0x00
		   || serial->dev->descriptor.bDeviceClass == 0xFF) {
		type = type_1;
		type_str = "type_1";
	}
	dev_dbg(&serial->interface->dev, "device type: %s\n", type_str);

	spriv->type = type;
	usb_set_serial_data(serial, spriv);

	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_write(0x0404, 0, serial);
	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_read(0x8383, 0, serial, buf);
	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_write(0x0404, 1, serial);
	pl2303_vendor_read(0x8484, 0, serial, buf);
	pl2303_vendor_read(0x8383, 0, serial, buf);
	pl2303_vendor_write(0, 1, serial);
	pl2303_vendor_write(1, 0, serial);
	if (type == type_0 || type == type_1)
		pl2303_vendor_write(2, 0x24, serial);
	else
		pl2303_vendor_write(2, 0x44, serial);

	kfree(buf);
	return 0;
}
コード例 #4
0
static void pl2303_set_termios(struct tty_struct *tty,
		struct usb_serial_port *port, struct ktermios *old_termios)
{
	struct usb_serial *serial = port->serial;
	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
	struct pl2303_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	unsigned char *buf;
	int i;
	u8 control;

	if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
		return;

	buf = kzalloc(7, GFP_KERNEL);
	if (!buf) {
		dev_err(&port->dev, "%s - out of memory.\n", __func__);
		/* Report back no change occurred */
		if (old_termios)
			tty->termios = *old_termios;
		return;
	}

	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
			    0, 0, buf, 7, 100);
	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);

	switch (C_CSIZE(tty)) {
	case CS5:
		buf[6] = 5;
		break;
	case CS6:
		buf[6] = 6;
		break;
	case CS7:
		buf[6] = 7;
		break;
	default:
	case CS8:
		buf[6] = 8;
	}
	dev_dbg(&port->dev, "data bits = %d\n", buf[6]);

	/* For reference buf[0]:buf[3] baud rate value */
	pl2303_encode_baudrate(tty, port, &buf[0]);

	/* For reference buf[4]=0 is 1 stop bits */
	/* For reference buf[4]=1 is 1.5 stop bits */
	/* For reference buf[4]=2 is 2 stop bits */
	if (C_CSTOPB(tty)) {
		/*
		 * NOTE: Comply with "real" UARTs / RS232:
		 *       use 1.5 instead of 2 stop bits with 5 data bits
		 */
		if (C_CSIZE(tty) == CS5) {
			buf[4] = 1;
			dev_dbg(&port->dev, "stop bits = 1.5\n");
		} else {
			buf[4] = 2;
			dev_dbg(&port->dev, "stop bits = 2\n");
		}
	} else {
		buf[4] = 0;
		dev_dbg(&port->dev, "stop bits = 1\n");
	}

	if (C_PARENB(tty)) {
		/* For reference buf[5]=0 is none parity */
		/* For reference buf[5]=1 is odd parity */
		/* For reference buf[5]=2 is even parity */
		/* For reference buf[5]=3 is mark parity */
		/* For reference buf[5]=4 is space parity */
		if (C_PARODD(tty)) {
			if (tty->termios.c_cflag & CMSPAR) {
				buf[5] = 3;
				dev_dbg(&port->dev, "parity = mark\n");
			} else {
				buf[5] = 1;
				dev_dbg(&port->dev, "parity = odd\n");
			}
		} else {
			if (tty->termios.c_cflag & CMSPAR) {
				buf[5] = 4;
				dev_dbg(&port->dev, "parity = space\n");
			} else {
				buf[5] = 2;
				dev_dbg(&port->dev, "parity = even\n");
			}
		}
	} else {
		buf[5] = 0;
		dev_dbg(&port->dev, "parity = none\n");
	}

	/*
	 * Some PL2303 are known to lose bytes if you change serial settings
	 * even to the same values as before. Thus we actually need to filter
	 * in this specific case.
	 *
	 * Note that the tty_termios_hw_change check above is not sufficient
	 * as a previously requested baud rate may differ from the one
	 * actually used (and stored in old_termios).
	 *
	 * NOTE: No additional locking needed for line_settings as it is
	 *       only used in set_termios, which is serialised against itself.
	 */
	if (!old_termios || memcmp(buf, priv->line_settings, 7)) {
		i = usb_control_msg(serial->dev,
				    usb_sndctrlpipe(serial->dev, 0),
				    SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
				    0, 0, buf, 7, 100);

		dev_dbg(&port->dev, "0x21:0x20:0:0  %d\n", i);

		if (i == 7)
			memcpy(priv->line_settings, buf, 7);
	}

	/* change control lines if we are switching to or from B0 */
	spin_lock_irqsave(&priv->lock, flags);
	control = priv->line_control;
	if (C_BAUD(tty) == B0)
		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
	else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
	if (control != priv->line_control) {
		control = priv->line_control;
		spin_unlock_irqrestore(&priv->lock, flags);
		pl2303_set_control_lines(port, control);
	} else {
		spin_unlock_irqrestore(&priv->lock, flags);
	}

	memset(buf, 0, 7);
	i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
			    GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
			    0, 0, buf, 7, 100);
	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);

	if (C_CRTSCTS(tty)) {
		if (spriv->type == HX)
			pl2303_vendor_write(0x0, 0x61, serial);
		else
			pl2303_vendor_write(0x0, 0x41, serial);
	} else {
		pl2303_vendor_write(0x0, 0x0, serial);
	}

	kfree(buf);
}