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

📄 usb-cdc-eth-raw.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
static int usbc_open( struct inode *pInode, struct file *pFile ){	 DPRINTK("\n");	 usb_ref_count++;	 MOD_INC_USE_COUNT;	 kick_start_rx();	 return 0;}static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,			  size_t stCount, loff_t *pPos ){	ssize_t retval;	int flags;	DECLARE_WAITQUEUE( wait, current );	DPRINTK("\n");	local_irq_save( flags );	if ( last_rx_result == 0 ) {		local_irq_restore( flags );	} else {  /* an error happended and receiver is paused */		local_irq_restore( flags );		last_rx_result = 0;		kick_start_rx();	}	add_wait_queue( &wq_read, &wait );	while ( 1 ) {		ssize_t bytes_avail;		ssize_t bytes_to_end;		set_current_state( TASK_INTERRUPTIBLE );		/* snap ring buf state */		local_irq_save( flags );		bytes_avail  = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );		bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );		local_irq_restore( flags );		if ( bytes_avail != 0 ) {			ssize_t bytes_to_move = MIN( stCount, bytes_avail );			retval = 0;	// will be bytes transfered			if ( bytes_to_move != 0 ) {				size_t n = MIN( bytes_to_end, bytes_to_move );				if ( copy_to_user( pUserBuffer,						   &rx_ring.buf[ rx_ring.out ],						   n ) ) {					retval = -EFAULT;					break;				}				bytes_to_move -= n;				retval += n;				// might go 1 char off end, so wrap				rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);				if ( copy_to_user( pUserBuffer + n,						   &rx_ring.buf[ rx_ring.out ],						   bytes_to_move ) ) {					DPRINTK( "copy_to_user() failed\n" );					retval = -EFAULT;					break;				}				rx_ring.out += bytes_to_move;	// cannot wrap				retval += bytes_to_move;				kick_start_rx();			}			break;		}		else if ( last_rx_result ) {			retval = last_rx_result;			break;		}		else if ( pFile->f_flags & O_NONBLOCK ) {			// no data, can't sleep			DPRINTK( "non blocking\n" );			retval = -EAGAIN;			break;		}		else if ( signal_pending( current ) ) {			// no data, can sleep, but signal  			DPRINTK( "signal pending\n" );			retval = -ERESTARTSYS;			break;		}		schedule();	// no data, can sleep	}	set_current_state( TASK_RUNNING );	remove_wait_queue( &wq_read, &wait );	return retval;}static ssize_t usbc_write( struct file *pFile, const char * pUserBuffer,			   size_t stCount, loff_t *pPos ){	ssize_t retval = 0;	ssize_t stSent = 0;	DECLARE_WAITQUEUE( wait, current );	DPRINTK("%d bytes\n", stCount );	down( &xmit_sem );  // only one thread onto the hardware at a time	while( stCount != 0 && retval == 0 ) {		int nThisTime  = MIN( TX_PACKET_SIZE, stCount );		copy_from_user( tx_buf, pUserBuffer, nThisTime );		sending = nThisTime;		retval = elfin_usb_send( tx_buf, nThisTime, tx_done_callback );		if ( retval < 0 ) {			DPRINTK( "Could not queue xmission. rc=%d\n", retval );			sending = 0;			break;		}		/* now have something on the diving board */		add_wait_queue( &wq_write, &wait );		tx_timer.expires = jiffies + ( HZ * 5 );		add_timer( &tx_timer );		while( 1 ) {			set_current_state( TASK_INTERRUPTIBLE );			if ( sending == 0 ) {  /* it jumped into the pool */				del_timer( &tx_timer );				retval = last_tx_result;				if ( retval == 0 ) {					stSent      += last_tx_size;					pUserBuffer += last_tx_size;					stCount     -= last_tx_size;				}				else					DPRINTK( "xmission error rc=%d\n", retval );				break;			}			else if ( signal_pending( current ) ) {				del_timer( &tx_timer );				DPRINTK( "signal pending\n" );				retval = -ERESTARTSYS;				break;			}			schedule();		}		set_current_state( TASK_RUNNING );		remove_wait_queue( &wq_write, &wait );	}	up( &xmit_sem );	if ( retval == 0 )		retval = stSent;	return retval;}static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ){	unsigned int retval = 0;	DPRINTK("\n");	poll_wait( pFile, &wq_poll, pWait );	if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )		retval |= POLLIN | POLLRDNORM;	if ( elfin_usb_xmitter_avail() )		retval |= POLLOUT | POLLWRNORM;	return retval;}static int usbc_ioctl( struct inode *pInode, struct file *pFile,                       unsigned int nCmd, unsigned long argument ){	int retval = 0;	DPRINTK("cmd: 0x%08x\n", nCmd);	switch( nCmd ) {	case USBC_IOC_FLUSH_RECEIVER:		elfin_usb_recv_reset();		rx_ring.in = rx_ring.out = 0;		break;	case USBC_IOC_FLUSH_TRANSMITTER:		elfin_usb_send_reset();		break;	case USBC_IOC_FLUSH_ALL:		elfin_usb_recv_reset();		rx_ring.in = rx_ring.out = 0;		elfin_usb_send_reset();		break;	default:		retval = -ENOIOCTLCMD;		break;	}	return retval;}static int usbc_close( struct inode *pInode, struct file * pFile ){	DPRINTK("\n");	elfin_usb_recv_reset();	usb_ref_count--;	MOD_DEC_USE_COUNT;	return 0;}//////////////////////////////////////////////////////////////////////////////// Initialization//////////////////////////////////////////////////////////////////////////////static struct file_operations usbc_fops = {	owner:      THIS_MODULE,	open:		usbc_open,	read:		usbc_read,	write:		usbc_write,	poll:		usbc_poll,	ioctl:		usbc_ioctl,	release:	usbc_close,};static struct miscdevice usbc_misc_device = {	USBC_MINOR, "usb_char", &usbc_fops};static int usbc_activate(void){	int retval = 0;	/* start usb core */ 	retval = elfin_usb_open( "usb-cdc-eth-raw" );	if ( retval ) {		printk( "usb-cdc-eth-raw: failed to open USB core\n" );		return retval;	}	twiddle_descriptors();	retval = elfin_usb_start();	if ( retval ) { 		printk( "usb-cdc-eth-raw: failed to start USB core\n" );		elfin_usb_close();		return retval;	}	return 0;}static void usbc_deactivate(void){        down( &xmit_sem );        elfin_usb_stop();        del_timer( &tx_timer );        elfin_usb_close();        up( &xmit_sem );}#ifdef CONFIG_PMstatic struct pm_dev *usbc_pm_dev;static int usbc_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	DPRINTK("req: %d\n", req);        switch (req) {        case PM_RESUME:                usbc_activate();                break;        case PM_SUSPEND:                usbc_deactivate();                break;        }        return 0;}#endif/* * usbc_init() */static int __init usbc_init( void ){	int rc;	if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {		printk("usb-cdc-eth-raw: failed to register device\n");		return rc;	}	// initialize wait queues	init_waitqueue_head( &wq_read );	init_waitqueue_head( &wq_write );	init_waitqueue_head( &wq_poll );	// initialize tx timeout timer	init_timer( &tx_timer );	tx_timer.function = tx_timeout;#ifdef CONFIG_PM	usbc_pm_dev = pm_register(PM_SYS_DEV, MZ_PM_SYS, usbc_pm_callback);#endif	alloc_txrx_buffers();	usbc_activate();	printk("USB Function CDC Ethernet Driver Raw Access Mode Interface\n");	return rc;}static void __exit usbc_exit( void ){	usbc_deactivate();	free_txrx_buffers();	free_string_descriptors();#ifdef CONFIG_PM	if (usbc_pm_dev)		pm_unregister(usbc_pm_dev);#endif	misc_deregister( &usbc_misc_device );}module_init(usbc_init);module_exit(usbc_exit);EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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