[better version of the patch, passing the checkpatch.pl] Version of iuu_phoenix in the kernel is based on original version 0.5 from http://eczema.ecze.com/iuu_phoenix.html which has many problems and is pretty old. This patch apply the changes done from 0.5 to 0.9 to the last kernel version. The changes covered: - basic implementation of ioctl(), - basic implementation of iuu_set_termios(), - support for more cards. Signed-off-by: Olivier Bornet <Olivier.Bornet@xxxxxxx> --- drivers/usb/serial/iuu_phoenix.c | 116 +++++++++++++++++++++++++++++++------- 1 files changed, 95 insertions(+), 21 deletions(-) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 4473d44..f9cf24c 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -40,7 +40,7 @@ static int debug; /* * Version Information */ -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.10" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" static struct usb_device_id id_table[] = { @@ -77,10 +77,13 @@ struct iuu_private { u8 reset; /* if 1 reset is needed */ int poll; /* number of poll */ u8 *writebuf; /* buffer for writing to device */ - int writelen; /* num of byte to write to device */ + u8 writelen; /* num of byte to write to device */ u8 *buf; /* used for initialize speed */ u8 *dbgbuf; /* debug buffer */ u8 len; + u8 parity; /* 0=even 1=odd */ + u8 setline; /* 1=change request */ + }; @@ -105,6 +108,49 @@ static int iuu_alloc_buf(struct iuu_private *priv) return 0; } +static int iuu_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int mask; + struct usb_serial_port *port = tty->driver_data; + + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + switch (cmd) { + + /* could be usefull later... */ + case TCFLSH: + return 0; + + case TIOCGSERIAL: + case TCGETS: + dbg("%s TIOCGSERIAL", __func__); + mask = CLOCAL | CREAD | CS8 | B9600 | TIOCM_CTS | CSTOPB + | PARODD; + put_user(mask, &arg); + return 0; + case TIOCMBIS: + case TIOCMBIC: + case TIOCSSERIAL: + if (get_user(mask, (unsigned long *)arg)) + return -EFAULT; + dbg("%s (%d) msg = %04x", __func__, port->number, mask); + return 0; + + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return 0; + + case TCSBRK: + dbg("%s (%d) TIOBRK", __func__, port->number); + return 0; + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + + } + return -ENOIOCTLCMD; +} + static int iuu_startup(struct usb_serial *serial) { struct iuu_private *priv; @@ -651,32 +697,34 @@ static int iuu_bulk_write(struct usb_serial_port *port) unsigned long flags; int result; int i; + u8 buf_len; char *buf_ptr = port->write_urb->transfer_buffer; dbg("%s - enter", __func__); + spin_lock_irqsave(&priv->lock, flags); *buf_ptr++ = IUU_UART_ESC; *buf_ptr++ = IUU_UART_TX; *buf_ptr++ = priv->writelen; memcpy(buf_ptr, priv->writebuf, priv->writelen); + buf_len = priv->writelen ; + priv->writelen = 0; + spin_unlock_irqrestore(&priv->lock, flags); if (debug == 1) { - for (i = 0; i < priv->writelen; i++) + for (i = 0; i < buf_len; i++) sprintf(priv->dbgbuf + i*2 , "%02X", priv->writebuf[i]); - priv->dbgbuf[priv->writelen+i*2] = 0; + priv->dbgbuf[buf_len+i*2] = 0; dbg("%s - writing %i chars : %s", __func__, - priv->writelen, priv->dbgbuf); + buf_len, priv->dbgbuf); } usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, priv->writelen + 3, + port->write_urb->transfer_buffer, buf_len + 3, iuu_rxcmd, port); result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - spin_lock_irqsave(&priv->lock, flags); - priv->writelen = 0; - spin_unlock_irqrestore(&priv->lock, flags); usb_serial_port_softint(port); return result; } @@ -770,14 +818,10 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, return -ENOMEM; spin_lock_irqsave(&priv->lock, flags); - if (priv->writelen > 0) { - /* buffer already filled but not commited */ - spin_unlock_irqrestore(&priv->lock, flags); - return 0; - } + /* fill the buffer */ - memcpy(priv->writebuf, buf, count); - priv->writelen = count; + memcpy(priv->writebuf+priv->writelen, buf, count); + priv->writelen += (u8)count; spin_unlock_irqrestore(&priv->lock, flags); return count; @@ -819,7 +863,7 @@ static int iuu_uart_on(struct usb_serial_port *port) buf[0] = IUU_UART_ENABLE; buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF); buf[2] = (u8) (0x00FF & IUU_BAUD_9600); - buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN); + buf[3] = (u8) (0x0F0 & IUU_ONE_STOP_BIT) | (0x07 & IUU_PARITY_EVEN); status = bulk_immediate(port, buf, 4); if (status != IUU_OPERATION_OK) { @@ -946,6 +990,30 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, return status; } +static void iuu_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old) +{ + unsigned int cflag = tty->termios->c_cflag; + int status; + u32 actual; + dbg("%s (%d) ", __func__, port->number); + if (cflag & PARODD) { + status = iuu_uart_baud(port, + (clockmode == 2) ? 16457 : 9600 * boost / 100, + &actual, IUU_PARITY_ODD | IUU_TWO_STOP_BITS); + dbg("%s (%d) ODD", __func__, port->number); + return; + } + + if (cflag & PARENB) { + status = iuu_uart_baud(port, + (clockmode == 2) ? 16457 : 9600 * boost / 100, + &actual, IUU_PARITY_EVEN | IUU_ONE_STOP_BIT); + dbg("%s (%d) EVEN", __func__, port->number); + } + +} + static int set_control_lines(struct usb_device *dev, u8 value) { return 0; @@ -1044,13 +1112,16 @@ static int iuu_open(struct tty_struct *tty, if (tty && !priv->termios_initialized) { *(tty->termios) = tty_std_termios; tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 - | TIOCM_CTS | CSTOPB | PARENB; + | TIOCM_CTS | PARENB; + tty->termios->c_cflag &= ~(CSIZE|PARODD|CSTOPB); + tty->termios->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + tty->termios->c_oflag &= ~OPOST;; + tty->termios->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP + |INLCR|IGNCR|ICRNL|IXON); tty->termios->c_ispeed = 9600; tty->termios->c_ospeed = 9600; - tty->termios->c_lflag = 0; - tty->termios->c_oflag = 0; - tty->termios->c_iflag = 0; priv->termios_initialized = 1; + tty->low_latency = 1; priv->poll = 0; } spin_unlock_irqrestore(&priv->lock, flags); @@ -1078,6 +1149,7 @@ static int iuu_open(struct tty_struct *tty, kfree(buf); iuu_led(port, 0xF000, 0xF000, 0, 0xFF); iuu_uart_on(port); + priv->parity = IUU_PARITY_EVEN; if (boost < 100) boost = 100; switch (clockmode) { @@ -1175,6 +1247,8 @@ static struct usb_serial_driver iuu_device = { .read_bulk_callback = iuu_uart_read_callback, .tiocmget = iuu_tiocmget, .tiocmset = iuu_tiocmset, + .ioctl = iuu_ioctl, + .set_termios = iuu_set_termios, .attach = iuu_startup, .shutdown = iuu_shutdown, }; -- 1.6.2.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html