📄 pl2303.c
字号:
priv->control_state |= (TIOCM_DTR | TIOCM_RTS);
if(BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState |= 0x0001) < 0)
err("Set DTR error");
/* don't set RTS if using hardware flow control */
if(!(old_cflag & CRTSCTS))
if(BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState |= 0x0002) < 0)
err("Set RTS error");
}
switch(cflag & CBAUD)
{
case B150: rate = 150; break;
case B300: rate = 300; break;
case B600: rate = 600; break;
case B1200: rate = 1200; break;
case B2400: rate = 2400; break;
case B4800: rate = 4800; break;
case B9600: rate = 9600; break;
case B19200: rate = 19200; break;
case B38400: rate = 38400; break;
case B115200: rate = 115200; break;
case B230400: rate = 230400; break;
case B460800: rate = 460800; break;
}
if((cflag & CBAUD) == B0) {
/* Drop RTS and DTR */
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
if(BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState &= 0xFFFE) < 0)
err("DTR LOW error");
if(BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState &= 0xFFFD) < 0)
err("RTS LOW error");
}
}
/* set the parity */
if((cflag & (PARENB | PARODD)) != (old_cflag & (PARENB | PARODD))) {
if(cflag & PARENB)
parity = (cflag & PARODD) ? 0x01 : 0x02;
else
parity = 0;
}
/* set the number of data bits */
if((cflag & CSIZE) != (old_cflag & CSIZE)) {
switch(cflag & CSIZE)
{
case CS5: size = 5; break;
case CS6: size = 6; break;
case CS7: size = 7; break;
case CS8: size = 8; break;
}
}
/* set the number of stop bits */
if((cflag & CSTOPB) != (old_cflag & CSTOPB))
format = (cflag & CSTOPB) ? 0x02 : 0x00;
/* Set flow control */
if((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
if(cflag & CRTSCTS)
prolific_set_dcr_state(port, TRUE);
else
prolific_set_dcr_state(port, FALSE);
}
priv->lineCoding.dwDTERate = rate;
priv->lineCoding.bCharFormat = format;
priv->lineCoding.bParityType = parity;
priv->lineCoding.bDatabits = size;
dbg(__FUNCTION__ "==> dwDTERate: %ld - bCharFormat: %d - bParityType: %d - bDatabits: %d", rate, format, parity, size);
if(BSA_USB_CMD_SET_DATA_LEN(PROLIFIC_SA_SET_LINECODING_REQUEST, 0, &priv->lineCoding, 7) < 0)
err("Set_line_coding request error");
} /* prolific_sa_set_termios */
static void prolific_sa_break_ctl(struct usb_serial_port *port, int break_state)
{
struct usb_serial *serial = port->serial;
if(break_state) {
if(BSA_USB_CMD(PROLIFIC_SA_SET_BREAK_REQUEST, 0xFFFF) < 0)
err("Set break_ctl %d fail", break_state);
}
else {
if(BSA_USB_CMD(PROLIFIC_SA_SET_BREAK_REQUEST, 0) < 0)
err("Set break_ctl %d fail", break_state);
}
}
static int prolific_sa_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
__u16 urb_value; /* Will hold the new flags */
struct prolific_sa_private *priv = (struct prolific_sa_private *)port->private;
int ret, mask;
info(__FUNCTION__ " cmd: %04x", cmd);
/* Based on code from acm.c and others */
switch(cmd)
{
case TIOCMGET:
dbg("TIOCMGET: control_state - 0x%04x", (unsigned int)priv->control_state);
return put_user(priv->control_state, (unsigned long *)arg);
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
if((ret = get_user(mask, (unsigned long *)arg)))
return ret;
dbg("cmd: 0x%04X mask: 0x%04X", cmd, mask);
if((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
/* RTS needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0;
if(urb_value)
priv->control_state |= TIOCM_RTS;
else
priv->control_state &= ~TIOCM_RTS;
if(urb_value) {
if((ret = BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState |= 0x0002)) < 0) {
err("Set RTS error %d", ret);
return(ret);
}
}
else {
if((ret = BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState &= 0xFFFD)) < 0) {
err("Clear RTS error %d", ret);
return(ret);
}
}
if((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
/* DTR needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0;
if(urb_value)
priv->control_state |= TIOCM_DTR;
else
priv->control_state &= ~TIOCM_DTR;
if(urb_value) {
if((ret = BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState |= 0x0001)) < 0) {
err("Set DTR error %d", ret);
return(ret);
}
}
else {
if((ret = BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState &= 0xFFFE)) < 0) {
err("Clear DTR error %d", ret);
return(ret);
}
}
}
}
break;
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
return(0);
case TIOCGICOUNT:
/* return count of modemline transitions */
/* TODO */
return 0;
default:
dbg("prolific_sa_ioctl arg not supported - 0x%04x", cmd);
return(-ENOIOCTLCMD);
break;
}
return 0;
} /* prolific_sa_ioctl */
static void prolific_set_dcr_state(struct usb_serial_port *port, int set)
{
struct usb_serial *serial = port->serial;
unsigned short code = 0;
unsigned char old_value = 0;
unsigned short new_value;
int ret;
struct prolific_sa_private *priv = (struct prolific_sa_private *)port->private;
info(__FUNCTION__ " - set: %d", set);
if(BSA_USB_CMD_GET_VENDOR_DATA(PROLIFIC_SA_VENDOR_REQUEST, code, &old_value, sizeof(old_value)) < 0)
err("Get DCR request error");
if(set)
new_value = old_value | 0x40;
else
new_value = old_value & 0x3F;
if(BSA_USB_CMD_SET_VENDOR(PROLIFIC_SA_VENDOR_REQUEST, code, new_value) < 0)
err("Set DCR request error");
if(set) {
if((ret = BSA_USB_CMD(PROLIFIC_SA_SET_CTRL_LINE_REQUEST, priv->RTSDTRState |= 0x0002)) < 0) {
err("Set RTS error %d", ret);
return;
}
}
}
static int prolific_sa_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
unsigned long flags;
int result;
dbg(__FUNCTION__ " - port %d", port->number);
if(count == 0) {
dbg(__FUNCTION__ " - write request of 0 bytes");
return(0);
}
/* only do something if we have a bulk out endpoint */
if(serial->num_bulk_out) {
/*
if(port->write_urb->status == -EINPROGRESS) {
dbg(__FUNCTION__ " - already writing");
return(0);
}
*/
while(port->write_urb->status == -EINPROGRESS)
schedule();
spin_lock_irqsave(&port->port_lock, flags);
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
usb_serial_debug_data(__FILE__, __FUNCTION__, count, buf);
if(from_user) {
copy_from_user(port->write_urb->transfer_buffer, buf, count);
}
else {
memcpy(port->write_urb->transfer_buffer, buf, count);
}
/* set up our urb */
FILL_BULK_URB(port->write_urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
prolific_sa_write_bulk_callback,
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb);
if(result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
spin_unlock_irqrestore(&port->port_lock, flags);
return 0;
}
spin_unlock_irqrestore(&port->port_lock, flags);
return(count);
}
/* no bulk out, so return 0 bytes written */
return(0);
}
static void prolific_sa_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);
dbg(__FUNCTION__ " - port %d", port->number);
if(!serial) {
dbg(__FUNCTION__ " - bad serial pointer, exiting");
return;
}
if(urb->status) {
dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
return;
}
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
}
static int __init prolific_sa_init(void)
{
usb_serial_register(&prolific_sa_device);
return 0;
}
static void __exit prolific_sa_exit(void)
{
usb_serial_deregister(&prolific_sa_device);
}
module_init(prolific_sa_init);
module_exit(prolific_sa_exit);
MODULE_AUTHOR("Sam Kuo");
MODULE_DESCRIPTION("Prolific USB-Serial converter driver");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -