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

📄 usb-cdc-eth-raw.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * CDC Ethernet Raw Access Mode driver for the PXA USB client function * Based on linux/arch/arm/mach-pxa/usb-cdc-eth.c and usb-char.c * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/module.h>#include <linux/config.h>#include <linux/miscdevice.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/circ_buf.h>#include <linux/timer.h>#ifdef CONFIG_PM#include <linux/pm.h>#endif#include <asm/hardware.h>#include "s3c2440_usb.h"/* for using major, minor and ioctl command numbers of usb-char */#include "usb-char.h"//////////////////////////////////////////////////////////////////////////////// Globals - Macros - Enums - Structures///////////////////////////////////////////////////////////////////////////////* Define this for debug messages */#undef DEBUG#ifdef DEBUG#define DPRINTK(X...) { printk(__FUNCTION__); printk ("(): "); printk(X); }#else#define DPRINTK(X...) do { } while (0);#endif/* Define this for random remote MAC address */#undef USE_RANDOM_REMOTE_MAC#ifdef CONFIG_S3C2440_SMDK#define ETHERNET_VENDOR_ID 0x4e8#define ETHERNET_PRODUCT_ID 0x661d#define ETHERNET_REV_NUM        0x100#define ETHERNET_MANUFACTURE    "SAMSUNG Electronics Co.,Ltd."#define ETHERNET_FOR_WHAT       "i519"#else#define ETHERNET_VENDOR_ID 0x49f#define ETHERNET_PRODUCT_ID 0x505A#endif#ifndef MIN#define MIN( a, b ) ((a)<(b)?(a):(b))#endif/* size of usb data tx/rx packets. */#define TX_PACKET_SIZE 64#define RX_PACKET_SIZE 64/* RX buffer size */#define RBUF_SIZE  (8*PAGE_SIZE)/* I/O wait queues */static DECLARE_WAIT_QUEUE_HEAD(wq_read);static DECLARE_WAIT_QUEUE_HEAD(wq_write);static DECLARE_WAIT_QUEUE_HEAD(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 );static struct wcirc_buf {	char *buf;	int in;	int out;} rx_ring = { NULL, 0, 0 };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;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;//////////////////////////////////////////////////////////////////////////////// Private Helpers//////////////////////////////////////////////////////////////////////////////static void free_txrx_buffers( void ){	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;	}}static int alloc_txrx_buffers( void ){	tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );	if ( tx_buf == NULL ) {		DPRINTK( "ARGHH! COULD NOT ALLOCATE TX BUFFER\n" );		goto malloc_fail;	}	rx_ring.buf = (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );	if ( rx_ring.buf == NULL ) { 		DPRINTK( "ARGHH! COULD NOT ALLOCATE RX BUFFER\n" );		goto malloc_fail;	}	packet_buffer = (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );	if ( packet_buffer == NULL ) {		DPRINTK( "ARGHH! COULD NOT ALLOCATE RX PACKET BUFFER\n" );		goto malloc_fail;	}	rx_ring.in = rx_ring.out = 0;	memset( &charstats, 0, sizeof( charstats ) );	sending = 0;	last_tx_result = 0;	last_tx_size = 0;	return 0; malloc_fail:	free_txrx_buffers();	return -ENOMEM;}/* twiddle_descriptors() * It is between open() and start(). Setup descriptors. */static void twiddle_descriptors( void ){	desc_t * pd = elfin_usb_get_descriptor_ptr();	string_desc_t * pstr;	u8 remote_mac_address[13];#ifdef USE_RANDOM_REMOTE_MAC	u8 node_id [ETH_ALEN];#endif	pd->dev.bDeviceClass = CDC_DEVICE_CLASS;	pd->dev.bDeviceSubClass = 0;	pd->dev.bDeviceProtocol = 0;	pd->b.ep1.wMaxPacketSize = make_word( RX_PACKET_SIZE );	pd->b.ep2.wMaxPacketSize = make_word( TX_PACKET_SIZE );	pd->dev.idVendor         = ETHERNET_VENDOR_ID;	pd->dev.idProduct        = ETHERNET_PRODUCT_ID;#ifdef CONFIG_S3C2440_SMDK        pd->dev.bcdDevice        = ETHERNET_REV_NUM;	if (elfin_usb_get_string_descriptor(3)) return;        pstr = elfin_usb_kmalloc_string_descriptor( ETHERNET_MANUFACTURE );        if ( pstr ) {           elfin_usb_set_string_descriptor( 1, pstr );           pd->dev.iManufacturer = 1;        }        pstr = elfin_usb_kmalloc_string_descriptor( ETHERNET_FOR_WHAT );        if ( pstr ) {           elfin_usb_set_string_descriptor( 3, pstr );           pd->dev.iProduct = 3;        }#else	if (elfin_usb_get_string_descriptor(2)) return;        pstr = elfin_usb_kmalloc_string_descriptor( "PXA USB CDC Ethernet Raw Access Mode" );        if ( pstr ) {                elfin_usb_set_string_descriptor( 1, pstr );                pd->dev.iProduct = 1;        }#endif	/* set remote mac address */#ifdef USE_RANDOM_REMOTE_MAC	get_random_bytes(node_id, ETH_ALEN);	node_id[0] &= 0xfe;    // clear multicast bit	node_id[1] &= 0xfe;    // second byte must be even	sprintf(remote_mac_address, "%02X%02X%02X%02X%02X%02X",		node_id[0], node_id[1], node_id[2], 		node_id[3], node_id[4], node_id[5]);#else	strcpy(remote_mac_address, "400002000001");#endif	pstr = elfin_usb_kmalloc_string_descriptor(remote_mac_address);	if ( pstr ) {		elfin_usb_set_string_descriptor( 2, pstr );		pd->cdc_b.func.eth.iMACAddress = 2;	}}static void free_string_descriptors( void ){	int i;	string_desc_t * pstr;	for( i = 1 ; i <= 2 ; i++ ) {		pstr = elfin_usb_get_string_descriptor( i );		if ( pstr ) 			kfree( pstr );		elfin_usb_set_string_descriptor( i , NULL);	}}//////////////////////////////////////////////////////////////////////////////// ASYNCHRONOUS//////////////////////////////////////////////////////////////////////////////static void rx_done_callback_packet_buffer( int flag, int size );static void kick_start_rx( void ){	if ( usb_ref_count ) {		int total_space  = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );		if ( total_space >= RX_PACKET_SIZE ) {			elfin_usb_recv( packet_buffer,				      RX_PACKET_SIZE,				      rx_done_callback_packet_buffer				      );		} else {			DPRINTK("buffer overflow: total space = %d\n", 				total_space);		}	}}/* * 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 void rx_done_callback_packet_buffer( int flag, int size ){	 charstats.cnt_rx_complete++;	 DPRINTK("flag = %d, size = %d\n", flag, size);	 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 ){	DPRINTK( "tx timeout\n" );	elfin_usb_send_reset();	charstats.cnt_tx_timeouts++;}static void tx_done_callback( int flag, int size ){	DPRINTK("flag = %d, size = %d\n", flag, size);	if ( flag == 0 )		charstats.bytes_tx += size;	else		charstats.cnt_tx_errors++;	last_tx_size = size;	last_tx_result = flag;	sending = 0;	wake_up_interruptible( &wq_write );	wake_up_interruptible( &wq_poll );}//////////////////////////////////////////////////////////////////////////////// Workers//////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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