?? pl2303.c
字號(hào):
/* * 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) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -