📄 pl2303.c
字号:
priv->write_urb_in_use = 1; spin_unlock_irqrestore(&priv->lock, flags); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer); port->write_urb->transfer_buffer_length = count; port->write_urb->dev = port->serial->dev; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, "%s - failed submitting write urb," " error %d\n", __FUNCTION__, result); priv->write_urb_in_use = 0; // TODO: reschedule pl2303_send } usb_serial_port_softint(port);}static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf, int count){ struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); if (!count) return count; spin_lock_irqsave(&priv->lock, flags); count = pl2303_buf_put(priv->buf, buf, count); spin_unlock_irqrestore(&priv->lock, flags); pl2303_send(port); return count;}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("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); room = pl2303_buf_space_avail(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - returns %d", __FUNCTION__, 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("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->lock, flags); chars = pl2303_buf_data_avail(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); dbg("%s - returns %d", __FUNCTION__, chars); return chars;}static void pl2303_set_termios(struct usb_serial_port *port, struct ktermios *old_termios){ struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag; unsigned char *buf; int baud; int i; u8 control; dbg("%s - port %d", __FUNCTION__, 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; port->tty->termios->c_ispeed = 9600; port->tty->termios->c_ospeed = 9600; priv->termios_initialized = 1; } spin_unlock_irqrestore(&priv->lock, flags); /* The PL2303 is reported to lose bytes if you change serial settings even to the same values as before. Thus we actually need to filter in this specific case */ if (!tty_termios_hw_change(port->tty->termios, old_termios)) return; cflag = port->tty->termios->c_cflag; buf = kzalloc(7, GFP_KERNEL); if (!buf) { dev_err(&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; case CS6: buf[6] = 6; break; case CS7: buf[6] = 7; break; default: case CS8: buf[6] = 8; break; } dbg("%s - data bits = %d", __FUNCTION__, buf[6]); } baud = tty_get_baud_rate(port->tty);; dbg("%s - baud = %d", __FUNCTION__, baud); if (baud) { buf[0] = baud & 0xff; buf[1] = (baud >> 8) & 0xff; buf[2] = (baud >> 16) & 0xff; buf[3] = (baud >> 24) & 0xff; } /* For reference buf[4]=0 is 1 stop bits */ /* 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", __FUNCTION__); } else { buf[4] = 0; dbg("%s - stop bits = 1", __FUNCTION__); } if (cflag & PARENB) { /* For reference buf[5]=0 is none parity */ /* For reference buf[5]=1 is odd parity */ /* For reference buf[5]=2 is even parity */ /* 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", __FUNCTION__); } else { buf[5] = 2; dbg("%s - parity = even", __FUNCTION__); } } else { buf[5] = 0; dbg("%s - parity = none", __FUNCTION__); } i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); dbg("0x21:0x20:0:0 %d", i); /* change control lines if we are switching to or from B0 */ spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; if ((cflag & CBAUD) == B0) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); else priv->line_control |= (CONTROL_DTR | CONTROL_RTS); if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); set_control_lines(serial->dev, control); } else { spin_unlock_irqrestore(&priv->lock, flags); } buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; 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 & CRTSCTS) { __u16 index; if (priv->type == HX) index = 0x61; else index = 0x41; i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, 0x0, index, NULL, 0, 100); dbg("0x40:0x1:0x0:0x%x %d", index, i); } else { i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, 0x0, 0x0, NULL, 0, 100); dbg ("0x40:0x1:0x0:0x0 %d", i); } /* FIXME: Need to read back resulting baud rate */ if (baud) tty_encode_baud_rate(port->tty, baud, baud); kfree(buf);}static void pl2303_close(struct usb_serial_port *port, struct file *filp){ struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int c_cflag; int bps; long timeout; wait_queue_t wait; dbg("%s - port %d", __FUNCTION__, port->number); /* 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); 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 */ 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); /* clear out any remaining data in the buffer */ pl2303_buf_clear(priv->buf); spin_unlock_irqrestore(&priv->lock, flags); /* wait for characters to drain from the device */ /* (this is long enough for the entire 256 byte */ /* pl2303 hardware buffer to drain with no flow */ /* control for data rates of 1200 bps or more, */ /* 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); if (bps > 1200) timeout = max((HZ*2560)/bps,HZ/10); else timeout = 2*HZ; schedule_timeout_interruptible(timeout); /* shutdown our urbs */ dbg("%s - shutting down urbs", __FUNCTION__); 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); } }}static int pl2303_open(struct usb_serial_port *port, struct file *filp){ struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned char *buf; int result; dbg("%s - port %d", __FUNCTION__, port->number); if (priv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } buf = kmalloc(10, GFP_KERNEL); if (buf==NULL) return -ENOMEM;#define FISH(a,b,c,d) \ result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ b, a, c, d, buf, 1, 100); \ dbg("0x%x:0x%x:0x%x:0x%x %d - %x",a,b,c,d,result,buf[0]);#define SOUP(a,b,c,d) \ result=usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev,0), \ b, a, c, d, NULL, 0, 100); \ dbg("0x%x:0x%x:0x%x:0x%x %d",a,b,c,d,result); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0); if (priv->type == HX) { /* HX chip */ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44); /* reset upstream data pipes */ SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0); SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0); } else { SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24); } kfree(buf); /* Setup termios */ if (port->tty) { pl2303_set_termios(port, &tmp_termios); } //FIXME: need to assert RTS and DTR if CRTSCTS off dbg("%s - submitting read urb", __FUNCTION__); port->read_urb->dev = serial->dev; result = usb_submit_urb(port->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; } dbg("%s - submitting interrupt urb", __FUNCTION__); port->interrupt_in_urb->dev = serial->dev; result = usb_submit_urb(port->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; } return 0;}static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear){ struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; if (!usb_get_intfdata(port->serial->interface)) return -ENODEV; spin_lock_irqsave(&priv->lock, flags); if (set & TIOCM_RTS) priv->line_control |= CONTROL_RTS; if (set & TIOCM_DTR) priv->line_control |= CONTROL_DTR; if (clear & TIOCM_RTS) priv->line_control &= ~CONTROL_RTS; if (clear & TIOCM_DTR) priv->line_control &= ~CONTROL_DTR; control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -