rk3568-Android11-韦根输出驱动

由于之前没接触过韦根,现公司分配需求给我就试韦根输入输出。只能硬着头皮查资料看代码完成需求。


//#include "wiegand.h"
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/hrtimer.h>
#include <linux/init.h>
#include <linux/ioctl.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/semaphore.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/uaccess.h>

// msleep:实现毫秒级的延时,该延时保证至少延时所设置的延时时间,不会提前超时返回,会让出CPU
#define delay_1ms(x) msleep(x)
#define IOCTL_SET_DATA0    0x26
#define IOCTL_SET_DATA1    0x34
#define IOCTL_SET_LOW_TIME 0x01
#define IOCTL_SET_HIGH_TIME    0x02
#define GPIO2_D5    93
#define GPIO2_D4    92
#define DEVICE_DATA0_LABEL "wiegand_out_d0"
#define DEVICE_DATA1_LABEL "wiegand_out_d1"
#define DELAY_60    udelay(400)
#define DELAY_800   udelay(2000)
#define DELAY_2000  mdelay(5)
struct wiegand26 {
bool flag;
char data[27];
} wiegand26;

struct wiegand34 {
bool flag;
char data[35];
} wiegand34;

struct wiegand66 {
bool flag;
char data[67];
} wiegand66;

static struct workqueue_struct *queue = NULL;
//static struct work_struct work;
static int major;
static struct class *class = NULL;
static struct device *dev = NULL;
static int WG_DATA1 = GPIO2_D4;
static int WG_DATA0 = GPIO2_D5;
static int LOW_TIME = 100;
static int HIGH_TIME = 1500;
static int isStartGPIO = false;

//设置相应GPIO引脚为输出,并输出为高
void gpio_set_output(void) {
    gpio_direction_output(WG_DATA0, 1); // DATA0初始为高
    gpio_direction_output(WG_DATA1, 1); // DATA1初始为高
  //  return 0;
}

//初始化相应GPIO
void gpio_init(void) {
    gpio_request(WG_DATA0, DEVICE_DATA0_LABEL);
    gpio_request(WG_DATA1, DEVICE_DATA1_LABEL);
    gpio_set_output();
  //  return 0;
}
void Send_Weigand26(unsigned char *str)
{

    unsigned char one_num = 0;
    unsigned char even = 0;
    unsigned char odd = 0;
    unsigned char check_temp,i,j;

    check_temp = *str;
    
    printk("start wiegand26!\n");
    printk("Send WG26: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
    for(i = 0;i < 8;i++)
    {
        if(check_temp & 0x1)
            one_num++;
        check_temp >>= 1;
    }

    check_temp = *(str + 1);
    for(i = 0;i < 4;i++)
    {
        if(check_temp & 0x80)
            one_num++;
        check_temp <<= 1;
    }

    if(one_num % 2 )
        even = 1;
    else
        even = 0;

    one_num = 0;

    check_temp = *(str + 1);
    for(i = 0;i < 4;i++)
    {
        if(check_temp & 0x01)
            one_num++;
        check_temp >>= 1;
    }

    check_temp = *(str + 2);
    for(i = 0;i < 8;i++)
    {
        if(check_temp & 0x01)
            one_num++;
        check_temp >>= 1;
    }

    if(one_num % 2 )
        odd = 0;
    else
        odd = 1;

    one_num = 0;

    gpio_direction_output(WG_DATA0, 1); 
    gpio_direction_output(WG_DATA1, 1);

    DELAY_800;
    if(even)
    {
        gpio_set_value(WG_DATA1, 0);
        DELAY_60;
        gpio_set_value(WG_DATA1, 1);
    }
    else
    {
        gpio_set_value(WG_DATA0, 0);
        DELAY_60;
        gpio_set_value(WG_DATA0, 1);
    }

    DELAY_800;

    gpio_set_value(WG_DATA0, 1);
    gpio_set_value(WG_DATA1, 1);

    for(j=0;j<3;j++)
    {
        check_temp = *(str + j);
        for(i = 0;i < 8;i++)
        {
        //    gpio_set_value(WG_DATA1, 1);
         //   gpio_set_value(WG_DATA0, 1);
            if(check_temp&0x80)
            {
                gpio_set_value(WG_DATA1, 0);
                DELAY_60;
                gpio_set_value(WG_DATA1, 1);
            }
            else
            {
                gpio_set_value(WG_DATA0, 0);
                DELAY_60;
                gpio_set_value(WG_DATA0, 1);
            }

            check_temp <<= 1;
            DELAY_800;
        }
    }

    gpio_set_value(WG_DATA0, 1);
    gpio_set_value(WG_DATA1, 1);

    if(odd)
    {
        gpio_set_value(WG_DATA1, 0);
        DELAY_60;
        gpio_set_value(WG_DATA1, 1);
    }
    else
    {
        gpio_set_value(WG_DATA0, 0);
        DELAY_60;
        gpio_set_value(WG_DATA0, 1);
    }

    printk("Send WG26-1: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
    DELAY_800;
    //return *str;
}

void Send_Weigand34(unsigned char *str)
{
    unsigned char one_num = 0;
    unsigned char even = 0;
    unsigned char odd = 0;
    unsigned char check_temp,i,j;

    check_temp = *str;
    
    printk("start wiegand34!\n");
    printk("Send WG34: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
    for(i = 0;i < 8;i++)
    {
        if(check_temp & 0x01)
            one_num++;
        check_temp >>= 1;
    }

    check_temp = *(str + 1);
    for(i = 0;i < 8;i++)
    {
        if(check_temp & 0x01)
            one_num++;
        check_temp >>= 1;
    }

    if(one_num % 2 )
        even = 1;
    else
        even = 0;

    one_num = 0;

    check_temp = *(str + 2);
    for(i = 0;i < 8;i++)
    {
        if(check_temp & 0x01)
            one_num++;
        check_temp >>= 1;
    }

    check_temp = *(str + 3);
    for(i = 0;i < 8;i++)
    {
        if(check_temp & 0x01)
            one_num++;
        check_temp >>= 1;
    }

    if(one_num % 2 )
        odd = 0;
    else
        odd = 1;

    one_num = 0;

    gpio_direction_output(WG_DATA0, 1); 
    gpio_direction_output(WG_DATA1, 1);

    DELAY_800;
    if(even)
    {
        gpio_set_value(WG_DATA1, 0);
        DELAY_60;
        gpio_set_value(WG_DATA1, 1);
    }
    else
    {
        gpio_set_value(WG_DATA0, 0);
        DELAY_60;
        gpio_set_value(WG_DATA0, 1);
    }

    DELAY_800;

    gpio_set_value(WG_DATA0, 1);
    gpio_set_value(WG_DATA1, 1);

    for(j=0;j<4;j++)
    {
        check_temp = *(str + j);
        for(i = 0;i < 8;i++)
        {
            gpio_set_value(WG_DATA1, 1);
            gpio_set_value(WG_DATA0, 1);
            if(check_temp&0x80)
            {
                gpio_set_value(WG_DATA1, 0);
                DELAY_60;
                gpio_set_value(WG_DATA1, 1);
            }
            else
            {
                gpio_set_value(WG_DATA0, 0);
                DELAY_60;
                gpio_set_value(WG_DATA0, 1);
            }

            check_temp <<= 1;
            DELAY_800;
        }
    }

    gpio_set_value(WG_DATA0, 1);
    gpio_set_value(WG_DATA1, 1);

    if(odd)
    {
        gpio_set_value(WG_DATA1, 0);
        DELAY_60;
        gpio_set_value(WG_DATA1, 1);
    }
    else
    {
        gpio_set_value(WG_DATA0, 0);
        DELAY_60;
        gpio_set_value(WG_DATA0, 1);
    }

    printk("Send WG34-1: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
    DELAY_2000;
}

int gpio_wgo_send(int wgtype, unsigned long wgdata)
{
    unsigned char weigen26[3]= {0x0,0x0,0x0};
    unsigned char weigen34[4]= {0x0,0x0,0x0,0x0};

    printk("gpio_wgo_send start\n ");
    if (wgtype == 26) {
        weigen26[0] = (wgdata & 0xff0000)>>16;
        weigen26[1] = (wgdata & 0xff00)>>8;
        weigen26[2] = wgdata & 0xff;
        Send_Weigand26(&weigen26[0]);
        printk("weigand26 send end\n");
    } else if (wgtype == 34) {
        weigen34[0] = (wgdata & 0xff000000)>>24;
        weigen34[1] = (wgdata & 0xff0000)>>16;
        weigen34[2] = (wgdata & 0xff00)>>8;
        weigen34[3] = wgdata & 0xff;
        Send_Weigand34(&weigen34[0]);
        printk("weigand34 send end\n");
    } else if (wgtype == 37) {
        printk(" unsupport wiegand37 output\n");
    }
    return 0;
}
void wiegand26_int_to_char(int wgdata) {
gpio_wgo_send(26, wgdata); 
}

void wiegand34_int_to_char(int wgdata) {
gpio_wgo_send(34, wgdata); 
}
static ssize_t wiegand26_show(struct device *dev, struct device_attribute *attr,
char *str) {
    printk("Send WG26-3: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
return sprintf(str, "%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
}

static ssize_t wiegand26_store(struct device *dev,
struct device_attribute *attr, const char *str,
size_t count) {
long long val = 0;
if (isStartGPIO == false) {
//注册及初始化GPIO
gpio_init();
isStartGPIO = true;
}
printk("str = %s\n", str);
sscanf(str, "%lld", &val);
printk("val = %lld\n", val);
//printk("Send WG26-12: Data:%02x%02x%02x\n",str[0], str[1], str[2]);
wiegand26_int_to_char(val);
wiegand26.flag = true;
//INIT_WORK(&work, work_handler);
//schedule_work(&work);
return count;
}

static ssize_t wiegand34_show(struct device *dev, struct device_attribute *attr,
char *str) {
    printk("Send WG34-3: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
    
return sprintf(str, "%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
}

static ssize_t wiegand34_store(struct device *dev,
struct device_attribute *attr, const char *str,
size_t count) {
long long val = 0;
if (isStartGPIO == false) {
//注册及初始化GPIO
gpio_init();
isStartGPIO = true;
}

printk("str = %s\n", str);
sscanf(str, "%lld", &val);
printk("val = %lld\n", val);
//printk("Send WG34-12: Data:%02x%02x%02x%02x\n",str[0], str[1], str[2], str[3]);
wiegand34_int_to_char(val);
wiegand34.flag = true;
//INIT_WORK(&work, work_handler);
//schedule_work(&work);

return count;
}

static ssize_t wiegand66_show(struct device *dev, struct device_attribute *attr,
char *str) {
return sprintf(str, "%s\n", wiegand66.data);
}

static ssize_t wiegand66_store(struct device *dev,
struct device_attribute *attr, const char *str,
size_t count) {
long long val = 0;
if (isStartGPIO == false) {
//注册及初始化GPIO
gpio_init();
isStartGPIO = true;
}
printk("str = %s\n", str);
sscanf(str, "%lld", &val);
printk("val = %lld\n", val);
//wiegand66_int_to_char(val);
wiegand66.flag = true;
//INIT_WORK(&work, work_handler);
//schedule_work(&work);
return count;
}

static DEVICE_ATTR(wiegand26, 0664, wiegand26_show, wiegand26_store);
static DEVICE_ATTR(wiegand34, 0664, wiegand34_show, wiegand34_store);
static DEVICE_ATTR(wiegand66, 0664, wiegand66_show, wiegand66_store);

static struct attribute *wiegand_out_attributes[] = {
&dev_attr_wiegand26.attr, &dev_attr_wiegand34.attr, &dev_attr_wiegand66.attr, NULL};

static struct attribute_group wiegand_out_attribute_group = {
.attrs = wiegand_out_attributes};

static int wiegand_out_open(struct inode *inode, struct file *file) {
return 0;
}

static int wiegand_out_close(struct inode *inode, struct file *file) {
return 0;
}

static ssize_t wiegand_out_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) {
    unsigned char wgobuff[12] = {0};

    if (count > 12)
        return -EFAULT;

    if (copy_from_user(wgobuff, buf, count))
        return -EFAULT;

    if (wgobuff[0] == 26) {
        Send_Weigand26(&wgobuff[1]);
    } else if (wgobuff[0] == 34) {
        Send_Weigand34(&wgobuff[1]);
    }

    return count;
}

static long wiegand_out_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
/* 检查设备类型 */
/*if (_IOC_TYPE(cmd) != IOC_MAGIC) {
//pr_err("[%s] command type [%c] error!\n", func, _IOC_TYPE(cmd));
return -ENOTTY;
}*/

switch (cmd) {
case IOCTL_SET_DATA0:
WG_DATA0 = arg;
break;
case IOCTL_SET_DATA1:
WG_DATA1 = arg;
break;
case IOCTL_SET_LOW_TIME:
LOW_TIME = arg;
break;
case IOCTL_SET_HIGH_TIME:
HIGH_TIME = arg;
break;
default:
break;
}
printk("wiegand %u,%ld\n", cmd, arg);
return 0;
}

static struct file_operations wiegand_out_fops = {
.owner = THIS_MODULE,
.open = wiegand_out_open,
.release = wiegand_out_close,
.write = wiegand_out_write,
.compat_ioctl = wiegand_out_ioctl,
.unlocked_ioctl = wiegand_out_ioctl,
};

static int wiegand_out_probe(struct platform_device *pdev) {
int ret = 0;

printk("wiegand_out_probe\n");

//注册设备驱动
major = register_chrdev(0, "wiegand_out", &wiegand_out_fops);
//创建类
class = class_create(THIS_MODULE, "wiegand_out");
//创建设备节点
dev = device_create(class, NULL, MKDEV(major, 0), NULL, "wiegand_out_dev");
if (IS_ERR(dev)) {
// return -1;
}
//在/sys/class/wiegand_out/wiegand_out目录下创建属性文件wiegand26
ret = device_create_file(dev, &dev_attr_wiegand26);
if (ret < 0) {
}
//在/sys/class/wiegand_out/wiegand_out_dev目录下创建属性文件wiegand34
ret = device_create_file(dev, &dev_attr_wiegand34);
if (ret < 0) {
}

//在/sys/class/wiegand_out/wiegand_out_dev目录下创建属性文件wiegand66
ret = device_create_file(dev, &dev_attr_wiegand66);
if (ret < 0) {
}

//创建属性文件的sysfs接口函数
ret = sysfs_create_group(&pdev->dev.kobj, &wiegand_out_attribute_group);

wiegand26.flag = false;
wiegand34.flag = false;
wiegand66.flag = false;

printk("wiegand_out_probe, end ret=%d\n", ret);

return ret;
}

static int wiegand_out_remove(struct platform_device *pdev) {
printk("wiegand_out_remove\n");

//删除接口函数
sysfs_remove_group(&pdev->dev.kobj, &wiegand_out_attribute_group);

device_remove_file(dev, &dev_attr_wiegand26);
device_remove_file(dev, &dev_attr_wiegand34);
device_remove_file(dev, &dev_attr_wiegand66);
//删除设备节点
device_unregister(dev);
//注销创建的设备类
class_destroy(class);
//取消注册设备驱动
unregister_chrdev(major, "wiegand_out");

if (isStartGPIO == true) {
//释放注册的GPIO编号
gpio_free(WG_DATA0);
gpio_free(WG_DATA1);
}
return 0;
}

static struct platform_driver wiegand_out_drv = {
//完成具体设备的初始化操作
.probe = wiegand_out_probe, //匹配到dev之后调用probe
//完成具体设备的退出操作
.remove = wiegand_out_remove,
.driver =
{
.name = "wiegand_out", .owner = THIS_MODULE,
//.of_match_table = of_match_ptr(wiegand_out_of_match),
},
};

static void wiegand_out_device_release(struct device *dev) { return; }

static struct platform_device wiegand_out_device = {
.name = "wiegand_out",
.id = -1,
//必须有release函数,否则卸载模块时会报"Device 'wiegand_out' does not have a
// release() function, it is broken and must be fixed."
.dev = {
.release = wiegand_out_device_release,
}};

//设备驱动模块加载函数
static int __init wiegand_out_init(void) {
int ret = 0;

printk("wiegand_out_init\n");

//创建一个单线程的工作队列
queue = create_singlethread_workqueue("weigand_send");
if (!queue) {
printk(KERN_ERR "create_singlethread_workqueue failed\n");
return -1;
}

//平台驱动注册
ret = platform_driver_register(&wiegand_out_drv);
if (ret) {
printk(KERN_ERR "platform_driver_register failed\n");
destroy_workqueue(queue);
return -1;
}

//平台设备注册
ret = platform_device_register(&wiegand_out_device);
if (ret) {
printk(KERN_ERR "platform_device_register failed\n");
platform_driver_unregister(&wiegand_out_drv);
destroy_workqueue(queue);
return -1;
}

return 0;
}

//设备驱动模块卸载函数
static void __exit wiegand_out_exit(void) {
printk("wiegand_out_exit\n");

//平台设备注销
platform_device_unregister(&wiegand_out_device);
//平台驱动注销
platform_driver_unregister(&wiegand_out_drv);
//释放工作队列所占的资源
destroy_workqueue(queue);
}

module_init(wiegand_out_init);
module_exit(wiegand_out_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hq@hqvt.ai");

以上就试韦根输出,继续看韦根输入。。。。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值