📄 digi_acceleport.c
字号:
oob_port->write_urb->transfer_buffer_length = 8; oob_port->write_urb->dev = port->serial->dev; if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) { oob_priv->dp_write_urb_in_use = 1; port_priv->dp_modem_signals = (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) | (modem_signals&(TIOCM_DTR|TIOCM_RTS)); } spin_unlock( &port_priv->dp_port_lock ); spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); if( ret ) { err( __FUNCTION__ ": usb_submit_urb failed, ret=%d", ret ); } return( ret );}/** Digi Transmit Idle** Digi transmit idle waits, up to timeout ticks, for the transmitter* to go idle. It returns 0 if successful or a negative error.** There are race conditions here if more than one process is calling* digi_transmit_idle on the same port at the same time. However, this* is only called from close, and only one process can be in close on a* port at a time, so its ok.*/static int digi_transmit_idle( struct usb_serial_port *port, unsigned long timeout ){ int ret; unsigned char buf[2]; digi_port_t *priv = (digi_port_t *)(port->private); unsigned long flags = 0; spin_lock_irqsave( &priv->dp_port_lock, flags ); priv->dp_transmit_idle = 0; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); buf[0] = DIGI_CMD_TRANSMIT_IDLE; buf[1] = 0; timeout += jiffies; if( (ret=digi_write_inb_command( port, buf, 2, timeout-jiffies )) != 0 ) return( ret ); spin_lock_irqsave( &priv->dp_port_lock, flags ); while( jiffies < timeout && !priv->dp_transmit_idle ) { cond_wait_interruptible_timeout_irqrestore( &priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT, &priv->dp_port_lock, flags ); if( signal_pending(current) ) { return( -EINTR ); } spin_lock_irqsave( &priv->dp_port_lock, flags ); } priv->dp_transmit_idle = 0; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( 0 );}static void digi_rx_throttle( struct usb_serial_port *port ){ unsigned long flags; digi_port_t *priv = (digi_port_t *)(port->private);dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num ); /* stop receiving characters by not resubmitting the read urb */ spin_lock_irqsave( &priv->dp_port_lock, flags ); priv->dp_throttled = 1; priv->dp_throttle_restart = 0; priv->dp_in_buf_len = 0; spin_unlock_irqrestore( &priv->dp_port_lock, flags );}static void digi_rx_unthrottle( struct usb_serial_port *port ){ int ret = 0; int len; unsigned long flags; digi_port_t *priv = (digi_port_t *)(port->private); struct tty_struct *tty = port->tty;dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); spin_lock_irqsave( &priv->dp_port_lock, flags ); /* send any buffered chars from throttle time on to tty subsystem */ len = min(priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count ); if( len > 0 ) { memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len ); memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len ); tty->flip.char_buf_ptr += len; tty->flip.flag_buf_ptr += len; tty->flip.count += len; tty_flip_buffer_push( tty ); } /* restart read chain */ if( priv->dp_throttle_restart ) { port->read_urb->dev = port->serial->dev; ret = usb_submit_urb( port->read_urb ); } /* turn throttle off */ priv->dp_throttled = 0; priv->dp_in_buf_len = 0; priv->dp_throttle_restart = 0; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); if( ret ) { err( __FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d", ret, priv->dp_port_num ); }}static void digi_set_termios( struct usb_serial_port *port, struct termios *old_termios ){ digi_port_t *priv = (digi_port_t *)(port->private); unsigned int iflag = port->tty->termios->c_iflag; unsigned int cflag = port->tty->termios->c_cflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int old_cflag = old_termios->c_cflag; unsigned char buf[32]; unsigned int modem_signals; int arg,ret; int i = 0;dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag ); /* set baud rate */ if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { arg = -1; /* reassert DTR and (maybe) RTS on transition from B0 */ if( (old_cflag&CBAUD) == B0 ) { /* don't set RTS if using hardware flow control */ /* and throttling input */ modem_signals = TIOCM_DTR; if( !(port->tty->termios->c_cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &port->tty->flags) ) { modem_signals |= TIOCM_RTS; } digi_set_modem_signals( port, modem_signals, 1 ); } switch( (cflag&CBAUD) ) { /* drop DTR and RTS on transition to B0 */ case B0: digi_set_modem_signals( port, 0, 1 ); break; case B50: arg = DIGI_BAUD_50; break; case B75: arg = DIGI_BAUD_75; break; case B110: arg = DIGI_BAUD_110; break; case B150: arg = DIGI_BAUD_150; break; case B200: arg = DIGI_BAUD_200; break; case B300: arg = DIGI_BAUD_300; break; case B600: arg = DIGI_BAUD_600; break; case B1200: arg = DIGI_BAUD_1200; break; case B1800: arg = DIGI_BAUD_1800; break; case B2400: arg = DIGI_BAUD_2400; break; case B4800: arg = DIGI_BAUD_4800; break; case B9600: arg = DIGI_BAUD_9600; break; case B19200: arg = DIGI_BAUD_19200; break; case B38400: arg = DIGI_BAUD_38400; break; case B57600: arg = DIGI_BAUD_57600; break; case B115200: arg = DIGI_BAUD_115200; break; case B230400: arg = DIGI_BAUD_230400; break; case B460800: arg = DIGI_BAUD_460800; break; default: dbg( "digi_set_termios: can't handle baud rate 0x%x", (cflag&CBAUD) ); break; } if( arg != -1 ) { buf[i++] = DIGI_CMD_SET_BAUD_RATE; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } } /* set parity */ if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { if( (cflag&PARENB) ) { if( (cflag&PARODD) ) arg = DIGI_PARITY_ODD; else arg = DIGI_PARITY_EVEN; } else { arg = DIGI_PARITY_NONE; } buf[i++] = DIGI_CMD_SET_PARITY; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } /* set word size */ if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { arg = -1; switch( (cflag&CSIZE) ) { case CS5: arg = DIGI_WORD_SIZE_5; break; case CS6: arg = DIGI_WORD_SIZE_6; break; case CS7: arg = DIGI_WORD_SIZE_7; break; case CS8: arg = DIGI_WORD_SIZE_8; break; default: dbg( "digi_set_termios: can't handle word size %d", (cflag&CSIZE) ); break; } if( arg != -1 ) { buf[i++] = DIGI_CMD_SET_WORD_SIZE; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } } /* set stop bits */ if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) { if( (cflag&CSTOPB) ) arg = DIGI_STOP_BITS_2; else arg = DIGI_STOP_BITS_1; buf[i++] = DIGI_CMD_SET_STOP_BITS; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } /* set input flow control */ if( (iflag&IXOFF) != (old_iflag&IXOFF) || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { arg = 0; if( (iflag&IXOFF) ) arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF; else arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF; if( (cflag&CRTSCTS) ) { arg |= DIGI_INPUT_FLOW_CONTROL_RTS; /* On USB-4 it is necessary to assert RTS prior */ /* to selecting RTS input flow control. */ buf[i++] = DIGI_CMD_SET_RTS_SIGNAL; buf[i++] = priv->dp_port_num; buf[i++] = DIGI_RTS_ACTIVE; buf[i++] = 0; } else { arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS; } buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } /* set output flow control */ if( (iflag&IXON) != (old_iflag&IXON) || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { arg = 0; if( (iflag&IXON) ) arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; else arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; if( (cflag&CRTSCTS) ) { arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS; } else { arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS; port->tty->hw_stopped = 0; } buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } /* set receive enable/disable */ if( (cflag&CREAD) != (old_cflag&CREAD) ) { if( (cflag&CREAD) ) arg = DIGI_ENABLE; else arg = DIGI_DISABLE; buf[i++] = DIGI_CMD_RECEIVE_ENABLE; buf[i++] = priv->dp_port_num; buf[i++] = arg; buf[i++] = 0; } if( (ret=digi_write_oob_command( port, buf, i, 1 )) != 0 ) dbg( "digi_set_termios: write oob failed, ret=%d", ret );}static void digi_break_ctl( struct usb_serial_port *port, int break_state ){ unsigned char buf[4]; buf[0] = DIGI_CMD_BREAK_CONTROL; buf[1] = 2; /* length */ buf[2] = break_state ? 1 : 0; buf[3] = 0; /* pad */ digi_write_inb_command( port, buf, 4, 0 );}static int digi_ioctl( struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg ){ digi_port_t *priv = (digi_port_t *)(port->private); unsigned int val; unsigned long flags = 0;dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd ); switch (cmd) { case TIOCMGET: spin_lock_irqsave( &priv->dp_port_lock, flags ); val = priv->dp_modem_signals; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); if( copy_to_user((unsigned int *)arg, &val, sizeof(int)) ) return( -EFAULT ); return( 0 ); case TIOCMSET: case TIOCMBIS: case TIOCMBIC: if( copy_from_user(&val, (unsigned int *)arg, sizeof(int)) ) return( -EFAULT ); spin_lock_irqsave( &priv->dp_port_lock, flags ); if( cmd == TIOCMBIS ) val = priv->dp_modem_signals | val; else if( cmd == TIOCMBIC ) val = priv->dp_modem_signals & ~val; spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return( digi_set_modem_signals( port, val, 1 ) ); 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; } return( -ENOIOCTLCMD );}static int digi_write( struct usb_serial_port *port, int from_user, const unsigned char *buf, int count ){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -