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

📄 usb-char.c

📁 编写的BOOTLOADER用于s3c2410的启动代码,直接引导自己的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	 wake_up_interruptible( &wq_poll );}//////////////////////////////////////////////////////////////////////////////// Workers//////////////////////////////////////////////////////////////////////////////#ifdef CONFIG_MIZIstatic void usbc_alloc_mem(void){	PRINTK("\n");	tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );	if ( tx_buf == NULL ) {		PRINTK( "%sARGHH! COULD NOT ALLOCATE TX BUFFER\n", pszMe );	}	rx_ring.buf = (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );	if ( rx_ring.buf == NULL ) {		PRINTK( "%sARGHH! COULD NOT ALLOCATE RX BUFFER\n", pszMe );	}	packet_buffer = (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );	if ( packet_buffer == NULL ) {		PRINTK( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n",pszMe);	}	//usbc_ioctl(0, 0, USBC_IOC_FLUSH_ALL, 0);}#endifstatic int usbc_open( struct inode *pInode, struct file *pFile ){	 MOD_INC_USE_COUNT;	 kick_start_rx();	 return 0;}/* * Read endpoint. Note that you can issue a read to an * unconfigured endpoint. Eventually, the host may come along * and configure underneath this module and data will appear. */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 );	// PRINTK( "count=%d", stCount);	 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 )						 ) {						 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			   retval = -EAGAIN;			   break;		  }		  else if ( signal_pending( current ) ) {   // no data, can sleep, but signal			   retval = -ERESTARTSYS;			   break;		  }		  schedule();					   			// no data, can sleep	 }	 set_current_state( TASK_RUNNING );	 remove_wait_queue( &wq_read, &wait );#ifndef CONFIG_MIZI	 if ( retval < 0 )		  printk( "%sread error %d - %s\n", pszMe, retval, what_the_f( retval ) );#endif	 return retval;}/* * Write endpoint. This routine attempts to break the passed in buffer * into usb DATA0/1 packet size chunks and send them to the host. * (The lower-level driver tries to do this too, but easier for us * to manage things here.) * * We are at the mercy of the host here, in that it must send an IN * token to us to pull this data back, so hopefully some higher level * protocol is expecting traffic to flow in that direction so the host * is actually polling us. To guard against hangs, a 5 second timeout * is used. * * This routine takes some care to only report bytes sent that have * actually made it across the wire. Thus we try to stay in lockstep * with the completion routine and only have one packet on the xmit * hardware at a time. Multiple simultaneous writers will get * "undefined" results. *  */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 );	 PRINTK( KERN_DEBUG "%swrite() %d bytes\n", pszMe, 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 = s3c2410_usb_send( tx_buf, nThisTime, tx_done_callback );		  if ( retval < 0 ) {#ifndef CONFIG_MIZI			   char * p = what_the_f( retval );			   printk( "%sCould not queue xmission. rc=%d - %s\n",					   pszMe, retval, p );#endif			   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;					}#ifndef CONFIG_MIZI					else						 printk( "%sxmission error rc=%d - %s\n",								 pszMe, retval, what_the_f(retval) );#endif					break;			   }			   else if ( signal_pending( current ) ) {					del_timer( &tx_timer );					PRINTK( "%ssignal\n", pszMe  );					retval = -ERESTARTSYS;					break;			   }			   schedule();		  }		  set_current_state( TASK_RUNNING );		  remove_wait_queue( &wq_write, &wait );	 }	 up( &xmit_sem );	 if ( 0 == retval )		  retval = stSent;	 return retval;}static unsigned int usbc_poll( struct file *pFile, poll_table * pWait ){	 unsigned int retval = 0;	 PRINTK( KERN_DEBUG "%poll()\n", pszMe );	 poll_wait( pFile, &wq_poll, pWait );	 if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )		  retval |= POLLIN | POLLRDNORM;	 if ( s3c2410_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;	 switch( nCmd ) {	 case USBC_IOC_FLUSH_RECEIVER:		  s3c2410_usb_recv_reset();		  rx_ring.in = rx_ring.out = 0;		  break;	 case USBC_IOC_FLUSH_TRANSMITTER:		  s3c2410_usb_send_reset();		  break;	 case USBC_IOC_FLUSH_ALL:		  s3c2410_usb_recv_reset();		  rx_ring.in = rx_ring.out = 0;		  s3c2410_usb_send_reset();		  break;	 default:		  retval = -ENOIOCTLCMD;		  break;	 }	 return retval;}#ifdef CONFIG_MIZIstatic intusbc_activate(void){	int retval = 0;	PRINTK("\n");	/* start usb core */	retval = s3c2410_usb_open( "usb-char" );	twiddle_descriptors();	retval = s3c2410_usb_start();	if ( retval ) {		PRINTK( "%sAGHH! Could not USB core\n", pszMe );		free_txrx_buffers();		return retval;	}	usb_ref_count++;   /* must do _before_ kick_start() */	kick_start_rx();	return 0;}static voidusbc_deactivate(void){	PRINTK("\n");	down( &xmit_sem );	s3c2410_usb_stop();	del_timer( &tx_timer );	s3c2410_usb_close();	up( &xmit_sem );}#endifstatic int usbc_close( struct inode *pInode, struct file * pFile ){	PRINTK( KERN_DEBUG "%sclose()\n", pszMe );#ifdef CONFIG_MIZI	--usb_ref_count;#else	if ( --usb_ref_count == 0 ) {		 down( &xmit_sem );		 s3c2410_usb_stop();		 free_txrx_buffers();		 free_string_descriptors();		 del_timer( &tx_timer );		 s3c2410_usb_close();		 up( &xmit_sem );	}#endif    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};/* * usbc_init() */int __init usbc_init( void ){	 int rc;#if !defined( CONFIG_ARCH_S3C2410 )	 return -ENODEV;#endif	 if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {		  printk( KERN_WARNING "%sCould not register device 10, "				  "%d. (%d)\n", pszMe, USBC_MINOR, rc );		  return -EBUSY;	 }	 // 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_MIZI	memset( &charstats, 0, sizeof( charstats ) );	sending = 0;	last_tx_result = 0;	last_tx_size = 0;#endif	printk( KERN_INFO "USB Function Character Driver Interface"		" - %s, (C) 2001, Extenex Corp.\n", VERSION); #ifdef CONFIG_MIZI#ifdef CONFIG_PM	usb_char_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_MISC,				      usbchar_pm_callback);#endif	usbc_alloc_mem();	usbc_activate();#endif	 return rc;}void __exit usbc_exit( void ){#ifdef CONFIG_MIZI	usbc_deactivate();	free_txrx_buffers();	free_string_descriptors();#ifdef CONFIG_PM	if (usb_char_pm_dev)		pm_unregister(usb_char_pm_dev);#endif #endif	misc_deregister( &usbc_misc_device );}EXPORT_NO_SYMBOLS;module_init(usbc_init);module_exit(usbc_exit);// end: usb-char.c

⌨️ 快捷键说明

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