diff options
Diffstat (limited to 'drivers/usb/serial/iuu_phoenix.c')
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 102 |
1 files changed, 64 insertions, 38 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 4473d442b2aa..76a3cc327bb9 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -40,7 +40,7 @@ static int debug; | |||
40 | /* | 40 | /* |
41 | * Version Information | 41 | * Version Information |
42 | */ | 42 | */ |
43 | #define DRIVER_VERSION "v0.5" | 43 | #define DRIVER_VERSION "v0.10" |
44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" | 44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" |
45 | 45 | ||
46 | static struct usb_device_id id_table[] = { | 46 | static struct usb_device_id id_table[] = { |
@@ -70,7 +70,6 @@ static void read_rxcmd_callback(struct urb *urb); | |||
70 | struct iuu_private { | 70 | struct iuu_private { |
71 | spinlock_t lock; /* store irq state */ | 71 | spinlock_t lock; /* store irq state */ |
72 | wait_queue_head_t delta_msr_wait; | 72 | wait_queue_head_t delta_msr_wait; |
73 | u8 line_control; | ||
74 | u8 line_status; | 73 | u8 line_status; |
75 | u8 termios_initialized; | 74 | u8 termios_initialized; |
76 | int tiostatus; /* store IUART SIGNAL for tiocmget call */ | 75 | int tiostatus; /* store IUART SIGNAL for tiocmget call */ |
@@ -651,32 +650,33 @@ static int iuu_bulk_write(struct usb_serial_port *port) | |||
651 | unsigned long flags; | 650 | unsigned long flags; |
652 | int result; | 651 | int result; |
653 | int i; | 652 | int i; |
653 | int buf_len; | ||
654 | char *buf_ptr = port->write_urb->transfer_buffer; | 654 | char *buf_ptr = port->write_urb->transfer_buffer; |
655 | dbg("%s - enter", __func__); | 655 | dbg("%s - enter", __func__); |
656 | 656 | ||
657 | spin_lock_irqsave(&priv->lock, flags); | ||
657 | *buf_ptr++ = IUU_UART_ESC; | 658 | *buf_ptr++ = IUU_UART_ESC; |
658 | *buf_ptr++ = IUU_UART_TX; | 659 | *buf_ptr++ = IUU_UART_TX; |
659 | *buf_ptr++ = priv->writelen; | 660 | *buf_ptr++ = priv->writelen; |
660 | 661 | ||
661 | memcpy(buf_ptr, priv->writebuf, | 662 | memcpy(buf_ptr, priv->writebuf, priv->writelen); |
662 | priv->writelen); | 663 | buf_len = priv->writelen; |
664 | priv->writelen = 0; | ||
665 | spin_unlock_irqrestore(&priv->lock, flags); | ||
663 | if (debug == 1) { | 666 | if (debug == 1) { |
664 | for (i = 0; i < priv->writelen; i++) | 667 | for (i = 0; i < buf_len; i++) |
665 | sprintf(priv->dbgbuf + i*2 , | 668 | sprintf(priv->dbgbuf + i*2 , |
666 | "%02X", priv->writebuf[i]); | 669 | "%02X", priv->writebuf[i]); |
667 | priv->dbgbuf[priv->writelen+i*2] = 0; | 670 | priv->dbgbuf[buf_len+i*2] = 0; |
668 | dbg("%s - writing %i chars : %s", __func__, | 671 | dbg("%s - writing %i chars : %s", __func__, |
669 | priv->writelen, priv->dbgbuf); | 672 | buf_len, priv->dbgbuf); |
670 | } | 673 | } |
671 | usb_fill_bulk_urb(port->write_urb, port->serial->dev, | 674 | usb_fill_bulk_urb(port->write_urb, port->serial->dev, |
672 | usb_sndbulkpipe(port->serial->dev, | 675 | usb_sndbulkpipe(port->serial->dev, |
673 | port->bulk_out_endpointAddress), | 676 | port->bulk_out_endpointAddress), |
674 | port->write_urb->transfer_buffer, priv->writelen + 3, | 677 | port->write_urb->transfer_buffer, buf_len + 3, |
675 | iuu_rxcmd, port); | 678 | iuu_rxcmd, port); |
676 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 679 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
677 | spin_lock_irqsave(&priv->lock, flags); | ||
678 | priv->writelen = 0; | ||
679 | spin_unlock_irqrestore(&priv->lock, flags); | ||
680 | usb_serial_port_softint(port); | 680 | usb_serial_port_softint(port); |
681 | return result; | 681 | return result; |
682 | } | 682 | } |
@@ -770,14 +770,10 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
770 | return -ENOMEM; | 770 | return -ENOMEM; |
771 | 771 | ||
772 | spin_lock_irqsave(&priv->lock, flags); | 772 | spin_lock_irqsave(&priv->lock, flags); |
773 | if (priv->writelen > 0) { | 773 | |
774 | /* buffer already filled but not commited */ | ||
775 | spin_unlock_irqrestore(&priv->lock, flags); | ||
776 | return 0; | ||
777 | } | ||
778 | /* fill the buffer */ | 774 | /* fill the buffer */ |
779 | memcpy(priv->writebuf, buf, count); | 775 | memcpy(priv->writebuf + priv->writelen, buf, count); |
780 | priv->writelen = count; | 776 | priv->writelen += count; |
781 | spin_unlock_irqrestore(&priv->lock, flags); | 777 | spin_unlock_irqrestore(&priv->lock, flags); |
782 | 778 | ||
783 | return count; | 779 | return count; |
@@ -819,7 +815,7 @@ static int iuu_uart_on(struct usb_serial_port *port) | |||
819 | buf[0] = IUU_UART_ENABLE; | 815 | buf[0] = IUU_UART_ENABLE; |
820 | buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF); | 816 | buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF); |
821 | buf[2] = (u8) (0x00FF & IUU_BAUD_9600); | 817 | buf[2] = (u8) (0x00FF & IUU_BAUD_9600); |
822 | buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN); | 818 | buf[3] = (u8) (0x0F0 & IUU_ONE_STOP_BIT) | (0x07 & IUU_PARITY_EVEN); |
823 | 819 | ||
824 | status = bulk_immediate(port, buf, 4); | 820 | status = bulk_immediate(port, buf, 4); |
825 | if (status != IUU_OPERATION_OK) { | 821 | if (status != IUU_OPERATION_OK) { |
@@ -946,19 +942,59 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, | |||
946 | return status; | 942 | return status; |
947 | } | 943 | } |
948 | 944 | ||
949 | static int set_control_lines(struct usb_device *dev, u8 value) | 945 | static void iuu_set_termios(struct tty_struct *tty, |
946 | struct usb_serial_port *port, struct ktermios *old_termios) | ||
950 | { | 947 | { |
951 | return 0; | 948 | const u32 supported_mask = CMSPAR|PARENB|PARODD; |
949 | |||
950 | unsigned int cflag = tty->termios->c_cflag; | ||
951 | int status; | ||
952 | u32 actual; | ||
953 | u32 parity; | ||
954 | int csize = CS7; | ||
955 | int baud = 9600; /* Fixed for the moment */ | ||
956 | u32 newval = cflag & supported_mask; | ||
957 | |||
958 | /* compute the parity parameter */ | ||
959 | parity = 0; | ||
960 | if (cflag & CMSPAR) { /* Using mark space */ | ||
961 | if (cflag & PARODD) | ||
962 | parity |= IUU_PARITY_SPACE; | ||
963 | else | ||
964 | parity |= IUU_PARITY_MARK; | ||
965 | } else if (!(cflag & PARENB)) { | ||
966 | parity |= IUU_PARITY_NONE; | ||
967 | csize = CS8; | ||
968 | } else if (cflag & PARODD) | ||
969 | parity |= IUU_PARITY_ODD; | ||
970 | else | ||
971 | parity |= IUU_PARITY_EVEN; | ||
972 | |||
973 | parity |= (cflag & CSTOPB ? IUU_TWO_STOP_BITS : IUU_ONE_STOP_BIT); | ||
974 | |||
975 | /* set it */ | ||
976 | status = iuu_uart_baud(port, | ||
977 | (clockmode == 2) ? 16457 : 9600 * boost / 100, | ||
978 | &actual, parity); | ||
979 | |||
980 | /* set the termios value to the real one, so the user now what has | ||
981 | * changed. We support few fields so its easies to copy the old hw | ||
982 | * settings back over and then adjust them | ||
983 | */ | ||
984 | if (old_termios) | ||
985 | tty_termios_copy_hw(tty->termios, old_termios); | ||
986 | if (status != 0) /* Set failed - return old bits */ | ||
987 | return; | ||
988 | /* Re-encode speed, parity and csize */ | ||
989 | tty_encode_baud_rate(tty, baud, baud); | ||
990 | tty->termios->c_cflag &= ~(supported_mask|CSIZE); | ||
991 | tty->termios->c_cflag |= newval | csize; | ||
952 | } | 992 | } |
953 | 993 | ||
954 | static void iuu_close(struct tty_struct *tty, | 994 | static void iuu_close(struct usb_serial_port *port) |
955 | struct usb_serial_port *port, struct file *filp) | ||
956 | { | 995 | { |
957 | /* iuu_led (port,255,0,0,0); */ | 996 | /* iuu_led (port,255,0,0,0); */ |
958 | struct usb_serial *serial; | 997 | struct usb_serial *serial; |
959 | struct iuu_private *priv = usb_get_serial_port_data(port); | ||
960 | unsigned long flags; | ||
961 | unsigned int c_cflag; | ||
962 | 998 | ||
963 | serial = port->serial; | 999 | serial = port->serial; |
964 | if (!serial) | 1000 | if (!serial) |
@@ -968,17 +1004,6 @@ static void iuu_close(struct tty_struct *tty, | |||
968 | 1004 | ||
969 | iuu_uart_off(port); | 1005 | iuu_uart_off(port); |
970 | if (serial->dev) { | 1006 | if (serial->dev) { |
971 | if (tty) { | ||
972 | c_cflag = tty->termios->c_cflag; | ||
973 | if (c_cflag & HUPCL) { | ||
974 | /* drop DTR and RTS */ | ||
975 | priv = usb_get_serial_port_data(port); | ||
976 | spin_lock_irqsave(&priv->lock, flags); | ||
977 | priv->line_control = 0; | ||
978 | spin_unlock_irqrestore(&priv->lock, flags); | ||
979 | set_control_lines(port->serial->dev, 0); | ||
980 | } | ||
981 | } | ||
982 | /* free writebuf */ | 1007 | /* free writebuf */ |
983 | /* shutdown our urbs */ | 1008 | /* shutdown our urbs */ |
984 | dbg("%s - shutting down urbs", __func__); | 1009 | dbg("%s - shutting down urbs", __func__); |
@@ -1154,7 +1179,7 @@ static int iuu_open(struct tty_struct *tty, | |||
1154 | if (result) { | 1179 | if (result) { |
1155 | dev_err(&port->dev, "%s - failed submitting read urb," | 1180 | dev_err(&port->dev, "%s - failed submitting read urb," |
1156 | " error %d\n", __func__, result); | 1181 | " error %d\n", __func__, result); |
1157 | iuu_close(tty, port, NULL); | 1182 | iuu_close(port); |
1158 | return -EPROTO; | 1183 | return -EPROTO; |
1159 | } else { | 1184 | } else { |
1160 | dbg("%s - rxcmd OK", __func__); | 1185 | dbg("%s - rxcmd OK", __func__); |
@@ -1175,6 +1200,7 @@ static struct usb_serial_driver iuu_device = { | |||
1175 | .read_bulk_callback = iuu_uart_read_callback, | 1200 | .read_bulk_callback = iuu_uart_read_callback, |
1176 | .tiocmget = iuu_tiocmget, | 1201 | .tiocmget = iuu_tiocmget, |
1177 | .tiocmset = iuu_tiocmset, | 1202 | .tiocmset = iuu_tiocmset, |
1203 | .set_termios = iuu_set_termios, | ||
1178 | .attach = iuu_startup, | 1204 | .attach = iuu_startup, |
1179 | .shutdown = iuu_shutdown, | 1205 | .shutdown = iuu_shutdown, |
1180 | }; | 1206 | }; |