This patch directly ports pl2303's tty functions to their Serial Core
version. Those function are:

   pl2303_open()        -> pl2303_startup()
   pl2303_close()       -> pl2303_shutdown()
   pl2303_write()       -> pl2303_start_tx()
   pl2303_break_ctl()   -> pl2303_break()
   pl2303_tiocmget()    -> pl2303_get_mctrl()
   pl2303_tiocmset()    -> pl2303_set_mctrl()
   pl2303_set_termios() -> pl2303_set_termios()

 Do note that:

  1. Serial Core's set_mctrl() method is called in atomic context, thus we
     can't call the pl2303's original set_control_lines() method (because it
     sleeps).

     Then an atomic version of set_control_lines() was created. It's called
     set_control_lines_atomic(), and its callback is
     set_control_lines_urb_callback().

  2. The new pl2303's set_termios() can (still) sleep. Serial Core's
     documentation says that that method must not sleep, but I couldn't find
     where in the Serial Core code it's called in atomic context. So, is this
     still true? Isn't the Serial Core's documentation out of date?

  3. As the shutdown() method should not disable RTS nor DTR, the code which
     does it in pl2303_shutdown() has been removed

 Additionaly, this patch also does the following (minor) changes:

  1. Introduces the struct pl2303_uart_ops

  2. Kills unnecessary members of the struct pl2303_device

  3. Some error and debug messages have been enhanced/added

Signed-off-by: Luiz Fernando N. Capitulino <[EMAIL PROTECTED]>
---
 drivers/usb/serial/pl2303.c |  448 +++++++++++++++++++++++++------------------
 1 files changed, 262 insertions(+), 186 deletions(-)

diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 0b60c04..f59892a 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -127,24 +127,23 @@ #define UART_OVERRUN_ERROR                0x40
 #define UART_CTS                       0x80
 
 /* function prototypes for a PL2303 serial converter */
-static int pl2303_open (struct usb_serial_port *port, struct file *filp);
-static void pl2303_close (struct usb_serial_port *port, struct file *filp);
-static void pl2303_set_termios (struct usb_serial_port *port,
-                               struct termios *old);
+static void pl2303_set_mctrl(struct uart_port *port, unsigned int mctrl);
+static unsigned int pl2303_get_mctrl(struct uart_port *port);
+static void pl2303_start_tx(struct uart_port *port);
 static int pl2303_ioctl (struct usb_serial_port *port, struct file *file,
                         unsigned int cmd, unsigned long arg);
+static void pl2303_break(struct uart_port *port, int break_state);
+static void pl2303_set_termios(struct uart_port *port,
+                              struct termios *termios,
+                              struct termios *old_termios);
+static int pl2303_startup(struct uart_port *port);
+static void pl2303_shutdown(struct uart_port *port);
 static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs);
 static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
 static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static int pl2303_write (struct usb_serial_port *port,
-                        const unsigned char *buf, int count);
 static void pl2303_send (struct usb_serial_port *port);
 static int pl2303_write_room(struct usb_serial_port *port);
 static int pl2303_chars_in_buffer(struct usb_serial_port *port);
-static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-                           unsigned int set, unsigned int clear);
 static int pl2303_attach(struct usb_serial *serial);
 static void pl2303_usb_shutdown(struct usb_serial *serial);
 static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
@@ -157,6 +156,15 @@ static unsigned int pl2303_buf_put(struc
 static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
        unsigned int count);
 
+static struct uart_ops pl2303_uart_ops = {
+       .set_mctrl    = pl2303_set_mctrl,
+       .get_mctrl    = pl2303_get_mctrl,
+       .start_tx     = pl2303_start_tx,
+       .break_ctl    = pl2303_break,
+       .startup      = pl2303_startup,
+       .shutdown     = pl2303_shutdown,
+       .set_termios  = pl2303_set_termios,
+};
 
 /* All of the device info needed for the PL2303 SIO serial converter */
 static struct usb_serial_driver pl2303_device = {
@@ -169,14 +177,8 @@ static struct usb_serial_driver pl2303_d
        .num_bulk_in =          1,
        .num_bulk_out =         1,
        .num_ports =            1,
-       .open =                 pl2303_open,
-       .close =                pl2303_close,
-       .write =                pl2303_write,
+       .uart_ops  =            &pl2303_uart_ops,
        .ioctl =                pl2303_ioctl,
-       .break_ctl =            pl2303_break_ctl,
-       .set_termios =          pl2303_set_termios,
-       .tiocmget =             pl2303_tiocmget,
-       .tiocmset =             pl2303_tiocmset,
        .read_bulk_callback =   pl2303_read_bulk_callback,
        .read_int_callback =    pl2303_read_int_callback,
        .write_bulk_callback =  pl2303_write_bulk_callback,
@@ -196,10 +198,8 @@ struct pl2303_private {
        spinlock_t lock;
        struct pl2303_buf *buf;
        int write_urb_in_use;
-       wait_queue_head_t delta_msr_wait;
        u8 line_control;
        u8 line_status;
-       u8 termios_initialized;
        enum pl2303_type type;
        struct kref kref;
 };
@@ -258,34 +258,85 @@ cleanup:
        return -ENOMEM;
 }
 
-static int set_control_lines (struct usb_device *dev, u8 value)
+static void set_control_lines_urb_callback(struct urb *urb,
+                                          struct pt_regs *regs)
 {
-       int retval;
-       
-       retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0),
-                                 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
-                                 value, 0, NULL, 0, 100);
-       dbg("value = %d, retval = %d", value, retval);
-       return retval;
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+
+       dbg("%d", port->number);
+
+       kfree(urb->setup_packet);
+
+       switch (urb->status) {
+       case 0:
+               port->uart_port.icount.tx += urb->actual_length;
+               dbg("URB transfered with success");
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("urb shutting down with status: %d", urb->status);
+               break;
+       default:
+               dev_err(&urb->dev->dev, "nonzero urb status received: %d",
+                       urb->status);
+               break;
+       }
 }
 
-static int pl2303_write (struct usb_serial_port *port,  const unsigned char 
*buf, int count)
+static void set_control_lines_atomic(struct usb_serial_port *port,
+                                    struct usb_device *dev, __u16 value)
 {
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
+       struct usb_ctrlrequest *cmd;
+       struct urb *urb;
+       int ret;
 
-       dbg("port %d, %d bytes", port->number, count);
+       dbg("port %d", port->uart_port.line);
 
-       if (!count)
-               return count;
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(&dev->dev, "%s: Could not allocate urb\n",
+                       __FUNCTION__);
+               return;
+       }
 
-       spin_lock_irqsave(&priv->lock, flags);
-       count = pl2303_buf_put(priv->buf, buf, count);
-       spin_unlock_irqrestore(&priv->lock, flags);
+       cmd = kzalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+       if (!cmd) {
+               dev_err(&dev->dev, "%s: Could not allocate cmd\n",
+                       __FUNCTION__);
+               goto exit;
+       }
 
-       pl2303_send(port);
+       cmd->bRequestType = SET_CONTROL_REQUEST_TYPE;
+       cmd->bRequest     = SET_CONTROL_REQUEST;
+       cmd->wValue       = cpu_to_le16p(&value);
 
-       return count;
+       usb_fill_control_urb(urb, dev, usb_sndctrlpipe(dev, 0),
+                            (unsigned char *)cmd, NULL, 0,
+                            set_control_lines_urb_callback, (void *)port);
+
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret) {
+               dev_err(&dev->dev, "%s: URB submit failed: %d\n",
+                       __FUNCTION__, ret);
+               kfree(cmd);
+       }
+
+exit:
+       /* Last holder will free it */
+       usb_free_urb(urb);
+}
+
+static int set_control_lines (struct usb_device *dev, u8 value)
+{
+       int retval;
+       
+       retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0),
+                                 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
+                                 value, 0, NULL, 0, 100);
+       dbg("value = %d, retval = %d", value, retval);
+       return retval;
 }
 
 static void pl2303_send(struct usb_serial_port *port)
@@ -294,7 +345,7 @@ static void pl2303_send(struct usb_seria
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       dbg("port %d", port->number);
+       dbg("port %d", port->uart_port.line);
 
        spin_lock_irqsave(&priv->lock, flags);
 
@@ -329,42 +380,34 @@ static void pl2303_send(struct usb_seria
        schedule_work(&port->work);
 }
 
-static int pl2303_write_room(struct usb_serial_port *port)
-{
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       int room = 0;
-       unsigned long flags;
-
-       dbg("port %d", port->number);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       room = pl2303_buf_space_avail(priv->buf);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       dbg("returns %d", room);
-       return room;
-}
-
-static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+static void pl2303_break(struct uart_port *port, int break_state)
 {
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       int chars = 0;
-       unsigned long flags;
+       struct usb_serial *serial = USBSERIAL_PORT->serial;
+       u16 state;
+       int result;
 
-       dbg("port %d", port->number);
+       dbg("port %d", port->line);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       chars = pl2303_buf_data_avail(priv->buf);
-       spin_unlock_irqrestore(&priv->lock, flags);
+       if (break_state == 0)
+               state = BREAK_OFF;
+       else
+               state = BREAK_ON;
+       dbg("turning break %s", state==BREAK_OFF ? "off" : "on");
 
-       dbg("returns %d", chars);
-       return chars;
+       result = usb_control_msg(serial->dev,
+                                usb_sndctrlpipe(serial->dev, 0),
+                                BREAK_REQUEST, BREAK_REQUEST_TYPE,
+                                state, 0, NULL, 0, 100);
+       if (result)
+               err("error sending break = %d", result);
 }
 
-static void pl2303_set_termios (struct usb_serial_port *port, struct termios 
*old_termios)
+static void pl2303_set_termios(struct uart_port *port,
+                              struct termios *termios,
+                              struct termios *old_termios)
 {
-       struct usb_serial *serial = port->serial;
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = USBSERIAL_PORT->serial;
+       struct pl2303_private *priv;
        unsigned long flags;
        unsigned int cflag;
        unsigned char *buf;
@@ -372,44 +415,23 @@ static void pl2303_set_termios (struct u
        int i;
        u8 control;
 
-       dbg("port %d", port->number);
+       dbg("port %d", port->line);
 
-       if ((!port->tty) || (!port->tty->termios)) {
-               dbg("no tty structures");
-               return;
-       }
-
-       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;
-               priv->termios_initialized = 1;
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       cflag = port->tty->termios->c_cflag;
-       /* check that they really want us to change something */
-       if (old_termios) {
-               if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == 
RELEVANT_IFLAG(old_termios->c_iflag))) {
-                   dbg("nothing to change...");
-                   return;
-               }
-       }
+       priv = usb_get_serial_port_data(USBSERIAL_PORT);
+       cflag = termios->c_cflag;
 
        buf = kzalloc (7, GFP_KERNEL);
        if (!buf) {
-               dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+               dev_err(&USBSERIAL_PORT->dev, "%s - out of memory.\n", 
__FUNCTION__);
                return;
        }
-       
+
        i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
                             GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
                             0, 0, buf, 7, 100);
        dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
-
        if (cflag & CSIZE) {
                switch (cflag & CSIZE) {
                        case CS5:       buf[6] = 5;     break;
@@ -440,7 +462,7 @@ static void pl2303_set_termios (struct u
                case B230400:   baud = 230400;  break;
                case B460800:   baud = 460800;  break;
                default:
-                       dev_err(&port->dev, "pl2303 driver does not support the 
baudrate requested (fix it)\n");
+                       dev_err(&USBSERIAL_PORT->dev, "pl2303 driver does not 
support the baudrate requested (fix it)\n");
                        break;
        }
        dbg("baud = %d", baud);
@@ -525,24 +547,29 @@ static void pl2303_set_termios (struct u
        kfree (buf);
 }
 
-static int pl2303_open (struct usb_serial_port *port, struct file *filp)
+static int pl2303_startup(struct uart_port *port)
 {
-       struct termios tmp_termios;
-       struct usb_serial *serial = port->serial;
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = USBSERIAL_PORT->serial;
+       struct usb_serial_port *usp = USBSERIAL_PORT;
+       struct pl2303_private *priv;
        unsigned char *buf;
        int result;
 
-       dbg("port %d", port->number);
+       dbg("port %d", port->line);
+
+       priv = usb_get_serial_port_data(usp);
+       kref_get(&priv->kref);
 
        if (priv->type != HX) {
-               usb_clear_halt(serial->dev, port->write_urb->pipe);
-               usb_clear_halt(serial->dev, port->read_urb->pipe);
+               usb_clear_halt(serial->dev, usp->write_urb->pipe);
+               usb_clear_halt(serial->dev, usp->read_urb->pipe);
        }
 
        buf = kmalloc(10, GFP_KERNEL);
-       if (buf==NULL)
-               return -ENOMEM;
+       if (buf==NULL) {
+               result = -ENOMEM;
+               goto exit_err;
+       }
 
 #define FISH(a,b,c,d)                                                          
\
        result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),     
\
@@ -577,62 +604,62 @@ #define SOUP(a,b,c,d)                                     
                        \
 
        kfree(buf);
 
-       /* Setup termios */
-       if (port->tty) {
-               pl2303_set_termios (port, &tmp_termios);
-       }
-
-       //FIXME: need to assert RTS and DTR if CRTSCTS off
-
        dbg("submitting read urb");
-       port->read_urb->dev = serial->dev;
-       result = usb_submit_urb (port->read_urb, GFP_KERNEL);
+       usp->read_urb->dev = serial->dev;
+       result = usb_submit_urb(usp->read_urb, GFP_KERNEL);
        if (result) {
-               dev_err(&port->dev, "%s - failed submitting read urb, error 
%d\n", __FUNCTION__, result);
-               pl2303_close (port, NULL);
-               return -EPROTO;
+               dev_err(&usp->dev, "%s - failed submitting read urb, error 
%d\n", __FUNCTION__, result);
+               pl2303_shutdown(port);
+               goto exit_err;
        }
 
        dbg("submitting interrupt urb");
-       port->interrupt_in_urb->dev = serial->dev;
-       result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
+       usp->interrupt_in_urb->dev = serial->dev;
+       result = usb_submit_urb(usp->interrupt_in_urb, GFP_KERNEL);
        if (result) {
-               dev_err(&port->dev, "%s - failed submitting interrupt urb, 
error %d\n", __FUNCTION__, result);
-               pl2303_close (port, NULL);
-               return -EPROTO;
+               dev_err(&usp->dev, "%s - failed submitting interrupt urb, error 
%d\n", __FUNCTION__, result);
+               pl2303_shutdown(port);
+               goto exit_err;
        }
+
+       dbg("pl2303 port %d opened", port->line);
        return 0;
-}
 
+ exit_err:
+       kref_put(&priv->kref, destroy_priv);
+       return result;
+}
 
-static void pl2303_close (struct usb_serial_port *port, struct file *filp)
+static void pl2303_shutdown(struct uart_port *port)
 {
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial_port *usp = USBSERIAL_PORT;
+       struct pl2303_private *priv;
        unsigned long flags;
-       unsigned int c_cflag;
        int bps;
        long timeout;
        wait_queue_t wait;                                              \
 
-       dbg("port %d", port->number);
+       dbg("port %d", port->line);
+
+       priv = usb_get_serial_port_data(usp);
 
        /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
        timeout = PL2303_CLOSING_WAIT;
        init_waitqueue_entry(&wait, current);
-       add_wait_queue(&port->tty->write_wait, &wait);
+       add_wait_queue(&port->info->tty->write_wait, &wait);
        for (;;) {
                set_current_state(TASK_INTERRUPTIBLE);
                if (pl2303_buf_data_avail(priv->buf) == 0
                || timeout == 0 || signal_pending(current)
-               || !usb_get_intfdata(port->serial->interface))  /* disconnect */
+               || !usb_get_intfdata(usp->serial->interface))   /* disconnect */
                        break;
                spin_unlock_irqrestore(&priv->lock, flags);
                timeout = schedule_timeout(timeout);
                spin_lock_irqsave(&priv->lock, flags);
        }
        set_current_state(TASK_RUNNING);
-       remove_wait_queue(&port->tty->write_wait, &wait);
+       remove_wait_queue(&port->info->tty->write_wait, &wait);
        /* clear out any remaining data in the buffer */
        pl2303_buf_clear(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -644,7 +671,7 @@ static void pl2303_close (struct usb_ser
        /* for lower rates we should really know how much */
        /* data is in the buffer to compute a delay */
        /* that is not unnecessarily long) */
-       bps = tty_get_baud_rate(port->tty);
+       bps = tty_get_baud_rate(port->info->tty);
        if (bps > 1200)
                timeout = max((HZ*2560)/bps,HZ/10);
        else
@@ -653,68 +680,66 @@ static void pl2303_close (struct usb_ser
 
        /* shutdown our urbs */
        dbg("shutting down urbs");
-       usb_kill_urb(port->write_urb);
-       usb_kill_urb(port->read_urb);
-       usb_kill_urb(port->interrupt_in_urb);
-
-       if (port->tty) {
-               c_cflag = port->tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore (&priv->lock, flags);
-                       set_control_lines (port->serial->dev, 0);
-               }
-       }
+       usb_kill_urb(usp->write_urb);
+       usb_kill_urb(usp->read_urb);
+       usb_kill_urb(usp->interrupt_in_urb);
+
+       kref_put(&priv->kref, destroy_priv);
+
+       dbg("pl2303 port %d closed", port->line);
 }
 
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-                           unsigned int set, unsigned int clear)
+static void pl2303_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct pl2303_private *priv;
        unsigned long flags;
        u8 control;
 
-       if (!usb_get_intfdata(port->serial->interface))
-               return -ENODEV;
+       dbg("port %d", port->line);
 
-       spin_lock_irqsave (&priv->lock, flags);
-       if (set & TIOCM_RTS)
+       if (!usb_get_intfdata(USBSERIAL_PORT->serial->interface))
+               return;
+
+       priv = usb_get_serial_port_data(USBSERIAL_PORT);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (mctrl & TIOCM_RTS)
                priv->line_control |= CONTROL_RTS;
-       if (set & TIOCM_DTR)
-               priv->line_control |= CONTROL_DTR;
-       if (clear & TIOCM_RTS)
+       else
                priv->line_control &= ~CONTROL_RTS;
-       if (clear & TIOCM_DTR)
+
+
+       if (mctrl & TIOCM_DTR)
+               priv->line_control |= CONTROL_DTR;
+       else
                priv->line_control &= ~CONTROL_DTR;
+
        control = priv->line_control;
        spin_unlock_irqrestore (&priv->lock, flags);
 
-       return set_control_lines (port->serial->dev, control);
+       set_control_lines_atomic(USBSERIAL_PORT, USBSERIAL_PORT->serial->dev,
+                                control);
 }
 
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
+static unsigned int pl2303_get_mctrl(struct uart_port *port)
 {
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct pl2303_private *priv;
        unsigned long flags;
-       unsigned int mcr;
        unsigned int status;
        unsigned int result;
 
-       dbg("(%d)", port->number);
+       dbg("port %d", port->line);
 
-       if (!usb_get_intfdata(port->serial->interface))
+       priv = usb_get_serial_port_data(USBSERIAL_PORT);
+
+       if (!usb_get_intfdata(USBSERIAL_PORT->serial->interface))
                return -ENODEV;
 
        spin_lock_irqsave (&priv->lock, flags);
-       mcr = priv->line_control;
        status = priv->line_status;
        spin_unlock_irqrestore (&priv->lock, flags);
 
-       result = ((mcr & CONTROL_DTR)           ? TIOCM_DTR : 0)
-                 | ((mcr & CONTROL_RTS)        ? TIOCM_RTS : 0)
-                 | ((status & UART_CTS)        ? TIOCM_CTS : 0)
+       result = ((status & UART_CTS)           ? TIOCM_CTS : 0)
                  | ((status & UART_DSR)        ? TIOCM_DSR : 0)
                  | ((status & UART_RING)       ? TIOCM_RI  : 0)
                  | ((status & UART_DCD)        ? TIOCM_CD  : 0);
@@ -724,6 +749,78 @@ static int pl2303_tiocmget (struct usb_s
        return result;
 }
 
+static void pl2303_start_tx(struct uart_port *port)
+{
+       struct usb_serial_port *usp = USBSERIAL_PORT;
+       struct circ_buf *xmit = &port->info->xmit;
+       struct pl2303_private *priv;
+       int count;
+
+       dbg("port %d", port->line);
+
+       priv = usb_get_serial_port_data(usp);
+
+       if (port->x_char) {
+               pl2303_buf_put(priv->buf, &port->x_char, 1);
+               port->x_char = 0;
+               goto submit;
+       }
+
+       if (uart_tx_stopped(port)) {
+               pl2303_stop_tx(port);
+               return;
+       }
+
+       if (uart_circ_empty(xmit))
+               return;
+
+       count = pl2303_buf_space_avail(priv->buf);
+       do {
+               pl2303_buf_put(priv->buf, &xmit->buf[xmit->tail], 1);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               if (uart_circ_empty(xmit))
+                       break;
+       } while (--count > 0);
+
+submit:
+       pl2303_send(usp);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+}
+
+static int pl2303_write_room(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       int room = 0;
+       unsigned long flags;
+
+       dbg("port %d", port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       room = pl2303_buf_space_avail(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       dbg("returns %d", room);
+       return room;
+}
+
+static int pl2303_chars_in_buffer(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       int chars = 0;
+       unsigned long flags;
+
+       dbg("port %d", port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       chars = pl2303_buf_data_avail(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       dbg("returns %d", chars);
+       return chars;
+}
+
 static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -777,27 +874,6 @@ static int pl2303_ioctl (struct usb_seri
        return -ENOIOCTLCMD;
 }
 
-static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
-{
-       struct usb_serial *serial = port->serial;
-       u16 state;
-       int result;
-
-       dbg("port %d", port->number);
-
-       if (break_state == 0)
-               state = BREAK_OFF;
-       else
-               state = BREAK_ON;
-       dbg("turning break %s", state==BREAK_OFF ? "off" : "on");
-
-       result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
-                                 0, NULL, 0, 100);
-       if (result)
-               dbg("error sending break = %d", result);
-}
-
 static void pl2303_usb_shutdown(struct usb_serial *serial)
 {
        int i;
-- 
1.3.3.g0825d



_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to