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

📄 rc531.c

📁 另外一个RC531非接触式读卡器的全部源代码
💻 C
字号:
/* rc531.c: Mifare RC531 Driver */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/uaccess.h>#define RC531_MINOR 21#define RC531_CMD	0#define RC531_REGR	1#define RC531_REGW	2struct rc531_cmd{    int cmd;    char *sendbuf;    char *recvbuf;    int bytesent;    int byterecv;    int bitsrecv;    int timeout;    int status;};struct rc531_regw{    int addr;    int data;};static wait_queue_head_t waitq;static struct rc531_cmd rcmd;static int rc531_use;static int sendptr, recvptr;static char sendbuf[1024];static char recvbuf[1024];static int r531(int reg){ *(unsigned char*)0x0a000000 = ((reg>>3)&0x07)|0x80; return *(unsigned char*)((reg&0x07)+0x0a000000);}static void w531(int reg, int data){ *(unsigned char*)0x0a000000 = ((reg>>3)&0x07)|0x80; *(unsigned char*)((reg&0x07)+0x0a000000) = data;}static void rc531_interrupt(int irq, void *dev_id,                            struct pt_regs *regs){ int i, irqrq, irqmask, nbytes; while(r531(0x03)&0x08){     irqmask = r531(0x06);     irqrq = r531(0x07)&irqmask;     if(irqrq&0x01){		//low alert         nbytes = 56-r531(0x04);         while(nbytes>0 && sendptr!=rcmd.bytesent){             w531(0x02, sendbuf[sendptr]);             nbytes--;             sendptr++;         }         if(sendptr==rcmd.bytesent){             w531(0x06, 0x01);	//disable low alert         }         w531(0x07, 0x01);	//clear low alert     }     if(irqrq&0x10){		//tx irq         w531(0x07, 0x10);	//clear tx irq         if(rcmd.cmd==0x01){	//write e2 command             w531(0x06, 0x7f);	//disable all irq             w531(0x07, 0x7f);	//clear all irq             rcmd.status = 0;             wake_up_interruptible(&waitq);         }     }     if(irqrq&0x0e){		//high alert, rx irq, idle irq         nbytes = r531(0x04);         for(i=0; i<nbytes; i++){             recvbuf[recvptr] = r531(0x02);             recvptr++;             rcmd.byterecv++;         }         w531(0x07, 0x0a);     }     if(irqrq&0x04){		//idle irq         w531(0x06, 0x7f);	//disable all irq         w531(0x07, 0x7f);	//clear all irq         rcmd.status = 0;         wake_up_interruptible(&waitq);     }     if(irqrq&0x20){		//timeout irq         w531(0x06, 0x7f);	//disable all irq         w531(0x07, 0x7f);	//clear all irq         rcmd.status = 0x80;         wake_up_interruptible(&waitq);     } }}static int rc531_open(struct inode *inode, struct file *file){ if(rc531_use == 0){     MOD_INC_USE_COUNT;     rc531_use ++;     return 0; }else{     return -EBUSY; }}static int rc531_release(struct inode *inode, struct file *file){ if(rc531_use){     MOD_DEC_USE_COUNT;     rc531_use --;     return 0; }else{     return -ENODEV; }}static int rc531_ioctl(struct inode *inode, struct file *file,                     unsigned int cmd, unsigned long arg){ int retv, data; struct rc531_regw wcmd; retv = 0; switch(cmd){ case RC531_CMD:     copy_from_user(&rcmd, (struct rc531_cmd*)arg, sizeof(rcmd));     copy_from_user(sendbuf, rcmd.sendbuf, rcmd.bytesent);     rcmd.byterecv = 0;     rcmd.bitsrecv = 0;     rcmd.status = -1;     sendptr = 0;     recvptr = 0;     w531(0x01, 0x00);		//Enter idle mode     w531(0x06, 0x00);		//disable all irq     w531(0x07, 0x7f);		//clear all irq     data = r531(0x09);		//flush fifo     data |= 0x01;     w531(0x09, data);     w531(0x2c, rcmd.timeout);	//set timeout     w531(0x01, rcmd.cmd);     w531(0x06, 0xbf);     while(rcmd.status==-1){         interruptible_sleep_on(&waitq);     }     w531(0x06, 0x00);		//disable all irq     w531(0x07, 0x7f);		//clear all irq     data = r531(0x09);		//stop timer     data |= 0x04;     w531(0x09, data);     w531(0x01, 0x00);		//Enter idle mode     rcmd.status |= r531(0x0a);     if(rcmd.cmd!=0x19 && rcmd.cmd!=0x0b)         rcmd.status &= ~0x40;	//clear key error     copy_to_user(rcmd.recvbuf, recvbuf, rcmd.byterecv);     copy_to_user((struct rc531_cmd*)arg, &rcmd, sizeof(rcmd));     break; case RC531_REGR:     retv = r531(arg);     break; case RC531_REGW:     copy_from_user(&wcmd, (struct rc531_regw*)arg, sizeof(wcmd));     w531(wcmd.addr, wcmd.data);     break; default: }  return retv;}static struct file_operations rc531_fops = {    owner:	THIS_MODULE,    ioctl:	rc531_ioctl,    open:	rc531_open,    release:	rc531_release,};static struct miscdevice rc531_miscdev = {    RC531_MINOR,    "rc531",    &rc531_fops};static int __init rc531_init(void){ int retv;  rc531_use = 0; retv = misc_register(&rc531_miscdev); printk("rc531 driver!\n"); init_waitqueue_head(&waitq); retv = request_irq(INT_EINT1, rc531_interrupt, 0, "rc531", NULL); return retv;}static void __exit rc531_exit(void){ misc_deregister(&rc531_miscdev); free_irq(INT_EINT1, NULL); return;}module_init(rc531_init);module_exit(rc531_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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