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

📄 pl2303.c

📁 linux下利用usb转换为串口的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Prolific USB Serial Adapter Driver * *  Copyright (C) 2001 *      Prolific Technology Inc. * *  This program is largely derived from work by the linux-usb group *  and associated source files.  Please see the usb/serial files for *  individual credits and copyrights. * */#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/slab.h>#include <linux/fcntl.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/tty_flip.h>#include <linux/module.h>#include <linux/spinlock.h>#include <linux/usb.h>#ifdef USB_SERIAL_DEBUGstatic int  debug = 1;#else// static int  debug;#endif#include "usb-serial.h"#include "pl2303.h"#define TRUE  1#define FALSE 0/* function prototypes for a Prolific USB Serial Adapter */static int                                prolific_sa_startup(struct usb_serial *serial);static void                               prolific_sa_shutdown(struct usb_serial *serial);static int                                prolific_sa_open(struct usb_serial_port *port, struct file *filp);static void                               prolific_sa_close(struct usb_serial_port *port, struct file *filp);static void                               prolific_sa_read_int_callback(struct urb *urb);static void                               prolific_sa_set_termios(struct usb_serial_port *port, struct termios *old);static int                                prolific_sa_ioctl(struct usb_serial_port  *port, struct file             *file,                                                            unsigned int            cmd, unsigned long           arg);static void                               prolific_sa_break_ctl(struct usb_serial_port *port, int break_state);static void                               prolific_set_dcr_state(struct usb_serial_port *port, int set);static int							  prolific_sa_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);static void							  prolific_sa_write_bulk_callback(struct urb *urb);static __devinitdata struct usb_device_id id_table_combined[] = {  { USB_DEVICE(PROLIFIC_SA_VID, PROLIFIC_SA_PID) },  { } /* Terminating entry */};static __devinitdata struct usb_device_id prolific_sa_table[] = {  { USB_DEVICE(PROLIFIC_SA_VID, PROLIFIC_SA_PID) },  { } /* Terminating entry */};MODULE_DEVICE_TABLE(usb, id_table_combined);/* All of the device info needed for the Prolific serial converter */struct usb_serial_device_type prolific_sa_device ={name:  "Prolific USB Serial Adapter",  id_table : prolific_sa_table,                       /* the Prolific device */  needs_interrupt_in : MUST_HAVE,                     /* 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 : 1,  num_bulk_in : 1,  num_bulk_out : 1,  num_ports : 1,  open : prolific_sa_open,  close : prolific_sa_close,  write : prolific_sa_write,  read_int_callback : prolific_sa_read_int_callback,  /* How we get the status info */  write_bulk_callback : prolific_sa_write_bulk_callback,  ioctl : prolific_sa_ioctl,  set_termios : prolific_sa_set_termios,  break_ctl : prolific_sa_break_ctl,  startup : prolific_sa_startup,  shutdown : prolific_sa_shutdown,};struct line_coding {  unsigned long dwDTERate;  unsigned char bCharFormat;  unsigned char bParityType;  unsigned char bDatabits;};struct prolific_sa_private {  unsigned long       control_state;  unsigned char       last_lsr;  unsigned char       last_msr;  int                 bad_flow_control;  struct line_coding  lineCoding;  unsigned short      RTSDTRState;};/* * *************************************************************************** * Prolific USB Serial Adapter specific driver functions * *************************************************************************** */#define WDR_TIMEOUT (HZ * 5)  /* default urb timeout *//* assumes that struct usb_serial *serial is available */#define BSA_USB_CMD(r, v) \  usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (r), PROLIFIC_SA_SET_REQUEST_CLASS_TYPE, (v), 0, NULL, 0, \                  WDR_TIMEOUT)#define BSA_USB_CMD_SET_DATA(r, v, data) \  usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (r), PROLIFIC_SA_SET_REQUEST_CLASS_TYPE, (v), 0, data, \                  sizeof(data), WDR_TIMEOUT)#define BSA_USB_CMD_SET_DATA_LEN(r, v, data, size) \  usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (r), PROLIFIC_SA_SET_REQUEST_CLASS_TYPE, (v), 0, data, \                  size, WDR_TIMEOUT)#define BSA_USB_CMD_SET_VENDOR(r, v, idx) \  usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (r), PROLIFIC_SA_SET_REQUEST_VENDOR_TYPE, (v), (idx), \                  NULL, 0, WDR_TIMEOUT)#define BSA_USB_CMD_GET_VENDOR_DATA(r, v, data, size) \  usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (r), PROLIFIC_SA_GET_REQUEST_VENDOR_TYPE, (v), 0, data, \                  size, WDR_TIMEOUT)/* do some startup allocations not currently performed by usb_serial_probe() */static int prolific_sa_startup(struct usb_serial *serial){  struct usb_device           *dev = serial->dev;  struct prolific_sa_private  *priv;  /* allocate the private data structure */  serial->port->private = kmalloc(sizeof(struct prolific_sa_private), GFP_KERNEL);  if(!serial->port->private)    return(-1); /* error */  priv = (struct prolific_sa_private *)serial->port->private;  /* set initial values for control structures */  priv->control_state = 0;  priv->last_lsr = 0;  priv->last_msr = 0;  /* see comments at top of file */  priv->bad_flow_control = (dev->descriptor.bcdDevice <= 0x0206) ? 1 : 0;  info("bcdDevice: %04x, bfc: %d", dev->descriptor.bcdDevice, priv->bad_flow_control);  init_waitqueue_head(&serial->port->write_wait);  return(0);}static void prolific_sa_shutdown(struct usb_serial *serial){  int i;  dbg(__FUNCTION__);  /* stop reads and writes on all ports */  for(i = 0; i < serial->num_ports; ++i) {    while(serial->port[i].open_count > 0) {      prolific_sa_close(&serial->port[i], NULL);    }    /* My special items, the standard routines free my urbs */    if(serial->port[i].private)      kfree(serial->port[i].private);  }}static int prolific_sa_open(struct usb_serial_port *port, struct file *filp){  unsigned long flags;  dbg(__FUNCTION__ " port %d", port->number);  spin_lock_irqsave(&port->port_lock, flags);  ++port->open_count;  MOD_INC_USE_COUNT;  if(!port->active) {    port->active = 1;    /*Start reading from the device*/    /* TODO: Look at possibility of submitting mulitple URBs to device to		 *       enhance buffering.  Win trace shows 16 initial read URBs.		 */    port->read_urb->dev = port->serial->dev;    if(usb_submit_urb(port->read_urb))      err("usb_submit_urb(read bulk) failed");    port->interrupt_in_urb->dev = port->serial->dev;    if(usb_submit_urb(port->interrupt_in_urb))      err(" usb_submit_urb(read int) failed");  }  spin_unlock_irqrestore(&port->port_lock, flags);  return 0;} /* prolific_sa_open */static void prolific_sa_close(struct usb_serial_port *port, struct file *filp){  unsigned long flags;  dbg(__FUNCTION__ " port %d", port->number);  spin_lock_irqsave(&port->port_lock, flags);  --port->open_count;  MOD_DEC_USE_COUNT;  if(port->open_count <= 0) {    /* shutdown our bulk reads and writes */    usb_unlink_urb(port->write_urb);    usb_unlink_urb(port->read_urb);    usb_unlink_urb(port->interrupt_in_urb); /* wgg - do I need this? I think so. */    port->active = 0;  }  spin_unlock_irqrestore(&port->port_lock, flags);} /* prolific_sa_close */static void prolific_sa_read_int_callback(struct urb *urb){  struct usb_serial_port      *port = (struct usb_serial_port *)urb->context;  struct prolific_sa_private  *priv = (struct prolific_sa_private *)port->private;  struct usb_serial           *serial;  unsigned char               *data = urb->transfer_buffer;  /* the urb might have been killed. */  if(urb->status)    return;  if(port_paranoia_check(port, "prolific_sa_read_interrupt"))    return;  serial = port->serial;  if(serial_paranoia_check(serial, "prolific_sa_read_interrupt"))    return;  usb_serial_debug_data(__FILE__, __FUNCTION__, urb->actual_length, data);  /* Handle known interrupt data */  /* ignore data[0] and data[1] */  priv->last_msr = data[PROLIFIC_SA_MSR_INDEX];  dbg("interrupt: 0x%02x", priv->last_msr);  /* Record Control Line states */  if(priv->last_msr & PROLIFIC_SA_MSR_DSR)    priv->control_state |= TIOCM_DSR;  else    priv->control_state &= ~TIOCM_DSR;  if(priv->last_msr & PROLIFIC_SA_MSR_CTS)    priv->control_state |= TIOCM_CTS;  else    priv->control_state &= ~TIOCM_CTS;  if(priv->last_msr & PROLIFIC_SA_MSR_RI)    priv->control_state |= TIOCM_RI;  else    priv->control_state &= ~TIOCM_RI;  if(priv->last_msr & PROLIFIC_SA_MSR_CD)    priv->control_state |= TIOCM_CD;  else    priv->control_state &= ~TIOCM_CD;  /* Now to report any errors */  priv->last_lsr = data[PROLIFIC_SA_LSR_INDEX];#if 0  if(priv->last_lsr & PROLIFIC_SA_LSR_ERR) {    tty = port->tty;    /* Overrun Error */    if(priv->last_lsr & PROLIFIC_SA_LSR_OE) {    }    /* Parity Error */    if(priv->last_lsr & PROLIFIC_SA_LSR_PE) {    }    /* Framing Error */    if(priv->last_lsr & PROLIFIC_SA_LSR_FE) {    }    /* Break Indicator */    if(priv->last_lsr & PROLIFIC_SA_LSR_BI) {    }  }#endif  /* INT urbs are automatically re-submitted */}static void prolific_sa_set_termios(struct usb_serial_port *port, struct termios *old_termios){  struct usb_serial           *serial = port->serial;  struct prolific_sa_private  *priv = (struct prolific_sa_private *)port->private;  unsigned int                cflag = port->tty->termios->c_cflag;  unsigned int                old_cflag = old_termios->c_cflag;  unsigned long               rate = 115200;  unsigned char               format = 0, parity = 0, size = 8;  info(__FUNCTION__ " - cflag: 0x%4X, old_cflag: 0x%4X", cflag, old_cflag);  /* Set the baud rate */  if((cflag & CBAUD) != (old_cflag & CBAUD)) {    /* reassert DTR and (maybe) RTS on transition from B0 */    if((old_cflag & CBAUD) == B0) {

⌨️ 快捷键说明

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