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

📄 fps200.c

📁 指纹识别芯片fps200(富士通)在linux下的驱动程序(for arm7(ep7312) linux
💻 C
字号:
/** * Title: fps200.c * Type: C (*.c) * Description: a driver of fps200 in linux 2.4.x * Copyright: Copyright (c) 2003 * Company: djws * author djws * version 1.0 */#ifndef __KERNEL__#  define __KERNEL__#endif#ifndef MODULE#  define MODULE#endif#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>   /* printk() */#include <linux/slab.h>     /* kmalloc() */#include <linux/fs.h>       /* everything... */#include <linux/errno.h>    /* error codes */#include <linux/types.h>    /* size_t *///#include <linux/proc_fs.h>#include <linux/init.h>//#include <linux/fcntl.h>    /* O_ACCMODE *///#include <asm/system.h>     /* cli(), *_flags */#include <linux/delay.h>    /* udelay() */#include <asm/io.h>    /* ioremap(), iounmap() *///#include <asm/hardware.h>#include <linux/ioport.h>//#include <asm/sizes.h>//#include <linux/tqueue.h>//#include <linux/interrupt.h>#include <asm/irq.h>#include <linux/string.h>//#include <linux/sched.h>//#include <linux/mm.h>//#include <asm/pgtable.h>//#include <asm/page.h>//#include <asm/setup.h>//#include <asm/mach-types.h>//#include <asm/mach/arch.h>//#include <asm/mach/map.h>#include <asm/uaccess.h>#include <asm/arch/irqs.h>#include "fps200.h"          /* local definitions */#define FPS200_VR 0xfd000000#define FPS_INDEX     (*(volatile unsigned char *)FPS200_VR)#define FPS_DATA      (*(volatile unsigned char *)(FPS200_VR+1))/* * I don't use static symbols here, because we export no symbols */#define FPS200_MAJOR 240#define FPS200_NR_DEVS 0#define FPS200_IRQ IRQ_EINT2 	// the irq is 6#define FPS200_DATASIZE 76800int fps200_major = FPS200_MAJOR;int fps200_nr_devs = FPS200_NR_DEVS;    /* number of bare fps200 devices (no use here) */MODULE_PARM(fps200_major,"i");MODULE_PARM(fps200_nr_devs,"i");MODULE_AUTHOR("Dai Jin");MODULE_LICENSE("GPL");struct file_operations fps200_fops = {        open: fps200_open,//      read: fps200_read,//      write: fps200_write,        ioctl: fps200_ioctl,        release: fps200_release};struct file_operations *fps200_fop_array[]={    &fps200_fops,      /* type 0 */   /* add more later */};#define FPS200_MAX_TYPE 0FPS200_Dev *fps200_device;void fps200_interrupt(int irq, void *dev_id, struct pt_regs *regs) {	disable_irq(irq);	//udelay(1000);	//fps_get_image();	fps200_device->flag = 1;}void fps_get_image(void) {	int i = 0;	int j = 0;	FPS_INDEX = FPS_CTRLA;	FPS_DATA = FPS_CTRLA_GETIMG;	for(i=0; i<300; i++) {		FPS_INDEX = FPS_CTRLB;		while(!(FPS_CTRLB_RDY&FPS_DATA)){udelay(1);};		for(j=0; j<256; j++) {			FPS_INDEX = FPS_CTRLB;			while(!(FPS_CTRLB_RDY&FPS_DATA)){udelay(1);};			FPS_INDEX = FPS_CTRLA;			*((unsigned char *)(fps200_device->data+i*256+j))=FPS_DATA;		}	}}int fps200_open(struct inode *inode, struct file *filp) {	MOD_INC_USE_COUNT;	return(0);}int fps200_release(struct inode *inode, struct file *filp) {	MOD_DEC_USE_COUNT;	return(0);}int fps200_ioctl(struct inode *inode, struct file *filp,		unsigned int cmd, unsigned long arg) {	int err = 0;	int ret = 0;	unsigned char tmp;	if(_IOC_TYPE(cmd) != FPS200_IOC_MAGIC)		return -ENOTTY;	if(_IOC_NR(cmd) > FPS200_IOC_MAXNR)		return -ENOTTY;	if (_IOC_DIR(cmd) & _IOC_READ)		err = verify_area(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));	else if (_IOC_DIR(cmd) & _IOC_WRITE)		err =  verify_area(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));	if (err)		return err;	switch(cmd) {		case FPS200_IOCSDTR:			ret = __get_user(tmp, (unsigned char *)arg);			if(tmp > 0x7f)				tmp = 0x7f;			FPS_INDEX = FPS_DTR;			FPS_DATA = tmp;			break;		case FPS200_IOCSDCR:			ret = __get_user(tmp, (unsigned char *)arg);			if(tmp > 0x1f)				tmp = 0x1f;			FPS_INDEX = FPS_DCR;			FPS_DATA = tmp;			break;		case FPS200_IOCSPGC:			ret = __get_user(tmp, (unsigned char *)arg);			if(tmp > 0x0f)				tmp = 0x0f;			FPS_INDEX = FPS_PGC;			FPS_DATA = tmp;			break;		case FPS200_IOCGDTR:			FPS_INDEX = FPS_DTR;			tmp = FPS_DATA;			ret = __put_user(tmp, (unsigned char *)arg);			break;		case FPS200_IOCGDCR:			FPS_INDEX = FPS_DCR;			tmp = FPS_DATA;			ret = __put_user(tmp, (unsigned char *)arg);			break;		case FPS200_IOCGPGC:			FPS_INDEX = FPS_PGC;			tmp = FPS_DATA;			ret = __put_user(tmp, (unsigned char *)arg);			break;		case FPS200_IOCEINT:			enable_irq(FPS200_IRQ);			break;		case FPS200_IOCDINT:			disable_irq(FPS200_IRQ);			break;		case FPS200_IOCFCAP:			fps_get_image();		case FPS200_IOCGDATA:			copy_to_user((void *)arg, fps200_device->data, FPS200_DATASIZE);			ret = 0;			fps200_device->flag = 0;			break;		case FPS200_IOCCLR:			memset(fps200_device->data, 0, FPS200_DATASIZE);			fps200_device->flag = 0;			break;		case FPS200_IOCCINT:			if(((clps_readw(INTSR1))&0x40) == 0) {				udelay(100);				if(((clps_readw(INTSR1))&0x40) == 0)					ret = __put_user(0x01, (unsigned char *)arg);				else					ret = __put_user(0x0, (unsigned char *)arg);			}			else				ret = __put_user(0x0, (unsigned char *)arg);			break;		case FPS200_IOCCRDY:			ret = __put_user(fps200_device->flag, (unsigned char *)arg);			break;		default:			return -ENOTTY;	}	return ret;}static int __init fps200_init_module(void) {	int result;	char tmp;	if((result = check_region (FPS200_VR,2))) {		printk ("<1> can't get I/O port address \n");		return (result);	}	if (!request_region (FPS200_VR,2,"fps200"))                return -EBUSY;	SET_MODULE_OWNER(&fps200_fops);/* * Register your major, and accept a dynamic number. This is the * first thing to do, in order to avoid releasing other module's * fops in scull_cleanup_module()*/	result = register_chrdev(fps200_major, "fps200", &fps200_fops);	if(result < 0) {		printk("<1>fps200: can't get major %d\n",fps200_major);		return result;	}	if(fps200_major == 0)		fps200_major = result; /* dynamic *//* read chip id first, if not equal 0x20xx, print error */	FPS_INDEX = FPS_CIDH;	tmp = FPS_DATA;	if(tmp != 0x20) {		printk("<1>wrong chip ID, insmod fail.\n");		return -EIO;	}	/* row auto inc. inner 12MHz vibrator. no low-power state */	FPS_INDEX = FPS_CTRLB;	FPS_DATA = (FPS_CTRLB_AFDEN|FPS_CTRLB_AUTOINCEN|FPS_CTRLB_ENABLE);	/* wait for 30us */	udelay(35);	// make delay longer than 30us	/* Interupt */	FPS_INDEX = FPS_ICR;        FPS_DATA = (FPS_ICR_IE0|FPS_ICR_IT0_LEVEL);	FPS_INDEX = FPS_THR;	FPS_DATA = ( FPS_THR_THV | FPS_THR_THC );	/* DTR, DCR, PGC */	FPS_INDEX = FPS_DTR;	FPS_DATA = 0x23;	FPS_INDEX = FPS_DCR;	FPS_DATA = 0x1;	FPS_INDEX = FPS_PGC;	FPS_DATA = 0;	/* other initial */	FPS_INDEX = FPS_RAL;	// raw address	FPS_DATA = 0;	FPS_INDEX = FPS_RAH;	FPS_DATA = 0;	FPS_INDEX = FPS_REL;	FPS_DATA = 0;	FPS_INDEX = FPS_REH;	FPS_DATA = 0;	FPS_INDEX = FPS_CAL;	// column address	FPS_DATA = 0;	FPS_INDEX = FPS_CEL;	FPS_DATA = 0;	FPS_INDEX = FPS_CTRLC;	FPS_DATA = 0;	FPS_INDEX = FPS_CTRLA;	FPS_DATA = 0;	// clear FPS_CTRLA_AINSEL	/* set irq */	result = request_irq(FPS200_IRQ, fps200_interrupt, SA_INTERRUPT, "fps200", NULL);	if(result) {		printk("<1>can't get assigned irq.\n");		return -EIO;	}	fps200_device = kmalloc(sizeof(FPS200_Dev), GFP_KERNEL);	if(!fps200_device) {		FPS_INDEX = FPS_CTRLB;		FPS_DATA = 0;		return -ENOMEM;	}	memset(fps200_device, 0, sizeof(FPS200_Dev));	fps200_device->data = kmalloc(FPS200_DATASIZE, GFP_KERNEL);	if(!fps200_device) {		FPS_INDEX = FPS_CTRLB;		FPS_DATA = 0;		kfree(fps200_device);		return -ENOMEM;	}	memset(fps200_device->data, 0, FPS200_DATASIZE);	return(0);}static void __exit fps200_cleanup_module(void) {	kfree(fps200_device->data);	kfree(fps200_device);	FPS_INDEX = FPS_CTRLB;	FPS_DATA = 0;	release_region (FPS200_VR,2);	free_irq(FPS200_IRQ, NULL);	unregister_chrdev(fps200_major, "fps200");}module_init(fps200_init_module);module_exit(fps200_cleanup_module);

⌨️ 快捷键说明

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