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

📄 usb-char.c

📁 编写的BOOTLOADER用于s3c2410的启动代码,直接引导自己的应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) Copyright 2000-2001 MIZI Research, Inc. * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2 of the License, or *	(at your option) any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  usb-char.c * *  Miscellaneous character device interface for S3C2410 USB function *	driver. */#include <linux/module.h>#include <linux/config.h>#include <linux/miscdevice.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/cache.h>#include <linux/poll.h>#include <linux/circ_buf.h>#include <linux/timer.h>#include <asm/io.h>#include <asm/semaphore.h>#include <asm/proc/page.h>#include <asm/mach-types.h>#include "usb-char.h"#include "s3c2410_usb.h"#ifdef CONFIG_MIZI#include <asm/irq.h>#ifdef CONFIG_PM#include <linux/pm.h>static struct pm_dev *usb_char_pm_dev;#endif#endif//////////////////////////////////////////////////////////////////////////////// Driver  Options//////////////////////////////////////////////////////////////////////////////#ifdef CONFIG_MIZI#define VERSION		"0.5"#define LINUETTE_VENDOR_ID	0x49f#define LINUETTE_PRODUCT_ID	0x505A#define LINUETTE_REV_NUM 1 #define USB_CHAR_MANUFACTURE	"MIZI Research Inc."#define USB_CHAR_FOR_WHAT	"linu@usb"#define USB_CHAR_BUILD_DATE	"20020115"#define USB_CHAR_INTERFACE	"Bulk Transfer"#else#define VERSION		"0.4"#endif//#define VERBOSITY 1#if VERBOSITY# define	PRINTK(a...)	printk(__FILE__":"__FUNCTION__"(): " ##a)#else# define	PRINTK(a...)	(void)(0)#endif//////////////////////////////////////////////////////////////////////////////// Globals - Macros - Enums - Structures//////////////////////////////////////////////////////////////////////////////#ifndef MIN#define MIN( a, b ) ((a)<(b)?(a):(b))#endiftypedef int bool; enum { false = 0, true = 1 };static const char pszMe[] = "usbchr: ";static wait_queue_head_t wq_read;static wait_queue_head_t wq_write;static wait_queue_head_t wq_poll;/* Serialze multiple writers onto the transmit hardware.. since we sleep the writer during transmit to stay in.. sync. (Multiple writers don't make much sense, but..) */static DECLARE_MUTEX( xmit_sem );// size of usb DATA0/1 packets. 64 is standard maximum// for bulk transport, though most hosts seem to be able// to handle larger.#define TX_PACKET_SIZE 64#define RX_PACKET_SIZE 64#define RBUF_SIZE  (4*PAGE_SIZE)static struct wcirc_buf {  char *buf;  int in;  int out;} rx_ring = { NULL, 0, 0 };static struct {	 unsigned long  cnt_rx_complete;	 unsigned long  cnt_rx_errors;	 unsigned long  bytes_rx;	 unsigned long  cnt_tx_timeouts;	 unsigned long  cnt_tx_errors;	 unsigned long  bytes_tx;} charstats;static char * tx_buf = NULL;static char * packet_buffer = NULL;static int sending = 0;static int usb_ref_count = 0;static int last_tx_result = 0;static int last_rx_result = 0;static int last_tx_size = 0;static struct timer_list tx_timer;//////////////////////////////////////////////////////////////////////////////// Prototypes//////////////////////////////////////////////////////////////////////////////#ifndef CONFIG_MIZIstatic char * 	what_the_f( int e );#endifstatic void 	free_txrx_buffers( void );static void     twiddle_descriptors( void );static void     free_string_descriptors( void ) ;static int      usbc_open( struct inode *pInode, struct file *pFile );static void     rx_done_callback_packet_buffer( int flag, int size );static void     tx_timeout( unsigned long );static void     tx_done_callback( int flag, int size );static ssize_t  usbc_read( struct file *, char *, size_t, loff_t * );static ssize_t  usbc_write( struct file *, const char *, size_t, loff_t * );static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );static int usbc_ioctl( struct inode *pInode, struct file *pFile,                       unsigned int nCmd, unsigned long argument );static int      usbc_close( struct inode *pInode, struct file *pFile );#ifdef CONFIG_S3C2410_EXTENEX1static void     extenex_configured_notify_proc( void );#endif#ifdef CONFIG_MIZIstatic int usbc_activate(void);static void usbc_deactivate(void);#endif//////////////////////////////////////////////////////////////////////////////// Private Helpers//////////////////////////////////////////////////////////////////////////////#if defined(CONFIG_PM) && defined(CONFIG_MIZI)extern void usbctl_suspend(void);extern void usbctl_resume(void);static intusbchar_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	PRINTK("pm_callback: %d\n", req);	switch (req) {	case PM_RESUME:    		usbctl_resume();		usbc_activate();		PRINTK("usb-char wakeup...");		break;	case PM_SUSPEND:   		usbc_deactivate();		usbctl_suspend();		PRINTK("usb-char sleep...");		break;	}	PRINTK("done\n"); 	return 0;}#endif#ifndef CONFIG_MIZIstatic char * what_the_f( int e ){	 char * p;	 switch( e ) {	 case 0:		  p = "noErr";		  break;	 case -ENODEV:		  p = "ENODEV - usb not in config state";		  break;	 case -EBUSY:		  p = "EBUSY - another request on the hardware";		  break;	 case -EAGAIN:		  p = "EAGAIN";		  break;	 case -EINTR:		  p = "EINTR - interrupted\n";		  break;	 case -EPIPE:		  p = "EPIPE - zero length xfer\n";		  break;	 default:		  p = "????";		  break;	 }	 return p;}#endifstatic void free_txrx_buffers( void ){	PRINTK("\n");	 if ( rx_ring.buf != NULL ) {		  kfree( rx_ring.buf );		  rx_ring.buf = NULL;	 }	 if ( packet_buffer != NULL ) {		  kfree( packet_buffer );		  packet_buffer = NULL;	 }	 if ( tx_buf != NULL ) {		  kfree( tx_buf );		  tx_buf = NULL;	 }}/* twiddle_descriptors() * It is between open() and start(). Setup descriptors. */static void twiddle_descriptors( void ){	 desc_t * pDesc = s3c2410_usb_get_descriptor_ptr();	 string_desc_t * pString;	PRINTK("\n");	 pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );	 pDesc->b.ep1.bmAttributes   = USB_EP_BULK;	 pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );	 pDesc->b.ep2.bmAttributes   = USB_EP_BULK;#ifdef CONFIG_MIZI	pDesc->dev.idVendor = LINUETTE_VENDOR_ID;	pDesc->dev.idProduct = LINUETTE_PRODUCT_ID;	pDesc->dev.bcdDevice = LINUETTE_REV_NUM;	pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;	pDesc->b.cfg.MaxPower = 0;	if (s3c2410_usb_get_string_descriptor(4)) return;	pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_MANUFACTURE);	if ( pString ) {		s3c2410_usb_set_string_descriptor( 1, pString );		pDesc->dev.iManufacturer = 1;	}	pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_FOR_WHAT );	if ( pString ) {		s3c2410_usb_set_string_descriptor( 2, pString );		pDesc->dev.iProduct = 2;	}	pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_BUILD_DATE );	if ( pString ) {		s3c2410_usb_set_string_descriptor( 3, pString );		pDesc->dev.iSerialNumber = 3;	}	pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_INTERFACE );	if ( pString ) {		s3c2410_usb_set_string_descriptor( 4, pString );		pDesc->b.intf.iInterface = 4;	}#endif}static void free_string_descriptors( void ){	PRINTK("\n");	 if ( machine_is_extenex1() ) {		  string_desc_t * pString;		  int i;		  for( i = 1 ; i <= 4 ; i++ ) {			   pString = s3c2410_usb_get_string_descriptor( i );			   if ( pString )					kfree( pString );		  }	 }#ifdef CONFIG_MIZI	{		string_desc_t * pString;		int i;		for( i = 1 ; i <= 4 ; i++ ) {			pString = s3c2410_usb_get_string_descriptor( i );			if ( pString )				kfree( pString );			s3c2410_usb_set_string_descriptor( i , NULL);		}	}#endif}//////////////////////////////////////////////////////////////////////////////// ASYNCHRONOUS//////////////////////////////////////////////////////////////////////////////static  void kick_start_rx( void ){	PRINTK("\n");#if defined(CONFIG_MIZI) 	 {#else	    // PRINTK("i'm not  MIZI - %d\n", usb_ref_count);	 if ( usb_ref_count ) {#endif		  int total_space  = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );//	     		PRINTK("total_space = %d, %d\n", total_space, RX_PACKET_SIZE);		  if ( total_space >= RX_PACKET_SIZE ) {			   s3c2410_usb_recv( packet_buffer,								RX_PACKET_SIZE,								rx_done_callback_packet_buffer						      );		  }	 }}/* * rx_done_callback_packet_buffer() * We have completed a DMA xfer into the temp packet buffer. * Move to ring. * * flag values: * on init,  -EAGAIN * on reset, -EINTR * on RPE, -EIO * on short packet -EPIPE */static voidrx_done_callback_packet_buffer( int flag, int size ){	 charstats.cnt_rx_complete++;	PRINTK("\n");	 if ( flag == 0 || flag == -EPIPE ) {		  size_t n;		  charstats.bytes_rx += size;		  n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );		  n = MIN( n, size );		  size -= n;		  memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );		  rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);		  memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );		  rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);		  wake_up_interruptible( &wq_read );		  wake_up_interruptible( &wq_poll );		  last_rx_result = 0;		  kick_start_rx();	 } else if ( flag != -EAGAIN ) {		  charstats.cnt_rx_errors++;		  last_rx_result = flag;		  wake_up_interruptible( &wq_read );		  wake_up_interruptible( &wq_poll );	 }	 else  /* init, start a read */		  kick_start_rx();}static void tx_timeout( unsigned long unused ){	PRINTK( "%stx timeout\n", pszMe );	s3c2410_usb_send_reset();	charstats.cnt_tx_timeouts++;}// on init, -EAGAIN// on reset, -EINTR// on TPE, -EIOstatic void tx_done_callback( int flags, int size ){	PRINTK("\n");	 if ( flags == 0 )		  charstats.bytes_tx += size;	 else		  charstats.cnt_tx_errors++;	 last_tx_size = size;	 last_tx_result = flags;	 sending = 0;	 wake_up_interruptible( &wq_write );

⌨️ 快捷键说明

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