⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pl2303.c

📁 PL2303 Linux驱动源码 drivers/usb/serial/usb-serial
💻 C
📖 第 1 页 / 共 2 页
字号:
#define __NO_VERSION__#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/malloc.h>#include <linux/fcntl.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/tty.h>#include <linux/module.h>#include <linux/spinlock.h>#ifndef MIN#define MIN(a,b)        ((a) < (b) ? (a) : (b))#endif#define	PL2303_LOCK(port,flags)					\		do {						\		spin_lock_irqsave(&port->lock, flags); \		} while (0)		#define	PL2303_UNLOCK(port,flags)					\		do {						\		spin_unlock_irqrestore(&port->lock, flags); \		} while (0)#ifdef CONFIG_USB_SERIAL_DEBUG#define DEBUG#else#undef DEBUG#endif#undef DEBUG#include <linux/usb.h>#include "usb-serial.h"#include "pl2303.h"/* function prototypes for a PL2303 serial converter */static int pl2303_startup (struct usb_serial *serial);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 int pl2303_ioctl (struct usb_serial_port *port, struct file *file,                         unsigned int cmd, unsigned long arg);static void pl2303_throttle (struct usb_serial_port *port);static void pl2303_unthrottle (struct usb_serial_port *port);static void pl2303_read_int_callback (struct urb *urb);static void pl2303_read_bulk_callback (struct urb *urb);static void pl2303_write_bulk_callback (struct urb *urb);static int pl2303_write (struct usb_serial_port *port, int from_user,                         const unsigned char *buf, int count);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 void start_xmit (struct usb_serial_port *port);/* All of the device info needed for the PL2303 SIO serial converter */static __u16 pl2303_vendor_id = PL2303_VENDOR_ID;static __u16 pl2303_product_id = PL2303_PRODUCT_ID;struct usb_serial_device_type pl2303_device = {  name:"PL-2303",  idVendor:&pl2303_vendor_id,   /* the PL2303 vendor ID */  idProduct:&pl2303_product_id, /* the PL2303 product id */  needs_interrupt_in:DONT_CARE, /* this device must have an interrupt in endpoint */  needs_bulk_in:MUST_HAVE,      /* this device must have a bulk in endpoint */  needs_bulk_out:MUST_HAVE,     /* this device must have a bulk out endpoint */  num_interrupt_in:NUM_DONT_CARE,  num_bulk_in:1,  num_bulk_out:1,  num_ports:1,  open:pl2303_open,  close:pl2303_close,  throttle:pl2303_throttle,  unthrottle:pl2303_unthrottle,  write:pl2303_write,  ioctl:pl2303_ioctl,write_room: pl2303_write_room,chars_in_buffer: pl2303_chars_in_buffer,break_ctl: pl2303_break_ctl,  set_termios:pl2303_set_termios,  read_bulk_callback:pl2303_read_bulk_callback,  read_int_callback:pl2303_read_int_callback,  write_bulk_callback:pl2303_write_bulk_callback,  startup:pl2303_startup,};#define WDR_TIMEOUT (HZ * 5 )   /* default urb timeout */static unsigned char *tmp_buf;static struct semaphore tmp_buf_sem = MUTEX;static inline struct usb_serial* get_usb_serial (struct usb_serial_port *port, const char *function){        /* if no port was specified, or it fails a paranoia check */        if (!port ||                port_paranoia_check (port, function) ||                serial_paranoia_check (port->serial, function)) {                /* then say that we dont have a valid usb_serial thing, which will                 * end up genrating -ENODEV return values */                return NULL;        }        return port->serial;}static intpl2303_write (struct usb_serial_port *port, int from_user,              const unsigned char *buf, int count){                               /* pl2303_write */  //struct usb_serial *serial = port->serial;  unsigned long flags;  int c,ret=0;  struct tty_struct *tty=port->tty;  dbg ("pl2303_write port %d, %d bytes", port->number, count);  if (!tty || !port->xmit_buf || !tmp_buf){      return 0;  }  PL2303_LOCK(port,flags);   if (from_user) {	down(&tmp_buf_sem);	while (1) {	    c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,				SERIAL_XMIT_SIZE - port->xmit_head));	    if (c <= 0)		break;	    c -= copy_from_user(tmp_buf, buf, c);	    if (!c) {		if (!ret) {		    ret = -EFAULT;		}		break;	    }	    c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,			SERIAL_XMIT_SIZE - port->xmit_head));	    memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);	    port->xmit_head = ((port->xmit_head + c) & (SERIAL_XMIT_SIZE-1));	    port->xmit_cnt += c;	    buf += c;	    count -= c;	    ret += c;	}	up(&tmp_buf_sem);    } else {	while (1) {	    c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, 			SERIAL_XMIT_SIZE - port->xmit_head));	    if (c <= 0) {		break;	    }	    memcpy(port->xmit_buf + port->xmit_head, buf, c);	    port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);	    port->xmit_cnt += c;	    buf += c;	    count -= c;	    ret += c;	}    }    PL2303_UNLOCK(port, flags);    if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped) {        start_xmit(port);    }    return ret;}static int pl2303_write_room(struct usb_serial_port *port){	int	ret;					ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;	if (ret < 0)		ret = 0;	return ret;}static int pl2303_chars_in_buffer(struct usb_serial_port *port){	return port->xmit_cnt;}static void pl2303_throttle(struct usb_serial_port *port){  //struct usb_serial *serial = port->serial;  struct tty_struct *tty=port->tty;  unsigned long flags;#if 0	char	buf[64];		printk("throttle %s: %d....\n", tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif#if 0//FIXME FIXME FIXME		if (I_IXOFF(tty))		rs_send_xchar(tty, STOP_CHAR(tty));#endif	PL2303_LOCK(port,flags);	//Should remove read request if one is present	PL2303_UNLOCK(fport,flags);}static void pl2303_unthrottle(struct usb_serial_port *port){  //struct usb_serial *serial = port->serial;  struct tty_struct *tty=port->tty;  unsigned long flags;#if 0	char	buf[64];		printk("unthrottle %s: %d....\n", tty_name(tty, buf),	       tty->ldisc.chars_in_buffer(tty));#endif#if 0	//FIXME FIXME FIXME FIXME FIXME	if (I_IXOFF(tty)) {		if (info->x_char)			info->x_char = 0;		else			rs_send_xchar(tty, START_CHAR(tty));	}#endif	PL2303_LOCK(port,flags);	//Should add read request if one is not present	PL2303_UNLOCK(fport,flags);}static voidpl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios){                               /* pl2303_set_termios */  struct usb_serial *serial = port->serial;  unsigned int cflag = port->tty->termios->c_cflag;  unsigned char buf[7] = { 0, 0, 0, 0, 0, 0, 0 };  int baud;  int i;  dbg ("pl2303_set_termios port %d", port->number);  i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),                       0x21, 0xa1, 0, 0, buf, 7, 100);  printk ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x\n", i,          buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);  i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),                       1, 0x40, 0, 1, NULL, 0, 100);  printk ("0x40:1:0:1  %d\n", i);  if (cflag & CSIZE)    {      switch (cflag & CSIZE)        {        case CS6:          buf[6] = 6;          dbg ("Setting CS6");          break;        case CS7:          buf[6] = 7;          dbg ("Setting CS7");          break;        case CS8:          buf[6] = 8;          dbg ("Setting CS8");          break;        default:          err ("CSIZE was set but not CS6-CS8");        }    }  baud = 0;  switch (cflag & CBAUD)    {    case B0:      err ("Can't do B0 yet");  //FIXME      break;    case B300:      baud = 300;      break;    case B600:      baud = 600;      break;    case B1200:      baud = 1200;      break;    case B2400:      baud = 2400;      break;    case B4800:      baud = 4800;      break;    case B9600:      baud = 9600;      break;    case B19200:      baud = 19200;      break;    case B38400:      baud = 38400;      break;    case B57600:      baud = 57600;      break;    case B115200:      baud = 115200;      break;    default:      dbg ("pl2303 driver does not support the baudrate requested (fix it)");      break;    }  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]=1 is 1.5 stop bits */  if (cflag & CSTOPB)    {      buf[4] = 2;    }  if (cflag & PARENB)    {      /* For reference buf[5]=3 is mark parity */      /* For reference buf[5]=4 is space parity */      if (cflag & PARODD)        {          buf[5] = 1;        }      else        {          buf[5] = 2;        }    }  i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),                       0x20, 0x21, 0, 0, buf, 7, 100);  printk ("0x21:0x20:0:0  %d \n", i);  i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),                       0x22, 0x21, 1, 0, NULL, 0, 100);  printk ("0x21:0x22:1:0  %d\n", i);  i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),                       0x22, 0x21, 3, 0, NULL, 0, 100);  printk ("0x21:0x22:3:0  %d\n", i);  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),                       0x21, 0xa1, 0, 0, buf, 7, 100);  printk ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x\n", i,          buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);  if (cflag & CRTSCTS)    {      i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),                           0x01, 0x40, 0x0, 0x41, NULL, 0, 100);      printk ("0x40:0x1:0x0:0x41  %d \n", i);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -