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

📄 digi_acceleport.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	for( i=0; i<serial->type->num_ports+1; i++ ) {		port = &serial->port[i];		port->write_urb->dev = port->serial->dev;		if( (ret=usb_submit_urb(port->read_urb)) != 0 ) {			err(			__FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d",			ret, i );			break;		}	}	return( ret );}static int digi_startup( struct usb_serial *serial ){	int i;	digi_port_t *priv;	digi_serial_t *serial_priv;dbg( "digi_startup: TOP" );	/* allocate the private data structures for all ports */	/* number of regular ports + 1 for the out-of-band port */	for( i=0; i<serial->type->num_ports+1; i++ ) {		serial->port[i].active = 0;		/* allocate port private structure */		priv = serial->port[i].private =			(digi_port_t *)kmalloc( sizeof(digi_port_t),			GFP_KERNEL );		if( priv == (digi_port_t *)0 ) {			while( --i >= 0 )				kfree( serial->port[i].private );			return( 1 );			/* error */		}		/* initialize port private structure */		spin_lock_init( &priv->dp_port_lock );		priv->dp_port_num = i;		priv->dp_out_buf_len = 0;		priv->dp_in_buf_len = 0;		priv->dp_write_urb_in_use = 0;		priv->dp_modem_signals = 0;		init_waitqueue_head( &priv->dp_modem_change_wait );		priv->dp_open_count = 0;		priv->dp_transmit_idle = 0;		init_waitqueue_head( &priv->dp_transmit_idle_wait );		priv->dp_throttled = 0;		priv->dp_throttle_restart = 0;		init_waitqueue_head( &priv->dp_flush_wait );		priv->dp_in_close = 0;		init_waitqueue_head( &priv->dp_close_wait );		INIT_LIST_HEAD(&priv->dp_wakeup_task.list);		priv->dp_wakeup_task.sync = 0;		priv->dp_wakeup_task.routine = (void *)digi_wakeup_write_lock;		priv->dp_wakeup_task.data = (void *)(&serial->port[i]);		/* initialize write wait queue for this port */		init_waitqueue_head( &serial->port[i].write_wait );	}	/* allocate serial private structure */	serial_priv = serial->private =		(digi_serial_t *)kmalloc( sizeof(digi_serial_t),		GFP_KERNEL );	if( serial_priv == (digi_serial_t *)0 ) {		for( i=0; i<serial->type->num_ports+1; i++ )			kfree( serial->port[i].private );		return( 1 );			/* error */	}	/* initialize serial private structure */	spin_lock_init( &serial_priv->ds_serial_lock );	serial_priv->ds_oob_port_num = serial->type->num_ports;	serial_priv->ds_oob_port = &serial->port[serial_priv->ds_oob_port_num];	serial_priv->ds_device_started = 0;	return( 0 );}static void digi_shutdown( struct usb_serial *serial ){	int i;	digi_port_t *priv;	unsigned long flags;dbg( "digi_shutdown: TOP, in_interrupt()=%d", in_interrupt() );	/* stop reads and writes on all ports */	for( i=0; i<serial->type->num_ports+1; i++ ) {		usb_unlink_urb( serial->port[i].read_urb );		usb_unlink_urb( serial->port[i].write_urb );	}	/* dec module use count */	for( i=0; i<serial->type->num_ports; i++ ) {		priv = serial->port[i].private;		spin_lock_irqsave( &priv->dp_port_lock, flags );		while( priv->dp_open_count > 0 ) {			MOD_DEC_USE_COUNT;			--priv->dp_open_count;		}		spin_unlock_irqrestore( &priv->dp_port_lock, flags );	}	/* free the private data structures for all ports */	/* number of regular ports + 1 for the out-of-band port */	for( i=0; i<serial->type->num_ports+1; i++ )		kfree( serial->port[i].private );	kfree( serial->private );}static void digi_read_bulk_callback( struct urb *urb ){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	digi_port_t *priv;	int ret;dbg( "digi_read_bulk_callback: TOP" );	/* port sanity check, do not resubmit if port is not valid */	if( port == NULL || (priv=(digi_port_t *)(port->private)) == NULL ) {		err( __FUNCTION__ ": port or port->private is NULL, status=%d",			urb->status );		return;	}	if( port->serial == NULL	|| serial_paranoia_check( port->serial, __FUNCTION__ )	|| port->serial->private == NULL ) {		err( __FUNCTION__ ": serial is bad or serial->private is NULL, status=%d", urb->status );		return;	}	/* do not resubmit urb if it has any status error */	if( urb->status ) {		err( __FUNCTION__ ": nonzero read bulk status: status=%d, port=%d", urb->status, priv->dp_port_num );		return;	}	/* handle oob or inb callback, do not resubmit if error */	if( priv->dp_port_num	== ((digi_serial_t *)(port->serial->private))->ds_oob_port_num ) {		if( digi_read_oob_callback( urb ) != 0 )			return;	} else {		if( digi_read_inb_callback( urb ) != 0 )			return;	}	/* continue read */	urb->dev = port->serial->dev;	if( (ret=usb_submit_urb(urb)) != 0 ) {		err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d",			ret, priv->dp_port_num );	}}/* *  Digi Read INB Callback**  Digi Read INB Callback handles reads on the in band ports, sending*  the data on to the tty subsystem.  When called we know port and*  port->private are not NULL and port->serial has been validated.*  It returns 0 if successful, 1 if successful but the port is*  throttled, and -1 if the sanity checks failed.*/static int digi_read_inb_callback( struct urb *urb ){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct tty_struct *tty = port->tty;	digi_port_t *priv = (digi_port_t *)(port->private);	int opcode = ((unsigned char *)urb->transfer_buffer)[0];	int len = ((unsigned char *)urb->transfer_buffer)[1];	int status = ((unsigned char *)urb->transfer_buffer)[2];	unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;	int flag,throttled;	/* sanity check */	if( port_paranoia_check( port, __FUNCTION__ ) )		return( -1 );	/* do not process callbacks on closed ports */	/* but do continue the read chain */	if( priv->dp_open_count == 0 )		return( 0 );	/* short/multiple packet check */	if( urb->actual_length != len + 2 ) {     		err( __FUNCTION__ ": INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status );		return( -1 );	}	spin_lock( &priv->dp_port_lock );	/* check for throttle; if set, do not resubmit read urb */	/* indicate the read chain needs to be restarted on unthrottle */	throttled = priv->dp_throttled;	if( throttled )		priv->dp_throttle_restart = 1;	/* receive data */	if( opcode == DIGI_CMD_RECEIVE_DATA ) {		/* get flag from status */		flag = 0;		/* overrun is special, not associated with a char */		if( status & DIGI_OVERRUN_ERROR ) {			tty_insert_flip_char( tty, 0, TTY_OVERRUN );		}		/* break takes precedence over parity, */		/* which takes precedence over framing errors */		if( status & DIGI_BREAK_ERROR ) {			flag = TTY_BREAK;		} else if( status & DIGI_PARITY_ERROR ) {			flag = TTY_PARITY;		} else if( status & DIGI_FRAMING_ERROR ) {			flag = TTY_FRAME;		}		/* data length is len-1 (one byte of len is status) */		--len;		if( throttled ) {			len = min( len,				DIGI_IN_BUF_SIZE - priv->dp_in_buf_len );			if( len > 0 ) {				memcpy( priv->dp_in_buf + priv->dp_in_buf_len,					data, len );				memset( priv->dp_in_flag_buf					+ priv->dp_in_buf_len, flag, len );				priv->dp_in_buf_len += len;			}		} else {			len = min( len, TTY_FLIPBUF_SIZE - tty->flip.count );			if( len > 0 ) {				memcpy( tty->flip.char_buf_ptr, data, len );				memset( tty->flip.flag_buf_ptr, flag, len );				tty->flip.char_buf_ptr += len;				tty->flip.flag_buf_ptr += len;				tty->flip.count += len;				tty_flip_buffer_push( tty );			}		}	}	spin_unlock( &priv->dp_port_lock );	if( opcode == DIGI_CMD_RECEIVE_DISABLE ) {		dbg( __FUNCTION__ ": got RECEIVE_DISABLE" );	} else if( opcode != DIGI_CMD_RECEIVE_DATA ) {		dbg( __FUNCTION__ ": unknown opcode: %d", opcode );	}	return( throttled ? 1 : 0 );}/* *  Digi Read OOB Callback**  Digi Read OOB Callback handles reads on the out of band port.*  When called we know port and port->private are not NULL and*  the port->serial is valid.  It returns 0 if successful, and*  -1 if the sanity checks failed.*/static int digi_read_oob_callback( struct urb *urb ){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = port->serial;	digi_port_t *priv = (digi_port_t *)(port->private);	int opcode, line, status, val;	int i;dbg( "digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num,urb->actual_length );	/* handle each oob command */	for( i=0; i<urb->actual_length-3; ) {		opcode = ((unsigned char *)urb->transfer_buffer)[i++];		line = ((unsigned char *)urb->transfer_buffer)[i++];		status = ((unsigned char *)urb->transfer_buffer)[i++];		val = ((unsigned char *)urb->transfer_buffer)[i++];dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d",opcode, line, status, val );		if( status != 0 || line >= serial->type->num_ports )			continue;		port = &serial->port[line];		if( port_paranoia_check( port, __FUNCTION__ )		|| (priv=port->private) == NULL )			return( -1 );		if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) {			spin_lock( &priv->dp_port_lock );			/* convert from digi flags to termiox flags */			if( val & DIGI_READ_INPUT_SIGNALS_CTS ) {				priv->dp_modem_signals |= TIOCM_CTS;				/* port must be open to use tty struct */				if( priv->dp_open_count				&& port->tty->termios->c_cflag & CRTSCTS ) {					port->tty->hw_stopped = 0;					digi_wakeup_write( port );				}			} else {				priv->dp_modem_signals &= ~TIOCM_CTS;				/* port must be open to use tty struct */				if( priv->dp_open_count				&& port->tty->termios->c_cflag & CRTSCTS ) {					port->tty->hw_stopped = 1;				}			}			if( val & DIGI_READ_INPUT_SIGNALS_DSR )				priv->dp_modem_signals |= TIOCM_DSR;			else				priv->dp_modem_signals &= ~TIOCM_DSR;			if( val & DIGI_READ_INPUT_SIGNALS_RI )				priv->dp_modem_signals |= TIOCM_RI;			else				priv->dp_modem_signals &= ~TIOCM_RI;			if( val & DIGI_READ_INPUT_SIGNALS_DCD )				priv->dp_modem_signals |= TIOCM_CD;			else				priv->dp_modem_signals &= ~TIOCM_CD;			wake_up_interruptible( &priv->dp_modem_change_wait );			spin_unlock( &priv->dp_port_lock );		} else if( opcode == DIGI_CMD_TRANSMIT_IDLE ) {			spin_lock( &priv->dp_port_lock );			priv->dp_transmit_idle = 1;			wake_up_interruptible( &priv->dp_transmit_idle_wait );			spin_unlock( &priv->dp_port_lock );		} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {			wake_up_interruptible( &priv->dp_flush_wait );		}	}	return( 0 );}static int __init digi_init (void){	usb_serial_register (&digi_acceleport_2_device);	usb_serial_register (&digi_acceleport_4_device);	info(DRIVER_VERSION ":" DRIVER_DESC);	return 0;}static void __exit digi_exit (void){	usb_serial_deregister (&digi_acceleport_2_device);	usb_serial_deregister (&digi_acceleport_4_device);}module_init(digi_init);module_exit(digi_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -