usbdmc.c

来自「一份介绍在S3C2410上液晶屏驱动程序的实现」· C语言 代码 · 共 734 行 · 第 1/2 页

C
734
字号
/* * * Copyright (c) 2004  DMC Co., Ltd. *  * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: *  * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *  * Except as contained in this notice, the name of the DMC Co., Ltd shall not  * be used in advertising or otherwise to promote the sale, use or other dealings * in this Software without prior written authorization from DMC Co., Ltd. *//* * EUC * tab=4 */#include <linux/kernel.h>#include <linux/poll.h>#include <linux/usb.h>#include <linux/smp_lock.h>#include <linux/init.h>#include <linux/module.h>#include "../vers.h"#include "usbdmc.h"#define DEBUG_HON		0#define USBDMC_MINOR	181		/* minor */#define VID_USBDMC		0x0afa	/* vendor ID */#define PID_USBDMC		0x03e8	/* product ID */#define	true	1#define	false	0#define	INI_2_IDLE		0x05#define	S_RATE			0x40#define	RESET			0x55#define	IDLE_2_XYP		0x31#define	XYP_2_IDLE		0x02#define	IDLE_2_RomRd	0x1d#define	IDLE_2_RomWr	0x0d#define	ACK				0x06#define	NAK				0x15typedef struct{    int					isopen;    struct usb_device	*dev;				/* usb device data */#if KER26    struct urb			*irq;				/* URB for interrupt      */#else    struct urb			irq;				/* URB for interrupt      */#endif    wait_queue_head_t	wait;				/* wait queue for interrupt */    wait_queue_head_t	remove_ok;   	char				data[64];	int					rxputp;	int					rxgetp;#define	MAX_RXBUF	256    char				rxbuf[MAX_RXBUF];	/* recv buffer */    int					ep_intr_in;			/* ENDPOINT(INT-IN)*/    int					ep_bulk_out;    int					ep_bulk_in;	char				svd[5];} usbdmc_data_t;static usbdmc_data_t *g_usbdmc_data;static void pktdump(char *title,int len,char *p);static int usbdmc_setup(usbdmc_data_t* pdata);static int usbdmc_reset(usbdmc_data_t* pdata);static int usbdmc_specify(usbdmc_data_t* pdata,int rate);static int usbdmc_goto_idle(usbdmc_data_t* pdata);static int usbdmc_goto_xyp(usbdmc_data_t* pdata);static int usbdmc_get_stat(usbdmc_data_t* pdata,u_short *stat);static int usbdmc_read_eeprom(usbdmc_data_t* pdata,u_char *buf);static int usbdmc_write_eeprom(usbdmc_data_t* pdata,u_char *buf);static int usbdmc_open(struct inode *inode, struct file *file);static int usbdmc_close(struct inode *inode, struct file *file);static int usbdmc_ioctl(struct inode *inode, struct file *file,               unsigned int cmd, unsigned long arg);static ssize_t usbdmc_read(struct file * file, char * buffer, size_t count, loff_t *ppos);static unsigned int usbdmc_poll(struct file *file, poll_table * wait);#if KER26static int usbdmc_probe(struct usb_interface *intface,const struct usb_device_id *id);static void usbdmc_disconnect(struct usb_interface *intface);#elsestatic void* usbdmc_probe(struct usb_device *dev, unsigned int ifnum,                          const struct usb_device_id *id);static void usbdmc_disconnect(struct usb_device *dev, void *ptr);#endif/* int usb_control_msg(struct usb_device *dev, unsigned int pipe,			   	__u8 request, __u8 requesttype,			   	__u16 value, __u16 index, void *data, __u16 size, int timeout) [sample]	usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,		0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT);	usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,			(type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)*/static void pktdump(char *title,int len,char *p){int i,k;char s[256];unsigned char *pp;	k = sprintf(s,"%s : len=%d",title,len);	if( len <= 0 )		return;	k += sprintf(&s[k]," data=");	if( p )	{		for( pp=(unsigned char *)p,i=0 ; i < len ; i++ )		{			k += sprintf(&s[k],"$%02x ",pp[i]);		}	}	printk(KERN_ERR "%s\n",s);}static int usbdmc_setup(usbdmc_data_t* pdata){u_short st;	/* usbdmc_reset(pdata); */	usbdmc_specify(pdata,0);	usbdmc_goto_xyp(pdata);	usbdmc_get_stat(pdata,&st);	return(true);}static int usbdmc_reset(usbdmc_data_t* pdata){int res;char bf[10];	res = usb_control_msg(pdata->dev,usb_rcvctrlpipe(pdata->dev,0),RESET,0xc0,0,0,bf,2,HZ*120);	pktdump("usbdmc_reset",res,bf);	if( res > 0 && bf[0] == ACK )		return(true);	// ACK goto init mode	return(false);		// NAK}static int usbdmc_specify(usbdmc_data_t* pdata,int rate){int res;char bf[10];	if( rate < 0 || rate > 5 )		return(false);	res = usb_control_msg(pdata->dev,usb_rcvctrlpipe(pdata->dev,0),INI_2_IDLE,0xc0,S_RATE+rate,0,bf,2,HZ*120);	pktdump("usbdmc_specify",res,bf);	//printk(KERN_ERR "rate=%d\n",rate);	if( res > 0 && bf[0] == ACK )		return(true);	// ACK goto idle mode	return(false);		// NAK}static int usbdmc_goto_idle(usbdmc_data_t* pdata){int res;char bf[10];	res = usb_control_msg(pdata->dev,usb_rcvctrlpipe(pdata->dev,0),XYP_2_IDLE,0xc0,0,0,bf,2,HZ*5);	pktdump("usbdmc_goto_idle",res,bf);	if( res > 0 && bf[0] == ACK )		return(true);	// ACK goto xyp mode	return(false);		// NAK}static int usbdmc_goto_xyp(usbdmc_data_t* pdata){int res;	res = usb_control_msg(pdata->dev,usb_sndctrlpipe(pdata->dev,0),IDLE_2_XYP,0x40,0,0,NULL,0,HZ*120);	pktdump("usbdmc_goto_xyp",res,NULL);	return(true);	// goto xyp mode}static int usbdmc_get_stat(usbdmc_data_t* pdata,u_short *stat){int res;u_char bf[10];	printk(KERN_ERR "usbdmc_get_stat s\n");	res = usb_control_msg(pdata->dev,usb_rcvctrlpipe(pdata->dev,0),0x15,0xc0,0,0,bf,2,HZ*10);	pktdump("usbdmc_get_stat",res,bf);	if( res <= 0 )		return(false);	*stat = (bf[0]<<8) + bf[1];	return(true);}static int usbdmc_read_eeprom(usbdmc_data_t* pdata,u_char *bf){int res,i,cnt,k;u_short st;	printk(KERN_ERR "usbdmc_read_eeprom\n");	usbdmc_get_stat(pdata,&st);	if( st & 0x0080 )		return(-1);	res = usb_control_msg(pdata->dev,usb_rcvctrlpipe(pdata->dev,0),IDLE_2_RomRd,0xc0,0,0,bf,2,HZ*120);	//pktdump("usbdmc_read_eeprom",res,bf);	if( res <= 0 )		return(-1);	cnt = (5*5)+1;	for( k=2,i=0 ; i < (cnt-1) ; i++,k+=8 )	{		res = usb_control_msg(pdata->dev, usb_rcvctrlpipe(pdata->dev, 0),				IDLE_2_RomRd, 0xc0, 0, 0, &bf[k], 8, HZ * 120);		//pktdump("usbdmc_read_eeprom",res,&bf[k]);	}	res = usb_control_msg(pdata->dev, usb_rcvctrlpipe(pdata->dev, 0),			IDLE_2_RomRd, 0xc0, 0, 0, &bf[k], 4, HZ * 120);	//pktdump("usbdmc_read_eeprom",res,&bf[k]);	k+=4;	return(k);}static int usbdmc_write_eeprom(usbdmc_data_t* pdata,u_char *bf){int i,res;char s[20];u_short *p,a;	for( i=0,p=(u_short *)bf ; i < 39 ; i++ )	{		a = (p[i]>>8) | (p[i]<<8);		//printk(KERN_ERR "usbdmc_write_eeprom %d $%03x(%4d) \n",i,a,a);		res = usb_control_msg(pdata->dev,usb_rcvctrlpipe(pdata->dev,0)								,IDLE_2_RomWr,0xc0,a,0,s,2,HZ*120);		//pktdump("usbdmc_write_eeprom",res,s);		if( s[0] != ACK )			break;	}	//printk(KERN_ERR "WRITE %d\n",i);	pktdump("usbdmc_write_eeprom",res,s);	return( s[0] == ACK ? i : -1 );}#if KER26static void usbdmc_irq(struct urb *urb, struct pt_regs *regs)#elsestatic void usbdmc_irq(struct urb *urb)#endif{int i,getp,putp;usbdmc_data_t *p;	#if DEBUG_HON		printk(KERN_ERR "usbdmc_irq status %d\n",urb->status);	#endif    if( urb->status )	{#if KER26		goto exit;#else        return;#endif    }    p = urb->context;	//pktdump(KERN_ERR "usbdmc_irq",5,p->data);	getp = p->rxgetp;	putp = p->rxputp;	if( memcmp(p->svd,p->data,5) == 0 )#if KER26			goto exit;#else		return;#endif	memcpy(p->svd,p->data,5);	for( i=0 ; i < 5 ; i++ )	{		p->rxbuf[putp++] = p->data[i];		putp = putp >= MAX_RXBUF ? 0 : putp;			if( putp == getp )#if KER26			goto exit;#else			return;#endif	}	p->rxputp = putp;    wake_up_interruptible(&p->wait);#if KER26exit:    p = urb->context;	usb_submit_urb(p->irq,GFP_ATOMIC);#endif}static int usbdmc_open(struct inode *inode, struct file *file){    usbdmc_data_t *pdata;    pdata = g_usbdmc_data;	printk(KERN_ERR "usbdmc_open \n");    if( pdata == NULL )	{        return -ENODEV;    }    if( pdata->isopen )	{        return -EBUSY;    }    init_waitqueue_head(&pdata->wait);    init_waitqueue_head(&pdata->remove_ok);    file->private_data = pdata;    pdata->isopen = 1;    pdata->rxputp = 0;    pdata->rxgetp = 0;#if KER26    pdata->irq->dev = pdata->dev;    usb_submit_urb(pdata->irq,GFP_KERNEL);#else    pdata->irq.dev = pdata->dev;    usb_submit_urb(&pdata->irq);#endif    return 0;}static int usbdmc_close(struct inode *inode, struct file *file){    usbdmc_data_t* pdata;    pdata = g_usbdmc_data;	printk(KERN_ERR "usbdmc_close \n");    if( pdata->isopen )	{        pdata->isopen = 0;        wake_up(&pdata->remove_ok);#if KER26        //usb_unlink_urb(pdata->irq);        usb_kill_urb(pdata->irq);#else        usb_unlink_urb(&pdata->irq);#endif    }    return 0;}static int usbdmc_ioctl(struct inode *inode, struct file *file,               unsigned int cmd, unsigned long arg){usbdmc_data_t* pdata;int res,a;u_short b;char buf[512];	#if DEBUG_HON		printk(KERN_ERR "usbdmc_ioctl %d($%x)\n",cmd,cmd);	#endif	res = true;    pdata = file->private_data;    switch(cmd)	{    case USBDMC_RESET:		res = usbdmc_reset(pdata);		break;    case USBDMC_SPECIFY:		get_user(a,(int *)arg);		res = usbdmc_specify(pdata,a);		break;    case USBDMC_GOTO_XYP:		res = usbdmc_goto_xyp(pdata);		break;    case USBDMC_GOTO_IDLE:		res = usbdmc_goto_idle(pdata);		break;

⌨️ 快捷键说明

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