⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 digi_acceleport.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -