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

📄 usb-func.c

📁 ARM嵌入式应用开发典型实例配书光盘,希望对你有用!
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/miscdevice.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>

#include "define.h"
#include "go7007drv.h"

/* Debug status */
static int debug = 0;

/* Redefine debug macro */
#undef	dbg
#define dbg(format, arg...) \
	do { if (debug) printk(KERN_DEBUG __FILE__ ": [" __FUNCTION__ "] " \
		format "\n" , ## arg); \
	} while (0)

#undef	err
#define err(format, arg...) printk(KERN_ERR __FILE__ ": [" __FUNCTION__ "] " \
		format "\n" , ## arg)

/* Version Information */
#define	DRIVER_VERSION	"v0.4"
#define	DRIVER_DESC		"USB Skeleton Driver"

/* basic usb pipe function */
#define STREAM_PIPE 		1
#define CONTROL_PIPE		2
#define DOWNLOAD_PIPE 		3
#define INTERRUPT_PIPE 		4

#define USB_TIMEOUT 		5   // second

/*
 * Devices information
 */

#define	USB_GO_MAJOR			240
#define	USB_GO_MINOR_BASE	0
#define MAX_DEVICES				256

#define	GODEV_MINOR(busnum, devnum) \
	((((busnum-1) & 7)*32) + ((devnum-1) & 31))

/* Device array and mutex */
static usb_t			*usb_dev_table[MAX_DEVICES];
static DECLARE_MUTEX	(usb_dev_table_mutex);

static int buffers = 256;

//char  tmpCMD_PACKET[72];
/* Local purpose */
#define IOCTL_GO_COMMAND	_IOWR('W', 0x80, CMD_PACKET)	
//#define IOCTL_GO_COMMAND   _IOWR('W', 0X80, tmpCMD_PACKET)   
/*
static struct
{
	short	allow_irq;
	unsigned short	ready;
	unsigned short	retval;
	unsigned short	retdata;
} rd_irq_data;
*/

/* static void interrupt_pipe_complete(purb_t purb); */

/*
 * Begin of basic usb pipe function
 */

/* Stream buffer */
DECLARE_WAIT_QUEUE_HEAD(stream_pipe_wq);

static void read_stream_submit(pusb_t s);

void stream_pipe_complete(purb_t purb)
{
	pusb_t s = (pusb_t) purb->context;

	dbg("Usb transfer complete");

	if(s->StreamThreadState) {
#if 0
		StreamBuffer_AddBlock(&(s->StreamBuffer),
								s->bulk_in_buffer,
								BULK_IN_BUFSIZE);

		read_stream_submit(s);
#else
		tasklet_schedule(&(s->bh));
#endif

		// read_stream_submit(s);
		// err("stream pipe complete");
	}
	else {
		wake_up(&(s->wq_stop_stream_thread));
	}
}

int ReadStreamPipe(pusb_t s, unsigned char *pbuf, int len)
{
	int pipe;	
	purb_t purb = NULL;
	int r=0;
		
	pipe = usb_rcvbulkpipe(s->usbdev, STREAM_PIPE);
	purb = s->bulkin_urb;
	
	s->stream_in_ready = 0;

	FILL_BULK_URB(purb, s->usbdev, pipe, pbuf, len, stream_pipe_complete, s);
	usb_submit_urb(purb);
	
	// r = sleep_on_timeout(&s->wq_stream_pipe, USB_TIMEOUT*HZ);
	while(!s->stream_in_ready)
		r = sleep_on_timeout(&stream_pipe_wq, USB_TIMEOUT*HZ);

	return r;
}

static void read_stream_submit(pusb_t s)
{
	int pipe;
	purb_t	purb = NULL;
	unsigned char *pbuf;

	pipe = usb_rcvbulkpipe(s->usbdev, STREAM_PIPE);
	purb = s->bulkin_urb;
	pbuf = s->bulk_in_buffer;

	FILL_BULK_URB(purb, s->usbdev, pipe, pbuf, BULK_IN_BUFSIZE, stream_pipe_complete, s);
	usb_submit_urb(purb);
}


static void read_stream_bh(unsigned long data)
{
	pusb_t s = (pusb_t) data;

	StreamBuffer_AddBlock(&(s->StreamBuffer),
			s->bulk_in_buffer, BULK_IN_BUFSIZE);

	read_stream_submit(s);
}

void begin_stream_input(pusb_t s)
{
	read_stream_submit(s);
}

/// init buffer

// DECLARE_WAIT_QUEUE_HEAD(download_pipe_wq);

void download_pipe_complete(purb_t purb)
{
	pusb_t s = (pusb_t) purb->context;

	dbg("Usb transfer complete");
	wake_up(&s->wq_download_pipe);
}

int DownloadBuffer(pusb_t s, unsigned char *pbuf, int len)
{
	int pipe;	
	purb_t purb = NULL;
	int r;

	pipe = usb_sndbulkpipe(s->usbdev, DOWNLOAD_PIPE);
	purb = usb_alloc_urb(0);
	
	dbg("download pipe : %x",pipe);
	dbg("bulk size / max bulk out size : %d / %d",
		len, s->bulk_out_size);
	
	{
		unsigned char *trans_buf;

		trans_buf	= kmalloc(len, GFP_KERNEL | __GFP_DMA);
		copy_from_user(trans_buf, pbuf, len);

		FILL_BULK_URB_TO(purb, s->usbdev, pipe, trans_buf, len,
						 download_pipe_complete, s, 500);
		purb->transfer_flags |= USB_QUEUE_BULK;

		r = usb_submit_urb(purb);
		if(r)
			dbg("usb_submit_urb error: %d", r);

		r = sleep_on_timeout(&s->wq_download_pipe, USB_TIMEOUT*HZ);
		if(!r)
		{
			dbg("download timeout : %d",r);
		}

		dbg("download return: %d", r);
		kfree(trans_buf);
	}

	usb_unlink_urb(purb);
	usb_free_urb(purb);	

	return r;
}

//// read interrupt

// DECLARE_WAIT_QUEUE_HEAD(interrupt_pipe_wq);

void interrupt_pipe_complete(purb_t purb)
{
	pusb_t s;

	s = (pusb_t) purb->context;

	if(!s->rd_irq_data.allow_irq)
	{
		dbg("IRQ is not allowed!");
		return;
	}

	dbg("USB interrupt complete: status = %d", purb->status);

	s->rd_irq_data.ready = 1;
	memcpy(&(s->rd_irq_data.retdata), purb->transfer_buffer, 2);
	memcpy(&(s->rd_irq_data.retval),  purb->transfer_buffer+2, 2);

	dbg("rd_irq_data.ready = %d", s->rd_irq_data.ready);

	wake_up(&s->wq_interrupt_pipe);
}
	
int ReadInterruptPipe(pusb_t s, unsigned short *pIntRetVal, unsigned short *pIntRetData)
{
	int r;
	int cnt;
	
	dbg("Enter");

	cnt = 0;
	while(!s->rd_irq_data.ready)
	{
		r = sleep_on_timeout(&s->wq_interrupt_pipe, 0.1*HZ);

		cnt++;
		if(cnt > 10) break;
	}
	
	dbg("irq_data: 0x%04X, 0x%04X, 0x%04X",
			s->rd_irq_data.ready,
			s->rd_irq_data.retdata,
			s->rd_irq_data.retval);

	if(s->rd_irq_data.ready)
	{
		*pIntRetData	= s->rd_irq_data.retdata;
		*pIntRetVal		= s->rd_irq_data.retval;

		s->rd_irq_data.ready	= 0;
		r = 1;
	}
	else
	{
		r = 0;
	}
 
	dbg("interrupt sleep return : %d, val : %04x, data : %04x", r, *pIntRetVal, *pIntRetData);

	dbg("Leave");

	return r;
}

//// write interrupt through control pipe

// DECLARE_WAIT_QUEUE_HEAD(control_pipe_wq);

void control_pipe_complete(purb_t purb)
{
	pusb_t s = (pusb_t) purb->context;

	dbg("Usb control complete");
	wake_up(&s->wq_control_pipe);
}

int WriteInterrupt(pusb_t s, unsigned short Addr, unsigned short Data)
{
	int pipe;	
	purb_t purb = NULL;
	int r;
	unsigned short *transbuf;
	unsigned char *setuppacket;	
	
	transbuf=kmalloc(8,GFP_KERNEL);
	setuppacket=kmalloc(8,GFP_KERNEL);
		
	transbuf[0] = Data;	
	transbuf[1] = Addr;	
	transbuf[2] = 0;	
	transbuf[3] = 0;	
	
	setuppacket[0] = 0x42;
	setuppacket[1] = 0x00;
	setuppacket[2] = 0xaa;
	setuppacket[3] = 0x55;
	setuppacket[4] = 0xf0;
	setuppacket[5] = 0xf0;
	setuppacket[6] = 0x08;
	setuppacket[7] = 0x00;
	
	pipe = usb_sndctrlpipe(s->usbdev, CONTROL_PIPE);
	dbg("control pipe : %x",pipe);
	
	purb = usb_alloc_urb(0);
	
	FILL_CONTROL_URB_TO(purb, s->usbdev, pipe, setuppacket, transbuf, 8,
						control_pipe_complete, s, 100);
	usb_submit_urb(purb);
	
	r = sleep_on_timeout(&s->wq_control_pipe, USB_TIMEOUT*HZ);
	
	kfree(transbuf);
	kfree(setuppacket);
	
	dbg("control sleep return : %d",r);

	usb_unlink_urb(purb);
	dbg("WriteInterrupt: free urb");
	usb_free_urb(purb);	

	return r;
}

// end of basic usb pipe function

/*
 * Driver interface
 */

static inline void go_delete(usb_t *s)
{
	usb_dev_table[s->minor] = NULL;

	if(s->irq_buf != NULL)
		kfree(s->irq_buf);

	kfree(s);
}

static ssize_t go_read (struct file *file, char *buf, size_t count, loff_t * ppos)
{
	pusb_t s;
	int rv;
	int FrameSize = count;

	dbg("Enter");
	
	s = (pusb_t) file->private_data;

	/* Get data from stream buffer */
	rv = StreamBuffer_GetFrame(&(s->StreamBuffer), buf, &FrameSize);

	if(rv == 0)
		rv = FrameSize;
	else
		rv = 0;

	dbg("Leave");
	return rv;
}

static ssize_t go_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
{
	pusb_t s;
	int rv;

	dbg("Enter");
	err("go_write %d %d", buf[0], count);

	s = (pusb_t) file->private_data;

	/* Process writing */
	if(OnWriteProc(s,buf)==0)
		rv = count;

⌨️ 快捷键说明

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