📄 kl5kusb105.c
字号:
bytes_sent = urb->actual_length - 2; } for (i = 2; i < 2+bytes_sent; i++) { /* if we insert more than TTY_FLIPBUF_SIZE characters, * we drop them. */ if(tty->flip.count >= TTY_FLIPBUF_SIZE) { tty_flip_buffer_push(tty); } /* this doesn't actually push the data through unless * tty->low_latency is set */ tty_insert_flip_char(tty, ((__u8*) data)[i], 0); } tty_flip_buffer_push(tty); priv->bytes_in += bytes_sent; } /* Continue trying to always read */ FILL_BULK_URB(port->read_urb, serial->dev, usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, klsi_105_read_bulk_callback, port); rc = usb_submit_urb(port->read_urb); if (rc) err(__FUNCTION__ " - failed resubmitting read urb, error %d", rc);} /* klsi_105_read_bulk_callback */static void klsi_105_set_termios (struct usb_serial_port *port, struct termios *old_termios){ struct usb_serial *serial = port->serial; struct klsi_105_private *priv = (struct klsi_105_private *)port->private; unsigned int iflag = port->tty->termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int cflag = port->tty->termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag; /* * Update baud rate */ if( (cflag & CBAUD) != (old_cflag & CBAUD) ) { /* reassert DTR and (maybe) RTS on transition from B0 */ if( (old_cflag & CBAUD) == B0 ) { dbg(__FUNCTION__ ": baud was B0");#if 0 priv->control_state |= TIOCM_DTR; /* don't set RTS if using hardware flow control */ if (!(old_cflag & CRTSCTS)) { priv->control_state |= TIOCM_RTS; } mct_u232_set_modem_ctrl(serial, priv->control_state);#endif } switch(cflag & CBAUD) { case B0: /* handled below */ break; case B1200: priv->cfg.baudrate = kl5kusb105a_sio_b1200; break; case B2400: priv->cfg.baudrate = kl5kusb105a_sio_b2400; break; case B4800: priv->cfg.baudrate = kl5kusb105a_sio_b4800; break; case B9600: priv->cfg.baudrate = kl5kusb105a_sio_b9600; break; case B19200: priv->cfg.baudrate = kl5kusb105a_sio_b19200; break; case B38400: priv->cfg.baudrate = kl5kusb105a_sio_b38400; break; case B57600: priv->cfg.baudrate = kl5kusb105a_sio_b57600; break; case B115200: priv->cfg.baudrate = kl5kusb105a_sio_b115200; break; default: err("KLSI USB->Serial converter:" " unsupported baudrate request, using default" " of 9600"); priv->cfg.baudrate = kl5kusb105a_sio_b9600; break; } if ((cflag & CBAUD) == B0 ) { dbg(__FUNCTION__ ": baud is B0"); /* Drop RTS and DTR */ /* maybe this should be simulated by sending read * disable and read enable messages? */ ;#if 0 priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); mct_u232_set_modem_ctrl(serial, priv->control_state);#endif } } if ((cflag & CSIZE) != (old_cflag & CSIZE)) { /* set the number of data bits */ switch (cflag & CSIZE) { case CS5: dbg(__FUNCTION__ " - 5 bits/byte not supported"); return ; case CS6: dbg(__FUNCTION__ " - 6 bits/byte not supported"); return ; case CS7: priv->cfg.databits = kl5kusb105a_dtb_7; break; case CS8: priv->cfg.databits = kl5kusb105a_dtb_8; break; default: err("CSIZE was not CS5-CS8, using default of 8"); priv->cfg.databits = kl5kusb105a_dtb_8; break; } } /* * Update line control register (LCR) */ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) { #if 0 priv->last_lcr = 0; /* set the parity */ if (cflag & PARENB) priv->last_lcr |= (cflag & PARODD) ? MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; else priv->last_lcr |= MCT_U232_PARITY_NONE; /* set the number of stop bits */ priv->last_lcr |= (cflag & CSTOPB) ? MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; mct_u232_set_line_ctrl(serial, priv->last_lcr);#endif ; } /* * Set flow control: well, I do not really now how to handle DTR/RTS. * Just do what we have seen with SniffUSB on Win98. */ if( (iflag & IXOFF) != (old_iflag & IXOFF) || (iflag & IXON) != (old_iflag & IXON) || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) { /* Drop DTR/RTS if no flow control otherwise assert */#if 0 if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) ) priv->control_state |= TIOCM_DTR | TIOCM_RTS; else priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); mct_u232_set_modem_ctrl(serial, priv->control_state);#endif ; } /* now commit changes to device */ klsi_105_chg_port_settings(serial, &(priv->cfg));} /* klsi_105_set_termios */#if 0static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ){ struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; unsigned char lcr = priv->last_lcr; dbg (__FUNCTION__ "state=%d", break_state); if (break_state) lcr |= MCT_U232_SET_BREAK; mct_u232_set_line_ctrl(serial, lcr);} /* mct_u232_break_ctl */#endifstatic int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg){ struct usb_serial *serial = port->serial; struct klsi_105_private *priv = (struct klsi_105_private *)port->private; int mask; dbg (__FUNCTION__ "cmd=0x%x", cmd); /* Based on code from acm.c and others */ switch (cmd) { case TIOCMGET: { int rc; unsigned long line_state; dbg (__FUNCTION__ " - TIOCMGET request, just guessing"); rc = klsi_105_get_line_state(serial, &line_state); if (rc < 0) { err("Reading line control failed (error = %d)", rc); /* better return value? EAGAIN? */ return -ENOIOCTLCMD; } else { priv->line_state = line_state; dbg(__FUNCTION__ " - read line state 0x%lx", line_state); } return put_user(priv->line_state, (unsigned long *) arg); }; 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 (get_user(mask, (unsigned long *) arg)) return -EFAULT; if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { /* RTS needs set */ if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ) dbg (__FUNCTION__ " - set RTS not handled"); /* priv->control_state |= TIOCM_RTS; */ else dbg (__FUNCTION__ " - clear RTS not handled"); /* priv->control_state &= ~TIOCM_RTS; */ } if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { /* DTR needs set */ if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ) dbg (__FUNCTION__ " - set DTR not handled"); /* priv->control_state |= TIOCM_DTR; */ else dbg (__FUNCTION__ " - clear DTR not handled"); /* priv->control_state &= ~TIOCM_DTR; */ } /* mct_u232_set_modem_ctrl(serial, priv->control_state); */ break; case TIOCMIWAIT: /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* TODO */ dbg (__FUNCTION__ " - TIOCMIWAIT not handled"); return -ENOIOCTLCMD; case TIOCGICOUNT: /* return count of modemline transitions */ /* TODO */ dbg (__FUNCTION__ " - TIOCGICOUNT not handled"); return -ENOIOCTLCMD; case TCGETS: { /* return current info to caller */ int retval; dbg (__FUNCTION__ " - TCGETS data faked/incomplete"); retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct termios)); if (retval) return(retval); kernel_termios_to_user_termios((struct termios *)arg, &priv->termios); return(0); } case TCSETS: { /* set port termios to the one given by the user */ int retval; dbg (__FUNCTION__ " - TCSETS not handled"); retval = verify_area(VERIFY_READ, (void *)arg, sizeof(struct termios)); if (retval) return(retval); user_termios_to_kernel_termios(&priv->termios, (struct termios *)arg); klsi_105_set_termios(port, &priv->termios); return(0); } case TCSETSW: { /* set port termios and try to wait for completion of last * write operation */ /* We guess here. If there are not too many write urbs * outstanding, we lie. */ /* what is the right way to wait here? schedule() ? */ /* while (klsi_105_chars_in_buffer(port) > (NUM_URBS / 4 ) * URB_TRANSFER_BUFFER_SIZE) schedule(); */ return -ENOIOCTLCMD; } default: dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd); return(-ENOIOCTLCMD); break; } return 0;} /* klsi_105_ioctl */static void klsi_105_throttle (struct usb_serial_port *port){ dbg(__FUNCTION__ " - port %d", port->number); down (&port->sem); usb_unlink_urb (port->read_urb); up (&port->sem); return;}static void klsi_105_unthrottle (struct usb_serial_port *port){ int result; dbg(__FUNCTION__ " - port %d", port->number); down (&port->sem); port->read_urb->dev = port->serial->dev; result = usb_submit_urb(port->read_urb); if (result) err(__FUNCTION__ " - failed submitting read urb, error %d", result); up (&port->sem); return;}static int __init klsi_105_init (void){ usb_serial_register (&palmconnect_device); usb_serial_register (&kl5kusb105d_device); info(DRIVER_DESC " " DRIVER_VERSION); return 0;}static void __exit klsi_105_exit (void){ usb_serial_deregister (&palmconnect_device); usb_serial_deregister (&kl5kusb105d_device);}module_init (klsi_105_init);module_exit (klsi_105_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "enable extensive debugging messages");/* FIXME: implementMODULE_PARM(num_urbs, "i");MODULE_PARM_DESC(num_urbs, "number of URBs to use in write pool");*//* vim: set sts=8 ts=8 sw=8: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -