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 + -
显示快捷键?