#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#define Delay_50us(x) usleep(x*50)
#define Delay_1ms(x) msleep(x)
#define Delay_50us(x) usleep_range(50*x,50*x+20)
#define D0_GPIO_NO 32*8+7-8 //gpio2_a7
#define D1_GPIO_NO 32*8+1-8 //gpio2_b0
static struct workqueue_struct *queue = NULL;
static struct work_struct work;
static int even =0;
static int odd =0;
struct Wiegand26{
bool flag;
char data[24];
};
struct Wiegand34{
bool flag;
char data[32];
};
struct Wiegand26 wiegand26;
struct Wiegand34 wiegand34;
static int major;
static struct class *cls;
static struct device *dev;
static int wiegandOut_open(struct inode *inode, struct file *file){
return 0;
}
static ssize_t wiegandOut_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos){
return 0;
}
static struct file_operations wiegandOut_fops = {
.owner = THIS_MODULE,
.open = wiegandOut_open,
.write = wiegandOut_write,
};
int Wiegand26_IntToChar(int data)
{
int i = 0;
odd=0;
even=0;
for (i = 0; i < 24; i++)
{
if ((1 << i) & data)
{
wiegand26.data[23-i] = '1';
if(i<12)
odd++;
else
even++;
}
else
wiegand26.data[23-i] = '0';
}
printk("in str %s \n", wiegand26.data);
printk("check even=%d,odd=%d \n",even,odd);
return 0;
}
int Wiegand34_IntToChar(int data)
{
int i =0;
odd=0;
even=0;
for (i = 0; i < 32; i++)
{
if ((1 << i) & data)
{
wiegand34.data[31-i] = '1';
if(i<16)
odd++;
else
even++;
}
else
wiegand34.data[31-i] = '0';
}
printk("in str %s \n", wiegand34.data);
printk("check even=%d,odd=%d \n",even,odd);
return 0;
}
void gpio_reset(void)
{
gpio_direction_output(D0_GPIO_NO,1);
gpio_direction_output(D1_GPIO_NO,1);
}
void Output_DATA0(void)
{
gpio_set_value(D0_GPIO_NO,0);
Delay_50us(8);
gpio_set_value(D0_GPIO_NO,1);
}
void Output_DATA1(void)
{
gpio_set_value(D1_GPIO_NO,0);
Delay_50us(8);
gpio_set_value(D1_GPIO_NO,1);
}
void Send_Wiegand34(unsigned char *str)
{
unsigned char one_num = 0;
int i =0;
// WG_DATA0 = 1;
// WG_DATA1 = 1;
gpio_reset();
Delay_1ms(2);
if(even % 2)
{
// WG_DATA1 = 0; /*偶校验位为1*/
printk("1");
// Delay_50us(8);
// WG_DATA1 = 1;
Output_DATA1();
}
else
{
Output_DATA0();
// WG_DATA0 = 0; /*偶校验位为0*/
printk("0");
//Delay_50us(8);
// WG_DATA0 = 1;
}
Delay_1ms(2); /*延时2ms*/
for(i = 0;i < 32;i++)
{
// WG_DATA0 = 1;
// WG_DATA1 = 1;
if(str[i] & 0x01)
{
// WG_DATA1 = 0;
// Delay_50us(8);
// WG_DATA1 = 1;
printk("1");
Output_DATA1();
}
else
{
// WG_DATA0 = 0;
// Delay_50us(8);
// WG_DATA0 = 1;
printk("0");
Output_DATA0();
}
//(*(long*)&str[0]) <<= 1;
Delay_1ms(2); /*延时2ms*/
}
// WG_DATA0 = 1;
// WG_DATA1 = 1;
if(odd % 2)
{
// WG_DATA0 = 0;
// Delay_50us(8);
// WG_DATA0 = 1;
printk("0");
Output_DATA0();
}
else
{
// WG_DATA1 = 0;
// Delay_50us(8);
// WG_DATA1 = 1;
printk("1");
Output_DATA1();
}
Delay_1ms(2);
}
/*
韦根26发送函数
*/
void Send_Wiegand26(unsigned char *str)
{
unsigned char one_num = 0;
int i =0;
printk("\nSend_Wiegand26 start \n");
// WG_DATA0 = 1;
// WG_DATA1 = 1;
gpio_reset();
Delay_1ms(2);
if(even % 2)
{
// WG_DATA1 = 0; /*偶校验位为1*/
// Delay_50us(8);
// WG_DATA1 = 1;
printk("1");
Output_DATA1();
}
else
{
// WG_DATA0 = 0; /*偶校验位为0*/
// Delay_50us(8);
// WG_DATA0 = 1;
Output_DATA0();
printk("0");
}
Delay_1ms(2); /*延时2ms*/
for(i = 0;i < 24;i++)
{
// WG_DATA0 = 1;
// WG_DATA1 = 1;
if(str[i] & 0x01)
{
// WG_DATA1 = 0;
// Delay_50us(8);
// WG_DATA1 = 1;
printk("1");
Output_DATA1();
}
else
{
// WG_DATA0 = 0;
// Delay_50us(8);
// WG_DATA0 = 1;
printk("0");
Output_DATA0();
}
// (*(long*)&str[0]) <<= 1;
Delay_1ms(2); /*延时2ms*/
}
// WG_DATA0 = 1;
// WG_DATA1 = 1;
if(odd % 2)
{
// WG_DATA0 = 0;
// Delay_50us(8);
// WG_DATA0 = 1;
printk("0");
Output_DATA0();
}
else
{
// WG_DATA1 = 0;
// Delay_50us(8);
// WG_DATA1 = 1;
printk("1");
Output_DATA1();
}
Delay_1ms(2);
printk("\n Send_Weigand26 end \n");
}
static void work_handler(struct work_struct *data)
{
printk(KERN_ALERT"work handler function.\n");
if(wiegand26.flag)
{
Send_Wiegand26(wiegand26.data);
wiegand26.flag =false;
}
else if(wiegand34.flag)
{
Send_Wiegand34(wiegand34.data);
wiegand34.flag =false;
}
else
{
printk(KERN_ALERT"work handler function error.\n");
}
printk(KERN_ALERT"work handler end.\n");
}
static ssize_t Wiegand26_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%s\n", wiegand26.data);
}
static ssize_t Wiegand26_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int val;
sscanf(buf, "%d", &val);
Wiegand26_IntToChar(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 *buf)
{
return sprintf(buf,"%s\n", wiegand34.data);
}
static ssize_t Wiegand34_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int val;
sscanf(buf, "%d", &val);
Wiegand34_IntToChar(val);
wiegand34.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 struct attribute *wiegandOut_attributes[] = {
&dev_attr_wiegand26.attr,
&dev_attr_wiegand34.attr,
NULL
};
static struct attribute_group wiegandOut_attribute_group = {
.attrs = wiegandOut_attributes
};
static void wiegandOut_release(struct device *dev){
}
static struct of_device_id wiegandOut_of_match[] = {
{ .compatible = "qianyi,wiegandout" },
{ }
};
MODULE_DEVICE_TABLE(of, wiegandOut_of_match);
static int wiegandOut_probe(struct platform_device *pdev){
int ret =0;
printk("wiegandOut_probe\n");
// 注册设备驱动 创建设备节点
major = register_chrdev(0, "wiegandOut", &wiegandOut_fops);
// 创建类
cls = class_create(THIS_MODULE, "wiegandOut");
// 创建设备节点
dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "wiegandOut");
ret = sysfs_create_group(&pdev->dev.kobj, &wiegandOut_attribute_group);
wiegand26.flag=false;
wiegand34.flag=false;
printk("wiegandOut_probe, end ret=%d \n",ret);
return ret;
}
static int wiegandOut_remove(struct platform_device *pdev){
printk("wiegandOut_remove, \n");
// 删除设备节点
device_unregister(dev);
// 销毁类
class_destroy(cls);
// 取消注册设备驱动
unregister_chrdev(major, "wiegandOut");
// 取消内存映射
gpio_reset();
return 0;
}
struct platform_driver wiegandOut_drv = {
.probe = wiegandOut_probe, //匹配到dev之后调用probe
.remove = wiegandOut_remove,
.driver = {
.name = "wiegandOut",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(wiegandOut_of_match),
},
};
static int __init wiegandOut_init(void)
{
int ret =0;
printk(KERN_ALERT"ace test_init function.\n");
queue=create_singlethread_workqueue("weigandSend");/*创建一个单线程的工作队列*/
if (!queue)
goto err;
// INIT_WORK(&work,work_handler);
// schedule_work(&work);
ret=platform_driver_register(&wiegandOut_drv);
printk(KERN_ALERT"ace test_init end.ret=%d \n",ret);
return 0;
err:
return -1;
}
static void __exit wiegandOut_exit(void)
{
platform_device_unregister(&wiegandOut_drv);
destroy_workqueue(queue);
}
MODULE_LICENSE("GPL");
module_init(wiegandOut_init);
module_exit(wiegandOut_exit);
///////////////////////////////////////////////////////////////////////
这里需要几点注意的地方:
1、此处没有做HID、PID的转换,直接将收到的数据做二进制转换的。如果需要的话,将收到的十进制数据分成HID和PID,再做二进制转换并发送
2、如果接收端移植无法正确识别,请查看发送的数据是否对。如果波形的数据无误,则是发送的周期太长导致接收端没能完整的接收数据,调整delay的时间即可