📄 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 + -