USB: g_file_storage: more code from file_storage.c moved to storage_common.c
[safe/jmp/linux-2.6] / drivers / usb / serial / pl2303.c
index 8835802..9ec1a49 100644 (file)
@@ -94,6 +94,9 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
        { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
        { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
+       { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
+       { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
+       { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
 
@@ -525,6 +528,12 @@ static void pl2303_set_termios(struct tty_struct *tty,
        int baud;
        int i;
        u8 control;
+       const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
+                                4800, 7200, 9600, 14400, 19200, 28800, 38400,
+                                57600, 115200, 230400, 460800, 614400,
+                                921600, 1228800, 2457600, 3000000, 6000000 };
+       int baud_floor, baud_ceil;
+       int k;
 
        dbg("%s -  port %d", __func__, port->number);
 
@@ -570,9 +579,39 @@ static void pl2303_set_termios(struct tty_struct *tty,
                dbg("%s - data bits = %d", __func__, buf[6]);
        }
 
+       /* For reference buf[0]:buf[3] baud rate value */
+       /* NOTE: Only the values defined in baud_sup are supported !
+        *       => if unsupported values are set, the PL2303 seems to use
+        *          9600 baud (at least my PL2303X always does)
+        */
        baud = tty_get_baud_rate(tty);
-       dbg("%s - baud = %d", __func__, baud);
+       dbg("%s - baud requested = %d", __func__, baud);
        if (baud) {
+               /* Set baudrate to nearest supported value */
+               for (k=0; k<ARRAY_SIZE(baud_sup); k++) {
+                       if (baud_sup[k] / baud) {
+                               baud_ceil = baud_sup[k];
+                               if (k==0) {
+                                       baud = baud_ceil;
+                               } else {
+                                       baud_floor = baud_sup[k-1];
+                                       if ((baud_ceil % baud)
+                                           > (baud % baud_floor))
+                                               baud = baud_floor;
+                                       else
+                                               baud = baud_ceil;
+                               }
+                               break;
+                       }
+               }
+               if (baud > 1228800) {
+                       /* type_0, type_1 only support up to 1228800 baud */
+                       if (priv->type != HX)
+                               baud = 1228800;
+                       else if (baud > 6000000)
+                               baud = 6000000;
+               }
+               dbg("%s - baud set = %d", __func__, baud);
                buf[0] = baud & 0xff;
                buf[1] = (baud >> 8) & 0xff;
                buf[2] = (baud >> 16) & 0xff;
@@ -583,8 +622,16 @@ static void pl2303_set_termios(struct tty_struct *tty,
        /* For reference buf[4]=1 is 1.5 stop bits */
        /* For reference buf[4]=2 is 2 stop bits */
        if (cflag & CSTOPB) {
-               buf[4] = 2;
-               dbg("%s - stop bits = 2", __func__);
+               /* NOTE: Comply with "real" UARTs / RS232:
+                *       use 1.5 instead of 2 stop bits with 5 data bits
+                */
+               if ((cflag & CSIZE) == CS5) {
+                       buf[4] = 1;
+                       dbg("%s - stop bits = 1.5", __func__);
+               } else {
+                       buf[4] = 2;
+                       dbg("%s - stop bits = 2", __func__);
+               }
        } else {
                buf[4] = 0;
                dbg("%s - stop bits = 1", __func__);
@@ -597,11 +644,21 @@ static void pl2303_set_termios(struct tty_struct *tty,
                /* For reference buf[5]=3 is mark parity */
                /* For reference buf[5]=4 is space parity */
                if (cflag & PARODD) {
-                       buf[5] = 1;
-                       dbg("%s - parity = odd", __func__);
+                       if (cflag & CMSPAR) {
+                               buf[5] = 3;
+                               dbg("%s - parity = mark", __func__);
+                       } else {
+                               buf[5] = 1;
+                               dbg("%s - parity = odd", __func__);
+                       }
                } else {
-                       buf[5] = 2;
-                       dbg("%s - parity = even", __func__);
+                       if (cflag & CMSPAR) {
+                               buf[5] = 4;
+                               dbg("%s - parity = space", __func__);
+                       } else {
+                               buf[5] = 2;
+                               dbg("%s - parity = even", __func__);
+                       }
                }
        } else {
                buf[5] = 0;
@@ -645,7 +702,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
                pl2303_vendor_write(0x0, 0x0, serial);
        }
 
-       /* FIXME: Need to read back resulting baud rate */
+       /* Save resulting baud rate */
        if (baud)
                tty_encode_baud_rate(tty, baud, baud);
 
@@ -689,8 +746,7 @@ static void pl2303_close(struct usb_serial_port *port)
 
 }
 
-static int pl2303_open(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct ktermios tmp_termios;
        struct usb_serial *serial = port->serial;
@@ -712,8 +768,6 @@ static int pl2303_open(struct tty_struct *tty,
        if (tty)
                pl2303_set_termios(tty, port, &tmp_termios);
 
-       /* FIXME: need to assert RTS and DTR if CRTSCTS off */
-
        dbg("%s - submitting read urb", __func__);
        port->read_urb->dev = serial->dev;
        result = usb_submit_urb(port->read_urb, GFP_KERNEL);
@@ -971,18 +1025,48 @@ exit:
                        __func__, retval);
 }
 
+static void pl2303_push_data(struct tty_struct *tty,
+               struct usb_serial_port *port, struct urb *urb,
+               u8 line_status)
+{
+       unsigned char *data = urb->transfer_buffer;
+       /* get tty_flag from status */
+       char tty_flag = TTY_NORMAL;
+       /* break takes precedence over parity, */
+       /* which takes precedence over framing errors */
+       if (line_status & UART_BREAK_ERROR)
+               tty_flag = TTY_BREAK;
+       else if (line_status & UART_PARITY_ERROR)
+               tty_flag = TTY_PARITY;
+       else if (line_status & UART_FRAME_ERROR)
+               tty_flag = TTY_FRAME;
+       dbg("%s - tty_flag = %d", __func__, tty_flag);
+
+       tty_buffer_request_room(tty, urb->actual_length + 1);
+       /* overrun is special, not associated with a char */
+       if (line_status & UART_OVERRUN_ERROR)
+               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+       if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq))
+               tty_insert_flip_string(tty, data, urb->actual_length);
+       else {
+               int i;
+               for (i = 0; i < urb->actual_length; ++i)
+                       if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
+                               tty_insert_flip_char(tty, data[i], tty_flag);
+       }
+       tty_flip_buffer_push(tty);
+}
+
 static void pl2303_read_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port =  urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
-       unsigned char *data = urb->transfer_buffer;
        unsigned long flags;
-       int i;
        int result;
        int status = urb->status;
        u8 line_status;
-       char tty_flag;
 
        dbg("%s - port %d", __func__, port->number);
 
@@ -1010,10 +1094,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        }
 
        usb_serial_debug_data(debug, &port->dev, __func__,
-                             urb->actual_length, data);
-
-       /* get tty_flag from status */
-       tty_flag = TTY_NORMAL;
+                             urb->actual_length, urb->transfer_buffer);
 
        spin_lock_irqsave(&priv->lock, flags);
        line_status = priv->line_status;
@@ -1021,26 +1102,9 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        spin_unlock_irqrestore(&priv->lock, flags);
        wake_up_interruptible(&priv->delta_msr_wait);
 
-       /* break takes precedence over parity, */
-       /* which takes precedence over framing errors */
-       if (line_status & UART_BREAK_ERROR)
-               tty_flag = TTY_BREAK;
-       else if (line_status & UART_PARITY_ERROR)
-               tty_flag = TTY_PARITY;
-       else if (line_status & UART_FRAME_ERROR)
-               tty_flag = TTY_FRAME;
-       dbg("%s - tty_flag = %d", __func__, tty_flag);
-
        tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
-               tty_buffer_request_room(tty, urb->actual_length + 1);
-               /* overrun is special, not associated with a char */
-               if (line_status & UART_OVERRUN_ERROR)
-                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-               for (i = 0; i < urb->actual_length; ++i)
-                       if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
-                               tty_insert_flip_char(tty, data[i], tty_flag);
-               tty_flip_buffer_push(tty);
+               pl2303_push_data(tty, port, urb, line_status);
        }
        tty_kref_put(tty);
        /* Schedule the next read _if_ we are still open */