📄 mct_u232.c
字号:
goto exit; } port->interrupt_in_urb->dev = port->serial->dev; retval = usb_submit_urb(port->interrupt_in_urb); if (retval) err(" usb_submit_urb(read int) failed"); }exit: up (&port->sem); return 0;} /* mct_u232_open */static void mct_u232_close (struct usb_serial_port *port, struct file *filp){ dbg(__FUNCTION__" port %d", port->number); down (&port->sem); --port->open_count; if (port->open_count <= 0) { if (port->serial->dev) { /* shutdown our urbs */ usb_unlink_urb (port->write_urb); usb_unlink_urb (port->read_urb); usb_unlink_urb (port->interrupt_in_urb); } port->active = 0; } up (&port->sem); MOD_DEC_USE_COUNT;} /* mct_u232_close */#ifdef FIX_WRITE_RETURN_CODE_PROBLEM/* The generic routines work fine otherwise */static int mct_u232_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count){ struct usb_serial *serial = port->serial; int result, bytes_sent, size; 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) return(0);; /* another write is still pending? */ if (port->write_urb->status == -EINPROGRESS) { dbg (__FUNCTION__ " - already writing"); return (0); } bytes_sent = 0; while (count > 0) { down (&port->sem); size = (count > port->bulk_out_size) ? port->bulk_out_size : count; usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf); if (from_user) { if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) { up (&port->sem); return -EFAULT; } } else { memcpy (port->write_urb->transfer_buffer, buf, size); } /* 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, size, ((serial->type->write_bulk_callback) ? serial->type->write_bulk_callback : mct_u232_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); up (&port->sem); return result; } up (&port->sem); bytes_sent += size; if (write_blocking) interruptible_sleep_on(&port->write_wait); else break; buf += size; count -= size; } return bytes_sent;} /* mct_u232_write */static void mct_u232_write_bulk_callback (struct urb *urb){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; struct tty_struct *tty = port->tty; 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; } if (write_blocking) { wake_up_interruptible(&port->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); wake_up_interruptible(&tty->write_wait); } else { /* from generic_write_bulk_callback */ queue_task(&port->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); } return;} /* mct_u232_write_bulk_callback */#endifstatic void mct_u232_read_int_callback (struct urb *urb){ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; struct usb_serial *serial = port->serial; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; dbg(__FUNCTION__ " - port %d", port->number); /* The urb might have been killed. */ if (urb->status) { dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); return; } if (!serial) { dbg(__FUNCTION__ " - bad serial pointer, exiting"); return; } usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); /* * Work-a-round: handle the 'usual' bulk-in pipe here */ if (urb->transfer_buffer_length > 2) { int i; tty = port->tty; if (urb->actual_length) { for (i = 0; i < urb->actual_length ; ++i) { tty_insert_flip_char(tty, data[i], 0); } tty_flip_buffer_push(tty); } /* INT urbs are automatically re-submitted */ return; } /* * The interrupt-in pipe signals exceptional conditions (modem line * signal changes and errors). data[0] holds MSR, data[1] holds LSR. */ priv->last_msr = data[MCT_U232_MSR_INDEX]; /* Record Control Line states */ mct_u232_msr_to_state(&priv->control_state, priv->last_msr);#if 0 /* Not yet handled. See belin_sa.c for further information */ /* Now to report any errors */ priv->last_lsr = data[MCT_U232_LSR_INDEX]; /* * fill in the flip buffer here, but I do not know the relation * to the current/next receive buffer or characters. I need * to look in to this before committing any code. */ if (priv->last_lsr & MCT_U232_LSR_ERR) { tty = port->tty; /* Overrun Error */ if (priv->last_lsr & MCT_U232_LSR_OE) { } /* Parity Error */ if (priv->last_lsr & MCT_U232_LSR_PE) { } /* Framing Error */ if (priv->last_lsr & MCT_U232_LSR_FE) { } /* Break Indicator */ if (priv->last_lsr & MCT_U232_LSR_BI) { } }#endif /* INT urbs are automatically re-submitted */} /* mct_u232_read_int_callback */static void mct_u232_set_termios (struct usb_serial_port *port, struct termios *old_termios){ struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_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"); 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); } switch(cflag & CBAUD) { case B0: /* handled below */ break; case B300: mct_u232_set_baud_rate(serial, 300); break; case B600: mct_u232_set_baud_rate(serial, 600); break; case B1200: mct_u232_set_baud_rate(serial, 1200); break; case B2400: mct_u232_set_baud_rate(serial, 2400); break; case B4800: mct_u232_set_baud_rate(serial, 4800); break; case B9600: mct_u232_set_baud_rate(serial, 9600); break; case B19200: mct_u232_set_baud_rate(serial, 19200); break; case B38400: mct_u232_set_baud_rate(serial, 38400); break; case B57600: mct_u232_set_baud_rate(serial, 57600); break; case B115200: mct_u232_set_baud_rate(serial, 115200); break; default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600"); mct_u232_set_baud_rate(serial, 9600); break; } if ((cflag & CBAUD) == B0 ) { dbg(__FUNCTION__ ": baud is B0"); /* Drop RTS and DTR */ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); mct_u232_set_modem_ctrl(serial, priv->control_state); } } /* * Update line control register (LCR) */ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) || (cflag & CSIZE) != (old_cflag & CSIZE) || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) { 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 data bits */ switch (cflag & CSIZE) { case CS5: priv->last_lcr |= MCT_U232_DATA_BITS_5; break; case CS6: priv->last_lcr |= MCT_U232_DATA_BITS_6; break; case CS7: priv->last_lcr |= MCT_U232_DATA_BITS_7; break; case CS8: priv->last_lcr |= MCT_U232_DATA_BITS_8; break; default: err("CSIZE was not CS5-CS8, using default of 8"); priv->last_lcr |= MCT_U232_DATA_BITS_8; break; } /* 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); } /* * 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 ((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); }} /* mct_u232_set_termios */static 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 */static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg){ struct usb_serial *serial = port->serial; struct mct_u232_private *priv = (struct mct_u232_private *)port->private; int mask; dbg (__FUNCTION__ "cmd=0x%x", cmd); /* Based on code from acm.c and others */ switch (cmd) { case TIOCMGET: 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 (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) ) priv->control_state |= TIOCM_RTS; else priv->control_state &= ~TIOCM_RTS; } if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { /* DTR needs set */ if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ) priv->control_state |= TIOCM_DTR; else 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 */ return( 0 ); case TIOCGICOUNT: /* return count of modemline transitions */ /* TODO */ return 0; default: dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd); return(-ENOIOCTLCMD); break; } return 0;} /* mct_u232_ioctl */static int __init mct_u232_init (void){ usb_serial_register (&mct_u232_device); usb_serial_register (&mct_u232_sitecom_device); usb_serial_register (&mct_u232_du_h3sp_device); info(DRIVER_VERSION ":" DRIVER_DESC); return 0;}static void __exit mct_u232_exit (void){ usb_serial_deregister (&mct_u232_device); usb_serial_deregister (&mct_u232_sitecom_device); usb_serial_deregister (&mct_u232_du_h3sp_device);}module_init (mct_u232_init);module_exit(mct_u232_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");#ifdef FIX_WRITE_RETURN_CODE_PROBLEMMODULE_PARM(write_blocking, "i");MODULE_PARM_DESC(write_blocking, "The write function will block to write out all data");#endifMODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -