以下代码为韦根26位发送代码,实际项目已经验证过,发送部分没有经过验证,思路可参考,实际调试过程如果有问题,建议使用示波器抓波形,按26位韦根协议对比波形调试,按部就班即可完成。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#define INVALID_GPIO -1
#define uchar unsigned char
#define USE_INT
struct proc_dir_entry *gpio_extend_dir;
static struct class *rk_gpio_class = NULL;
void Send_Wiegand26(unsigned char *str);
static int Wiegand26_IntToChar(int data);
extern void rk_send_power_key(int state);
extern void rk_send_wakeup_key(void);
static int gpio2_a0;
static int gpio2_a1;
static int gl_value = 0;
static int irq_gpio2_a0;
static int irq_gpio2_a1;
static int even=0;
static int odd =0;
struct Wiegand26{
bool flag;
char data[24];
};
struct Wiegand26 wiegand26;
static char tmp[28];
static char send_tmp[30];
static int irq_count = 0;
static struct of_device_id gpio_of_match[] = {
{ .compatible = "gpio_ctrl" },
{ }
};
static void WG_send_bit_0(void);
static void WG_send_bit_1(void);
MODULE_DEVICE_TABLE(of, gpio_of_match);
static ssize_t gpio_write_proc_string(struct file *file, const char __user *buffer,
size_t count, loff_t *pos)
{
char *buf;
char buf2[11] = {0};
//int i = 0;
int ret;
if (count < 1)
return -EINVAL;
buf = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, buffer, count)) {
kfree(buf);
return -EFAULT;
}
printk("gpio_write_proc_string gpio buf = %s\n", buf);
strncpy(buf2, buf, ((count > sizeof(buf2)) ? sizeof(buf2) : count));
buf2[10] = '\0';
printk("buf2 = %s\n", buf2);
kfree(buf);
return count;
}
static int gpio_str_proc_show(struct seq_file *m, void *v)
{
printk("gpio_str_proc_show something\n");
return 0;
}
static int gpio_str_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, gpio_str_proc_show, NULL);
}
static int gpio_str_proc_read(struct file *file, char *buffer,
size_t count, loff_t *pos)
{
if (count < 1)
return -EINVAL;
printk("tmp = %s\n", tmp);
if (copy_to_user(buffer, tmp, count)) {
//gpio_unlock(&gpio_lock);
return -EFAULT;
}
//gpio_unlock(&gpio_lock);
return 1;
}
static const struct file_operations gpio_extend_fops = {
.owner = THIS_MODULE,
.open = gpio_str_proc_open,
.read = gpio_str_proc_read,
.llseek = seq_lseek,
.release = single_release,
.write = gpio_write_proc_string,
};
static ssize_t switch_show(struct class *cls,struct class_attribute *attr, char *_buf)
{
printk("%s>>>>>>>>\n",__func__);
ssize_t len = 0;
int value = 0;
value = gl_value;
len += snprintf(_buf + len, PAGE_SIZE - len, "%d \r\n", value);
return len;
}
static ssize_t switch_store(struct class *cls,struct class_attribute *attr, const char *buf, size_t _count)
{
gl_value = simple_strtol(buf,NULL,10);
if(gl_value == 1)
{
printk(KERN_INFO "gl_value is %d\n",gl_value);
gpio_direction_input(gpio2_a0);
gpio_direction_input(gpio2_a1);
enable_irq(irq_gpio2_a0);
enable_irq(irq_gpio2_a1);
}
else if( gl_value == 0)
{
printk(KERN_INFO "gl_value is %d\n",gl_value);
disable_irq(irq_gpio2_a0);
disable_irq(irq_gpio2_a1);
gpio_direction_output(gpio2_a0, 1);
gpio_direction_output(gpio2_a1, 1);
}
return _count;
}
//0010 0100 0111 0011 0011 1100
static ssize_t send_show(struct class *cls,struct class_attribute *attr, char *_buf)
{
printk("%s>>>>>>>>\n",__func__);
ssize_t len = 0;
int value = 0;
value = gl_value;
len += snprintf(_buf + len, PAGE_SIZE - len, "%d \r\n", value);
return len;
}
static ssize_t send_store(struct class *cls,struct class_attribute *attr, const char *buf, size_t _count)
{
int value;
printk("hxl buf = %s\n", buf);
if(gl_value)
return _count;
strcpy(send_tmp,buf);
printk("hxl send_tmp = %s\n", send_tmp);
value = simple_strtol(buf,NULL,10);
// sscanf(buf, "%d", &value);
printk("send_store ============= %x\n",value);
Wiegand26_IntToChar(value);
Send_Wiegand26(wiegand26.data);
return _count;
}
static CLASS_ATTR(switch, 0664, switch_show, switch_store);
static CLASS_ATTR(send, 0664, send_show, send_store);
static int gpio_sys_init(void)
{
int ret ;
rk_gpio_class = class_create(THIS_MODULE, "wg_switch");
ret = class_create_file(rk_gpio_class, &class_attr_switch);
if (ret)
{
printk("Fail to creat class gpio5c1.\n");
}
ret = class_create_file(rk_gpio_class, &class_attr_send);
if (ret)
{
printk("Fail to creat class gpio5c3.\n");
}
return 0;
}
static void WG_send_bit_1(void)
{
//WG_DATA1 = 0;
gpio_direction_output(gpio2_a1, 0);
//----------------------延时100us
//delay_100us();
udelay(100);
//WG_DATA1 = 1;
gpio_direction_output(gpio2_a1, 1);
//-------------------------------延时一个发送周期
//delay_1500us();
udelay(1500);
}
static void WG_send_bit_0(void)
{
//WG_DATA0 = 0;
gpio_direction_output(gpio2_a0, 0);
//----------------------延时100us
udelay(100);
//delay_100us();
//WG_DATA0 = 1;
gpio_direction_output(gpio2_a0, 1);
//-------------------------------延时一个发送周期
//delay_1500us();
udelay(1500);
}
static int Wiegand26_IntToChar(int data)
{
int i = 0;
odd = 0;
even = 0;
for(i = 0; i < 24; i++)
{
if(send_tmp[i] =='1')
{
wiegand26.data[i] = '1';
if(i < 12)
even ++;
else
odd ++;
}
else
wiegand26.data[i] = '0';
}
printk("in str %s \n", wiegand26.data);
printk("check even=%d,odd=%d \n",even,odd);
return 0;
}
void gpio_reset(void)
{
gpio_direction_output(gpio2_a0,1);
gpio_direction_output(gpio2_a1,1);
}
void Output_DATA0(void)
{
gpio_direction_output(gpio2_a0, 0);
udelay(400);
gpio_direction_output(gpio2_a0, 1);
}
void Output_DATA1(void)
{
gpio_direction_output(gpio2_a1, 0);
udelay(400);
gpio_direction_output(gpio2_a1, 1);
}
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;
printk("hxl ===even % 2 = %d\n",even % 2);
gpio_reset();
udelay(2000);
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");
}
udelay(2000);/*延时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;
udelay(2000);/*延时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();
}
udelay(2000);
printk("\n Send_Weigand26 end \n");
}
static irqreturn_t weigen_read1(int irq, void *dev_id)
{
//printk("0 \n");
tmp[irq_count] = '0';
irq_count++;
if (irq_count > 25)
{
irq_count = 0;
}
return IRQ_HANDLED;
}
static irqreturn_t weigen_read2(int irq, void *dev_id)
{
tmp[irq_count] = '1';
irq_count++;
if (irq_count > 25)
{
irq_count = 0;
}
return IRQ_HANDLED;
}
static int gpio_control_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device *dev = &pdev->dev;
enum of_gpio_flags flags;
int ret,error;
int en_value;
struct proc_dir_entry *ent;
printk("hxl func: %s\n", __func__);
if (!node)
return -ENODEV;
printk("gpio_control_prob hxl #####\n");
gpio2_a0 = of_get_named_gpio_flags(node, "gpio_control_1", 0, &flags);
en_value = (flags == GPIO_ACTIVE_HIGH)? 1:0;
//gpio = of_get_named_gpio(node, "gpios", 0);
if(!gpio_is_valid(gpio2_a0)){
dev_err(&pdev->dev, "invalid gpio_control gpio%d\n", gpio2_a0);
}
printk("gpio_request hxl ####\n");
ret = devm_gpio_request(&pdev->dev, gpio2_a0, "gpio1");
if (ret) {
dev_err(&pdev->dev,
"failed to request GPIO%d for otg_drv\n",
gpio2_a0);
return -EINVAL;
}
printk("set gpio direction_output hxl ###");
//gpio_direction_output(gpio2_a0, en_value);
gpio_direction_input(gpio2_a0);
#ifdef USE_INT
irq_gpio2_a0 = gpio_to_irq(gpio2_a0);
if (irq_gpio2_a0 < 0) {
printk("gpio-keys: Unable to get irq number for GPIO %d\n",
gpio2_a0);
gpio_free(gpio2_a0);
//goto fail1;
}
error = devm_request_irq(dev, irq_gpio2_a0, weigen_read1,
IRQF_TRIGGER_FALLING,
"gpio2_a0",
NULL);
if (error) {
pr_err("gpio-keys: Unable to irq_gpio2_a0 irq %d; error %d\n",
irq_gpio2_a0, error);
gpio_free(gpio2_a0);
}
disable_irq(irq_gpio2_a0);
#endif
gpio2_a1 = of_get_named_gpio_flags(node, "gpio_control_2", 0, &flags);
en_value = (flags == GPIO_ACTIVE_HIGH)? 1:0;
//gpio = of_get_named_gpio(node, "gpios", 0);
if(!gpio_is_valid(gpio2_a1)){
dev_err(&pdev->dev, "invalid gpio_control gpio%d\n", gpio2_a1);
}
ret = devm_gpio_request(&pdev->dev, gpio2_a1, "gpio2");
if (ret) {
dev_err(&pdev->dev,
"failed to request GPIO%d for otg_drv\n",
gpio2_a1);
return -EINVAL;
}
printk("set gpio direction_output hxl ###");
//gpio_direction_output(gpio2_a1, en_value);
gpio_direction_input(gpio2_a1);
//#if 0
#ifdef USE_INT
irq_gpio2_a1 = gpio_to_irq(gpio2_a1);
if (irq_gpio2_a1 < 0) {
printk("gpio-keys: Unable to get irq number for GPIO %d\n",
gpio2_a1);
gpio_free(gpio2_a1);
//goto fail1;
}
#if 0
error = devm_request_threaded_irq(dev, irq, NULL,weigen_read2,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"gpio2_a1",
NULL);
#else
error = devm_request_irq(dev, irq_gpio2_a1, weigen_read2,
IRQF_TRIGGER_FALLING,
"gpio2_a1",
NULL);
#endif
if (error) {
pr_err("gpio-keys: Unable to irq_gpio2_a1 irq %d; error %d\n",
irq_gpio2_a1, error);
gpio_free(gpio2_a1);
//goto fail1;
}
disable_irq(irq_gpio2_a1);
#endif
gpio_direction_output(gpio2_a0, 1);
gpio_direction_output(gpio2_a1, 1);
gpio_extend_dir = proc_mkdir("gpio_extend", NULL);
if(gpio_extend_dir == NULL)
{
printk("unable to creat /proc/gpio_extend directory\n");
return -ENOMEM;
}
ent = proc_create("gpio_str", 0666, gpio_extend_dir, &gpio_extend_fops);
if(ent == NULL)
{
printk("unable to create /proc/gpio_extend/gpio_str entry");
//goto fail;
}
gpio_sys_init();
return 0;
file:
printk("func: %s some error\n", __func__);
return 0;
}
static int gpio_control_remove(struct platform_device *pdev)
{
//printk("func: %s\n", __func__);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int gpio_control_suspend(struct device *dev)
{
//printk("func: %s\n", __func__);
return 0;
}
static int gpio_control_resume(struct device *dev)
{
//printk("func: %s\n", __func__);
return 0;
}
#endif
static const struct dev_pm_ops gpio_control_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend = gpio_control_suspend,
.resume = gpio_control_resume,
.poweroff = gpio_control_suspend,
.restore = gpio_control_resume,
#endif
};
static struct platform_driver gpio_driver = {
.driver = {
.name = "gpio_control",
.owner = THIS_MODULE,
.pm = &gpio_control_ops,
.of_match_table = of_match_ptr(gpio_of_match),
},
.probe = gpio_control_probe,
.remove = gpio_control_remove,
};
module_platform_driver(gpio_driver);
MODULE_DESCRIPTION("gpio_control");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio_control");