X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fark3116.c;h=131e61adaaf72bdab5da517830ed43293eb2a69e;hb=5128a66c6605d8178f69b7a8f2a70060933a26b4;hp=77895c8f8f3189fb774acb59cad0f3f3a324cbad;hpb=28a4acb48586dc21d2d14a75a7aab7be78b7c83b;p=karo-tx-linux.git diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 77895c8f8f31..131e61adaaf7 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -31,14 +31,19 @@ static int debug; static struct usb_device_id id_table [] = { { USB_DEVICE(0x6547, 0x0232) }, + { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -struct ark3116_private { - spinlock_t lock; - u8 termios_initialized; -}; +static int is_irda(struct usb_serial *serial) +{ + struct usb_device *dev = serial->dev; + if (le16_to_cpu(dev->descriptor.idVendor) == 0x18ec && + le16_to_cpu(dev->descriptor.idProduct) == 0x3118) + return 1; + return 0; +} static inline void ARK3116_SND(struct usb_serial *serial, int seq, __u8 request, __u8 requesttype, @@ -82,29 +87,28 @@ static inline void ARK3116_RCV_QUIET(struct usb_serial *serial, static int ark3116_attach(struct usb_serial *serial) { char *buf; - struct ark3116_private *priv; - int i; - - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - - usb_set_serial_port_data(serial->port[i], priv); - } buf = kmalloc(1, GFP_KERNEL); if (!buf) { dbg("error kmalloc -> out of mem?"); - goto cleanup; + return -ENOMEM; } + if (is_irda(serial)) + dbg("IrDA mode"); + /* 3 */ ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002); ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001); ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008); - ARK3116_SND(serial, 6, 0xFE, 0x40, 0x0000, 0x000B); + ARK3116_SND(serial, 6, 0xFE, 0x40, is_irda(serial) ? 0x0001 : 0x0000, + 0x000B); + + if (is_irda(serial)) { + ARK3116_SND(serial, 1001, 0xFE, 0x40, 0x0000, 0x000C); + ARK3116_SND(serial, 1002, 0xFE, 0x40, 0x0041, 0x000D); + ARK3116_SND(serial, 1003, 0xFE, 0x40, 0x0001, 0x000A); + } /* <-- seq7 */ ARK3116_RCV(serial, 7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); @@ -141,6 +145,8 @@ static int ark3116_attach(struct usb_serial *serial) ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000); ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001); + if (is_irda(serial)) + ARK3116_SND(serial, 1004, 0xFE, 0x40, 0x0000, 0x0009); ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); @@ -149,23 +155,25 @@ static int ark3116_attach(struct usb_serial *serial) kfree(buf); return 0; +} -cleanup: - for (--i; i >= 0; --i) { - kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; +static void ark3116_init_termios(struct tty_struct *tty) +{ + struct ktermios *termios = tty->termios; + *termios = tty_std_termios; + termios->c_cflag = B9600 | CS8 + | CREAD | HUPCL | CLOCAL; + termios->c_ispeed = 9600; + termios->c_ospeed = 9600; } -static void ark3116_set_termios(struct usb_serial_port *port, +static void ark3116_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; - struct ark3116_private *priv = usb_get_serial_port_data(port); - struct ktermios *termios = port->tty->termios; + struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; - unsigned long flags; int baud; int ark3116_baud; char *buf; @@ -175,16 +183,6 @@ static void ark3116_set_termios(struct usb_serial_port *port, dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&priv->lock, flags); - if (!priv->termios_initialized) { - *(port->tty->termios) = tty_std_termios; - port->tty->termios->c_cflag = B9600 | CS8 - | CREAD | HUPCL | CLOCAL; - termios->c_ispeed = 9600; - termios->c_ospeed = 9600; - priv->termios_initialized = 1; - } - spin_unlock_irqrestore(&priv->lock, flags); cflag = termios->c_cflag; termios->c_cflag &= ~(CMSPAR|CRTSCTS); @@ -192,7 +190,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, buf = kmalloc(1, GFP_KERNEL); if (!buf) { dbg("error kmalloc"); - *port->tty->termios = *old_termios; + *termios = *old_termios; return; } @@ -243,7 +241,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, } /* set baudrate */ - baud = tty_get_baud_rate(port->tty); + baud = tty_get_baud_rate(tty); switch (baud) { case 75: @@ -262,11 +260,11 @@ static void ark3116_set_termios(struct usb_serial_port *port, case 230400: case 460800: /* Report the resulting rate back to the caller */ - tty_encode_baud_rate(port->tty, baud, baud); + tty_encode_baud_rate(tty, baud, baud); break; /* set 9600 as default (if given baudrate is invalid for example) */ default: - tty_encode_baud_rate(port->tty, 9600, 9600); + tty_encode_baud_rate(tty, 9600, 9600); case 0: baud = 9600; } @@ -317,7 +315,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, return; } -static int ark3116_open(struct usb_serial_port *port, struct file *filp) +static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; @@ -332,7 +330,7 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp) return -ENOMEM; } - result = usb_serial_generic_open(port, filp); + result = usb_serial_generic_open(tty, port); if (result) goto err_out; @@ -362,8 +360,8 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp) ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf); /* initialise termios */ - if (port->tty) - ark3116_set_termios(port, &tmp_termios); + if (tty) + ark3116_set_termios(tty, port, &tmp_termios); err_out: kfree(buf); @@ -371,9 +369,10 @@ err_out: return result; } -static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, +static int ark3116_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; @@ -403,8 +402,9 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file, return -ENOIOCTLCMD; } -static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file) +static int ark3116_tiocmget(struct tty_struct *tty, struct file *file) { + struct usb_serial_port *port = tty->driver_data; struct usb_serial *serial = port->serial; char *buf; char temp; @@ -451,6 +451,7 @@ static struct usb_serial_driver ark3116_device = { .num_ports = 1, .attach = ark3116_attach, .set_termios = ark3116_set_termios, + .init_termios = ark3116_init_termios, .ioctl = ark3116_ioctl, .tiocmget = ark3116_tiocmget, .open = ark3116_open,