RK3288平台韦根接收

/*wiegand 协议接收驱动代码*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define WIEGAND_MAJOR 243        
//delay 33ms to convert data
#define TIMER_DELAY HZ/8
#define DEVICE_NAME "wiegand" 
 
bool TIMEER_FLAG = false;   
bool RF_OPEN_FLAG = false;
static struct class *cdev_class; 
//dev_t dev = 0;

#define  D0_GPIO_NO  32*8+7-8  //gpio2_a7
#define  D1_GPIO_NO  32*8+1-8  //gpio2_b0

struct wiegand_dev
{
    char wiegand[26];    //Wiegand-26
    int hid;
    int pid;
    int count;    //Global Counter
    struct cdev cdev;
    struct semaphore sem;
    struct completion receive_completion;
    struct timer_list wiegand_timer;
    struct work_struct     pen_event_work;
    struct workqueue_struct *ts_workqueue;

    int gpio_d0;
    int gpio_d1;
    int d0_irq;
    int d1_irq;
    
};

static struct wiegand_dev *rf_card;


//应该除了初始化外,只能有这一个地方能够将rf_card->count置为0,其余地方置为0皆不合法
static char convert_data(void)
{
    int i,even,odd;
        int cardno ; 

    //偶校验
        even = 0;
        for(i = 1; i < 13;i++)
        {
         if(rf_card->wiegand[i] == 1)    
          even = (~even) & 0x01; 
        }
         if(even != rf_card->wiegand[0])
          {
        rf_card->count = 0;
        goto error;
          }    
    //奇校验  
        odd = 1;
        for(i = 13; i< 25;i++)
        {
        if(rf_card->wiegand[i] == 1)             
            odd = (~odd)& 0x01;          
         }
         if(odd != rf_card->wiegand[25])
          {
        rf_card->count = 0;
           goto error;
          }

    //奇偶校验通过
    rf_card->hid = 0;
    for(i = 1 ;i<=8;i++)//hid转换
        rf_card->hid =  rf_card->hid << 1 |rf_card->wiegand[i];    

    rf_card->pid = 0;
    for(i = 9 ;i<=24;i++)//pid转换
        rf_card->pid =  rf_card->pid << 1 |rf_card->wiegand[i];    
      
        cardno = rf_card->hid << 16 | rf_card->pid;
        rf_card->count = 0;
   
        printk("%s,%s,%d,cardno=(%x,%d)\n",__FILE__,__func__,__LINE__,cardno,cardno);
    return 0;
    
error:
    printk("Parity Efficacy Error!\n");
    return -1;
}


//static void wiegand_pen_irq_work(struct work_struct *work)


static void wiegand_do_timer(unsigned long arg)
{
    //wait_for_completion(&(rf_card->receive_completion));//等待维根数据传送完毕才进行转换


        printk("%s,%s,%d,rf_card->count=%d arg=%lu\n",__FILE__,__func__,__LINE__,rf_card->count,arg);
    
    disable_irq(rf_card->d0_irq);
    disable_irq(rf_card->d1_irq);//防止wieg_data在转换期间发生变化
    
    convert_data();
    up(&rf_card->sem);
    
    rf_card->count =0 ;
    //TIMEER_FLAG = false;
    enable_irq(rf_card->d0_irq);
    enable_irq(rf_card->d1_irq);
    TIMEER_FLAG = false;
}

static void enable_irqs(void)
{    
    enable_irq(rf_card->d0_irq);
    enable_irq(rf_card->d1_irq);
    printk("%s:the irq is setup!\n",__func__);
}

static irqreturn_t wiegand_irq0(int irq, void *dev_id)
{
//    printk("%s:the irq0 !\n",__func__);
    disable_irq_nosync(rf_card->d0_irq);
    //udelay(5);

    //(gpio_get_value(rf_card->gpio_d0) == 0)
    {
           rf_card->wiegand[rf_card->count] = 0;
         rf_card->count ++;
        //udelay(100);
    } 
    //else 
    //    goto end;
    
    enable_irq(rf_card->d0_irq);
    /*
    if(rf_card->count == 1)
        init_completion(&(rf_card->receive_completion));
    else if(rf_card->count == 26)
        complete(&(rf_card->receive_completion));//只能在此处complete    
    */
       if(TIMEER_FLAG == false)
       {
        rf_card->wiegand_timer.expires = jiffies + TIMER_DELAY;
        add_timer(&rf_card->wiegand_timer);
        TIMEER_FLAG = true;
    }
    return IRQ_HANDLED;
//end:
//    enable_irq(rf_card->d0_irq);
//    return IRQ_HANDLED;

}

static irqreturn_t wiegand_irq1(int irq, void *dev_id)
{

//    printk("%s:the irq1 !\n",__func__);
    disable_irq_nosync(rf_card->d1_irq);//必须用这个函数
   
//    udelay(5);

    //if(gpio_get_value(rf_card->gpio_d1) == 0 )
    {
           rf_card->wiegand[rf_card->count] = 1;
        rf_card->count ++;
        //udelay(100);
    }
    //else
    //    goto end;
    
    enable_irq(rf_card->d1_irq);

    //rf_card->count经过上面“++”之后都会大1
    /*if(rf_card->count == 1)
        init_completion(&(rf_card->receive_completion));
    else if(rf_card->count == 26)
        complete(&(rf_card->receive_completion));//只能在此处complete*/
     if(TIMEER_FLAG== false)
       {
        rf_card->wiegand_timer.expires = jiffies + TIMER_DELAY;
        add_timer(&rf_card->wiegand_timer);
        TIMEER_FLAG = true;
    }
//    return IRQ_HANDLED;
//end:
//    enable_irq(rf_card->d1_irq);
    return IRQ_HANDLED;
}

static ssize_t rfcd_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{        
        int max_count ;  
        char cardno[12];

      //  unsigned long p = *ppos ;  

    if ( down_interruptible(&rf_card->sem) ) {
                printk("lengzhg sem error\n");
        return -1 ;
        }
        max_count  = sizeof(cardno);

        if ( size >max_count )  { 
             return 0;  
        }
        /*if ( size >(max_count-p) )  { 
             size = max_count-p;
        }*/

        sprintf(cardno,"%d",rf_card->hid << 16 | rf_card->pid);

        printk(KERN_INFO"cardno:%s\n",cardno);

    if ( copy_to_user(buf,cardno,size)){
             return -EFAULT;
        }
        //*ppos += size;

    return size;
}

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

static int request_irqs(void)
{
    int ret;

        rf_card->d0_irq = gpio_to_irq(rf_card->gpio_d0);
        rf_card->d1_irq = gpio_to_irq(rf_card->gpio_d1);

    printk("%s:d0_irq=%d,d1_irq=%d\n",__func__, rf_card->d0_irq , rf_card->d1_irq );
    
    ret = request_irq(rf_card->d0_irq,wiegand_irq0,IRQF_SHARED | IRQF_TRIGGER_FALLING,"wiegand_data0",rf_card);

    if(ret)
    {
        printk("%s:request rf_card->d1_irq):%d,ret:%d failed!\n",__func__,rf_card->d0_irq,ret);
        return -1;   
    }
    ret = request_irq(rf_card->d1_irq,wiegand_irq1,IRQF_SHARED | IRQF_TRIGGER_FALLING,"wiegand_data1",rf_card);

    if(ret) 
    {
        printk("%s:request rf_card->d1_irq:%d,ret:%d failed!\n",__func__,rf_card->d1_irq,ret);
        return -1;   
    }

    printk(KERN_INFO"%s:request irqs success!\n",__func__);
    return 0;
}

static int rfcd_open(struct inode *inode, struct file *filp)
{
       if (RF_OPEN_FLAG)  { 
           return -EBUSY;//Don't open again!

     }        
    RF_OPEN_FLAG = true;
    TIMEER_FLAG = false;

    //setup_timer(&rf_card->wiegand_timer,wiegand_do_timer,0);
        printk("lengzhg %s: wiegand open\n",__func__);

    memset(rf_card->wiegand,0x00,26);
    rf_card->count = 0;

//    enable_irqs();

    printk("lengzhg %s: the device have been open\n",__func__);
    return 0;
}

static void free_irqs(void)
{
    free_irq(rf_card->d0_irq,rf_card);
    free_irq(rf_card->d1_irq,rf_card);
}

int rfcd_release(struct inode *inode, struct file *filp)
{
//    disable_irq(rf_card->d0_irq);
//    disable_irq(rf_card->d1_irq);

    RF_OPEN_FLAG = false;

//    del_timer_sync(&rf_card->wiegand_timer);
    return 0; 
}

static struct file_operations rfcd_fops = 
{
    .owner = THIS_MODULE,
    .read = rfcd_read,
    .write = rfcd_write,
    .open = rfcd_open,
    .release = rfcd_release,
};

static int __init wiegand_init(void)
{
    int err,result;
    dev_t devno = MKDEV(WIEGAND_MAJOR, 1);
        int ret ; 

    //if(WIEGAND_MAJOR)
    if(0)
        result = register_chrdev_region(devno,1,DEVICE_NAME);   
    else
        result = alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
    
    if(result < 0)
    {
        printk("lengzhg %s:register_chrdev_region error\n",__func__);
        return result;
    }

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

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

    rf_card->count = 0;

    cdev_init(&(rf_card->cdev), &rfcd_fops);
     
    rf_card->cdev.owner = THIS_MODULE;

    err = cdev_add(&rf_card->cdev, devno, 1);

    if(err)
    {
        printk("lengzhg adding err\r\n");
        unregister_chrdev_region(devno,1);
        kfree(rf_card);
        free_irqs();
        return err;
    }
 
    cdev_class = class_create(THIS_MODULE, DEVICE_NAME);//动态创建设备结点
    if(IS_ERR(cdev_class))
    { 
        printk("ERR:cannot create a cdev_class\n");
        unregister_chrdev_region(devno,1);
        return -1;
    }
    device_create(cdev_class,NULL, devno, 0, DEVICE_NAME);
 
    init_completion(&(rf_card->receive_completion));
    sema_init(&rf_card->sem,0);

    rf_card->gpio_d0 = D0_GPIO_NO;
    rf_card->gpio_d1 = D1_GPIO_NO;    

      ret = gpio_request(rf_card->gpio_d0, "wiegand_d0");
        if ( ret ) {
        printk("request gpio_d1 error\n");
        goto fail_malloc;
        }
      ret = gpio_request(rf_card->gpio_d1, "wiegand_d1");
        if ( ret ) {
           printk("request gpio_d1 error\n");
         goto fail_malloc;
        }
    result = request_irqs();

    if(result < 0)
    {
        printk("%s:request_irqs error\n",__func__);
        return result;
    }
    setup_timer(&rf_card->wiegand_timer,wiegand_do_timer,0);

    //disable_irq(rf_card->d0_irq);
    //disable_irq(rf_card->d1_irq);
//    INIT_WORK(&rf_card->pen_event_work, wiegand_pen_irq_work);
    
    printk (KERN_INFO "%s initialized\n",DEVICE_NAME);
    return 0;

fail_malloc: 
    unregister_chrdev_region(devno,1);
    
    return result;
}

static void __exit wiegand_exit(void)
{

    cdev_del(&rf_card->cdev);
    free_irqs();
    kfree(rf_card);
    unregister_chrdev_region(MKDEV(WIEGAND_MAJOR,0),1);
    printk (KERN_INFO"%s removed\n",DEVICE_NAME);
}

module_init(wiegand_init);
module_exit(wiegand_exit);

MODULE_AUTHOR("[email protected]");
MODULE_LICENSE("GPL");
 

 

测试程序:

#include
#include
#include
#include
#include

int main()
{
 int fd = 0;
 char dst[12] ={ 0};
 int result =0;
 fd = open("/dev/wiegand", O_RDWR);
 if(fd < 0)
 {
        printf("file open error ! \n");
     return -1;
 }
 while(1)
{
 result=read(fd, dst, sizeof(dst));
 printf("dst0 is %s,  size=%d\n", dst,result);
 sleep(1);
}
   /*关闭设备*/
 close(fd);

 return 0;
}

你可能感兴趣的:(RK3288平台韦根接收)