RK3568 韦根输入

1、韦根输入管脚

D0-> GPIO0_PC1
D1-> GPIO0_PC0
uart0 管脚

2、设备树配置

wiegand_input:wiegand-input{
		compatible= "wiegand-input";
		status="okay";

		pinctrl-names="default";
		pinctrl-0 = <&wiegand_int>;
                input0-gpio = <&gpio0 RK_PC1 IRQ_TYPE_EDGE_RISING>;
                input1-gpio = <&gpio0 RK_PC0 IRQ_TYPE_EDGE_RISING>;
	};
	&pinctrl {
	
		wiegand_gpio{
			
			wiegand_int:wiegand-int{
				rockchip,pins=
					 <0 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>,
			 		 <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
				
			};
	};

3、驱动代码



#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <asm/param.h>

#define DEVICE_NAME "wiegand"

//delay 33ms to convert data
#define TIMER_DELAY (HZ/30*8)

struct wiegand_dev{
	int hid;
	int pid;
	int rx_index;
	char wiegand[34];
	

	dev_t devno;
	struct cdev cdev;
	struct device *device;
	struct class *cls;
	struct device_node *nd;
	struct timer_list wiegand_timer;

	int timer_flag;
	int open_flag;

	struct semaphore sema;

	int irq_d0;
	int irq_d1;

	int gpio_d0;
	int gpio_d1;
	

	enum of_gpio_flags irq_d0_flags;
	enum of_gpio_flags irq_d1_flags;



};

static struct wiegand_dev *pdev_wiegand;

static int convert_data(void)
{
    int i,even;//,odd;
//    printk("%s:wait wieg_data completed\n",__func__);
    //偶校验
    even=0;
    for(i=0;i<17;i++)
    {
        even+=pdev_wiegand->wiegand[i];
    }
    if(even%2==0)
    {
    }
    else
    {
        goto error;
        //printk("Parity even Error!\n");
    }

    even=0;
    for(i=0;i<17;i++)
    {
        even+=pdev_wiegand->wiegand[17+i];
    }
    if(even%2==0)
    {
        goto error;
        //printk("Parity odd Error!\n");
    }
    pdev_wiegand->hid = 0;
    for(i = 1 ;i<=16;i++)
        pdev_wiegand->hid =  pdev_wiegand->hid << 1 |pdev_wiegand->wiegand[i];

    pdev_wiegand->pid = 0;
    for(i = 17 ;i<=32;i++)
        pdev_wiegand->pid =  pdev_wiegand->pid << 1 |pdev_wiegand->wiegand[i];

    return 0;

error:
    printk("Parity Efficacy Error!\n");
    return -1;
}

static void func_timer(struct timer_list *t)
{
	unsigned int  tmp;
	disable_irq(pdev_wiegand->irq_d0);
	disable_irq(pdev_wiegand->irq_d1);
	if(pdev_wiegand->rx_index!=34)
	{
		memset(pdev_wiegand->wiegand,0,34);
		pdev_wiegand->hid=0;
		pdev_wiegand->pid=0;
	}
	else
	{
		convert_data();
	}
	tmp=pdev_wiegand->hid<<16|pdev_wiegand->pid;
	printk("count:%d :complete convert wieg_data,hid = %x,pid = %x =>%u \n",pdev_wiegand->rx_index,pdev_wiegand->hid,pdev_wiegand->pid,tmp);


	pdev_wiegand->timer_flag=false;
	pdev_wiegand->rx_index=0;
	up(&pdev_wiegand->sema);
	enable_irq(pdev_wiegand->irq_d0);
	enable_irq(pdev_wiegand->irq_d1);
}

static irqreturn_t func_irq0(int irq,void *dev_id)
{
	disable_irq_nosync(pdev_wiegand->irq_d0);
	//printk("irq0 read  %d\n",pdev_wiegand->rx_index);
	udelay(5);
	if(gpio_get_value(pdev_wiegand->gpio_d0)==0 && pdev_wiegand->rx_index<34)
	{
		pdev_wiegand->wiegand[pdev_wiegand->rx_index]=0;
		pdev_wiegand->rx_index++;
	}
	else
	{
		printk("irq0 read high %d\n",pdev_wiegand->rx_index);
		goto end;
	}
	if(pdev_wiegand->timer_flag==false)
	{
		pdev_wiegand->wiegand_timer.expires=jiffies+TIMER_DELAY;
		add_timer(&pdev_wiegand->wiegand_timer);
		pdev_wiegand->timer_flag=true;
	}

	enable_irq(pdev_wiegand->irq_d0);
	return IRQ_HANDLED;
end:
	enable_irq(pdev_wiegand->irq_d0);
	return IRQ_HANDLED;
}
static irqreturn_t func_irq1(int irq,void *dev_id)
{
	disable_irq_nosync(pdev_wiegand->irq_d1);
	//printk("irq1 read  %d\n",pdev_wiegand->rx_index);
	udelay(5);
	if(gpio_get_value(pdev_wiegand->gpio_d1)==0 && pdev_wiegand->rx_index<34)
	{
		pdev_wiegand->wiegand[pdev_wiegand->rx_index]=1;
		pdev_wiegand->rx_index++;
	}
	else
	{
		printk("irq1 read high %d\n",pdev_wiegand->rx_index);
		goto end;
	}
	if(pdev_wiegand->timer_flag==false)
	{
		pdev_wiegand->wiegand_timer.expires=jiffies+TIMER_DELAY;
		add_timer(&pdev_wiegand->wiegand_timer);
		pdev_wiegand->timer_flag=true;
	}

	enable_irq(pdev_wiegand->irq_d1);
	return IRQ_HANDLED;
end:
	enable_irq(pdev_wiegand->irq_d1);
	return IRQ_HANDLED;
}

static ssize_t wiegand_read(struct file *filp,char __user *buf,size_t size,loff_t *ppos)
{
	int ret=down_interruptible(&pdev_wiegand->sema);
	ret++;
	if(size <= pdev_wiegand->rx_index)
		size=pdev_wiegand->rx_index;
	return copy_to_user(buf,pdev_wiegand->wiegand,size);
}

static ssize_t wiegand_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)
{
	return 0;
}

static int wiegand_release(struct inode *node,struct file *filp)
{
	disable_irq(pdev_wiegand->irq_d0);
	disable_irq(pdev_wiegand->irq_d1);
	pdev_wiegand->open_flag=false;

	del_timer_sync(&pdev_wiegand->wiegand_timer);
	return 0;
}

static int wiegand_open(struct inode *node,struct file *filp)
{

	if(pdev_wiegand->open_flag)
	{

		return -EBUSY;
	}

	pdev_wiegand->open_flag=true;
	pdev_wiegand->timer_flag=false;

	timer_setup(&pdev_wiegand->wiegand_timer,func_timer,0);

	memset(pdev_wiegand->wiegand,0,34);
	pdev_wiegand->rx_index=0;

	enable_irq(pdev_wiegand->irq_d0);
	enable_irq(pdev_wiegand->irq_d1);

	printk("%s:%d failed\n",__func__,__LINE__);

	return 0;
}

static struct file_operations wiegand_fops={
	.owner = THIS_MODULE,
	.read = wiegand_read,
	.write = wiegand_write,
	.open = wiegand_open,
	.release = wiegand_release,
} ;


static int __init wiegand_init(void )
{
	int result;
	dev_t devno;

	result=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
	if(result < 0 )
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		return result;
	}

	pdev_wiegand=kmalloc(sizeof(struct wiegand_dev),GFP_KERNEL);
	if(!pdev_wiegand)
	{
		result=-ENOMEM;
		goto fail_malloc;
	}

	memset(pdev_wiegand,0,sizeof(struct wiegand_dev));

	pdev_wiegand->devno=devno;
	pdev_wiegand->rx_index=0;


	cdev_init(&(pdev_wiegand->cdev),&wiegand_fops);

	pdev_wiegand->cdev.owner=THIS_MODULE;

	result=cdev_add(&pdev_wiegand->cdev,devno,1);
	if(result)
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		kfree(pdev_wiegand);
		goto fail_malloc;
	}

	pdev_wiegand->cls=class_create(THIS_MODULE,DEVICE_NAME);
	if(IS_ERR(pdev_wiegand->cls))
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		kfree(pdev_wiegand);
		goto fail_class;
	}

	pdev_wiegand->device=device_create(pdev_wiegand->cls,NULL,devno,NULL,DEVICE_NAME);
	if(IS_ERR(pdev_wiegand->device))
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		goto fail_device;
	}

	pdev_wiegand->nd=of_find_node_by_path("/wiegand-input");

	if(pdev_wiegand->nd==NULL)
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		goto fail_last;
	}

	pdev_wiegand->gpio_d0=of_get_named_gpio_flags(pdev_wiegand->nd,"input0-gpio",0,(enum of_gpio_flags*)&pdev_wiegand->irq_d0_flags);
	pdev_wiegand->gpio_d1=of_get_named_gpio_flags(pdev_wiegand->nd,"input1-gpio",0,(enum of_gpio_flags*)&pdev_wiegand->irq_d1_flags);
	#if 0
	if(pdev_wiegand->gpio_d0==NULL || pdev_wiegand->gpio_d0==NULL)
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		goto fail_last;
	}
	#endif
	pdev_wiegand->irq_d0=gpio_to_irq(pdev_wiegand->gpio_d0);
	pdev_wiegand->irq_d1=gpio_to_irq(pdev_wiegand->gpio_d1);

	sema_init(&pdev_wiegand->sema,0);


	result=request_threaded_irq(pdev_wiegand->irq_d0,NULL,func_irq0,IRQF_TRIGGER_FALLING|IRQF_ONESHOT,"wiegand-d0",pdev_wiegand);
	if(result !=0)
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		goto fail_last;
	}
	result=request_threaded_irq(pdev_wiegand->irq_d1,NULL,func_irq1,IRQF_TRIGGER_FALLING|IRQF_ONESHOT,"wiegand-d1",pdev_wiegand);
	if(result !=0)
	{
		printk("%s:%d failed\n",__func__,__LINE__);
		goto fail_last;
	}

	disable_irq(pdev_wiegand->irq_d0);
	disable_irq(pdev_wiegand->irq_d1);

	printk("%s:%d \n",__func__,__LINE__);

	return 0;

fail_last:
	device_destroy(pdev_wiegand->cls,pdev_wiegand->devno);

fail_device:
	class_destroy(pdev_wiegand->cls);
fail_class:
	cdev_del(&pdev_wiegand->cdev);
	kfree(pdev_wiegand);
fail_malloc:
	unregister_chrdev_region(devno,1);

	return result;


}

static __exit void wiegand_exit(void )
{
	if(pdev_wiegand)
	{
		free_irq(pdev_wiegand->irq_d0,pdev_wiegand);
		free_irq(pdev_wiegand->irq_d1,pdev_wiegand);

		device_destroy(pdev_wiegand->cls,pdev_wiegand->devno);
		class_destroy(pdev_wiegand->cls);
		cdev_del(&pdev_wiegand->cdev);


		kfree(pdev_wiegand);
		unregister_chrdev_region(pdev_wiegand->devno,1);
	
	}

	printk("%s:%d \n",__func__,__LINE__);
}

module_init(wiegand_init);
module_exit(wiegand_exit);

MODULE_AUTHOR("R@BTIOT.cn");
MODULE_LICENSE("GPL");

4、测试程序

static int convert_data(unsigned char wiegand[34],int &hid,int &pid)
{

    int i,even;//,odd;
    //    printk("%s:wait wieg_data completed\n",__func__);
    //偶校验
    even=0;
    for(i=0;i<17;i++)
    {
        even+=wiegand[i];
    }
    if(even%2==0)
    {
    }
    else
    {

        //        printk("even err\n");
        goto error;
    }

    even=0;
    for(i=0;i<17;i++)
    {
        even+=wiegand[17+i];
    }
    if(even%2==0)
    {

        //        printk("odd err\n");
        goto error;
    }

    hid = 0;
    for(i = 1 ;i<=16;i++)
        hid =  hid << 1 |wiegand[i];

    pid = 0;
    for(i = 17 ;i<=32;i++)
        pid =  pid << 1 |wiegand[i];


    return 0;

error:
    printf("Parity Efficacy Error!\n");
    return -1;

}
int test_wiegand()
{
    int fd = open("/dev/wiegand", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if(fd < 0)
    {
        printf("open wiegand failed\n");
        return -1;
    }

    fd_set fs_set;
    struct timeval tv_timeout;
    int retval = 0;

    FD_ZERO(&fs_set);
    FD_SET(fd, &fs_set);
    tv_timeout.tv_sec = 0;
    tv_timeout.tv_usec = 100000;

    unsigned char rbuf[34]={0};

    while(1)
    {
        retval = select(fd + 1, &fs_set, NULL, NULL, &tv_timeout);

        if (retval < 0) {
            return -1;
        } else if (retval == 0)         //time out
        {
            printf("timeout \n");

        } else {
            retval = FD_ISSET(fd, &fs_set);
            if (retval > 0) {
                memset(rbuf,0,34);
                if(read(fd,rbuf,34)<0)
                {
                    printf("read error \n");
                }
                else
                {
                    int hid,pid;
                    convert_data(rbuf,hid,pid);
                    printf("done hid:%4x pid:%x %lld \n",hid,pid,hid<<16|pid);
                }
            }
        }
    }
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值