📄 wg_output.c
字号:
#include <linux/fs.h>
#include <linux/iobuf.h>
//#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/module.h>int wg_open(struct inode*, struct file *);
int wg_close(struct inode*, struct file *);
int wg_ioctl(struct inode*inode,struct file *flip,unsigned int cmd,unsigned long arg);//#define DEBUG_WG#ifdef DEBUG_WG#define PRIN_DEBUG printk#else#define PRIN_DEBUG#endif#define WG_DATA0 GPIO_D11#define WG_DATA1 GPIO_H9#define WG26_BUFF_SIZE 180/*static int WG_MAJOR_NR=0;static unsigned char wg26_data[WG26_BUFF_SIZE];static unsigned char wg26_buff_tail=0;static unsigned char wg26_buff_head=0;//两个Weigand 输出数据最小间距250,每周期1.6ms(其中低电平0.1ms,高电平1.5ms),每个weigand26传送需要1.6*26=41.6ms// current_status= 0:当前状态空闲,可随时接受WG输出指令; =1,表示当前正在传输 ; =2表示最小时间距未到,驱动接收数据,但要等到最小间间距到才发出static unsigned char current_status=0; static unsigned char bEven;static unsigned char bOdd;static struct timer_list wg26_timer;*/static struct timer_list wg26_timer;static unsigned char current_status=0; int WG_MAJOR_NR=0;//struct timer_list wg26_timer;static struct wg26_data_ctl{ unsigned char wg26_data[WG26_BUFF_SIZE]; unsigned char wg26_out_data[26]; unsigned char wg26_buff_tail; unsigned char wg26_buff_head; //unsigned char bEven; //unsigned char bOdd; //struct timer_list wg26_timer;};static struct wg26_data_ctl wg26_p;static devfs_handle_t devfs_handle;static const char wg_name[] = "wgout";#define WG_26_CMD 1#define WG_34_CMD 2#define WG_37_CMD 3#define WG_FREE 0#define WG_BUSY 1#define WG_WAIT 2#define RET_OK 0//正常返回#define RET_ERR -1//失败#define WG_WAIT_TIME 25 //250 msstatic unsigned char Even_Parity(unsigned char *a)
{
unsigned char k,j;
unsigned char Bit_EP;
for(k=0,j=0;k<12;k++)
{
if(a[k]==0x01)
{
j++;
}
}
if((j&0x01)==0x01)
Bit_EP=1;
else
Bit_EP=0;
return(Bit_EP);
}static unsigned char Odd_Parity(unsigned char *a)
{
unsigned char Bit_OP;
unsigned char k,j;
for(k=0,j=0;k<12;k++)
{
if(a[k]==0x01)
{
j++;
}
}
if((j&0x01)==0x01)
Bit_OP=0;
else
Bit_OP=1;
return(Bit_OP);
}static void wg_output(){ unsigned char ucPE_Counter = 0;
unsigned char ucPO_Counter = 0; int i,j; unsigned char wg26_hid; unsigned short wg26_pid; wg26_hid=wg26_p.wg26_data[wg26_p.wg26_buff_tail]; wg26_pid=wg26_p.wg26_data[wg26_p.wg26_buff_tail+2]; wg26_pid=wg26_pid<<8; wg26_pid=wg26_pid+wg26_p.wg26_data[wg26_p.wg26_buff_tail+1]; //printk("wg_output: %x %x %x \n",wg26_p.wg26_data[wg26_p.wg26_buff_tail],wg26_p.wg26_data[wg26_p.wg26_buff_tail+1],wg26_p.wg26_data[wg26_p.wg26_buff_tail+2]); wg26_p.wg26_buff_tail=wg26_p.wg26_buff_tail+3; for(i=1;i<9;i++) { wg26_p.wg26_out_data[i]=(wg26_hid&0x80)>>7; wg26_hid=wg26_hid<<1; } for(i=9;i<25;i++) { if((wg26_pid&0x8000)==0x8000) wg26_p.wg26_out_data[i]=1; else wg26_p.wg26_out_data[i]=0; wg26_pid=wg26_pid<<1; } /////////////////////////////////////////////////////////////////////////// if((Even_Parity(&(wg26_p.wg26_out_data[1])))==1) wg26_p.wg26_out_data[0]=1; //wg26_p.wg26_out_data[0]=0; else //wg26_p.wg26_out_data[0]=1; wg26_p.wg26_out_data[0]=0; if((Odd_Parity(&(wg26_p.wg26_out_data[13])))==1) wg26_p.wg26_out_data[25]=1; else wg26_p.wg26_out_data[25]=0; /* printk("abc:\n"); for(i=0;i<26;i++) { printk("%d" ,wg26_p.wg26_out_data[i]); } printk("\n"); write_gpio_bit(GPIO_MODE_OUT | WG_DATA1,1); write_gpio_bit(GPIO_MODE_OUT | WG_DATA0,1); */ ///////////////////////////////////////////////////////////////////////////// for(i=0;i<26;i++) { if(wg26_p.wg26_out_data[i]==1) { write_gpio_bit(GPIO_MODE_OUT | WG_DATA1,0); udelay(100); write_gpio_bit(GPIO_MODE_OUT | WG_DATA1,1); } else { write_gpio_bit(GPIO_MODE_OUT | WG_DATA0,0); udelay(100); write_gpio_bit(GPIO_MODE_OUT | WG_DATA0,1); } for(j=0;j<10;j++) udelay(100); } #ifdef DEBUG_WG for(i=0;i<26;i++) PRIN_DEBUG("%d ",wg26_p.wg26_out_data[i]); PRIN_DEBUG("\n"); #endif}static void wg26_function(void){ if(current_status==WG_BUSY) { if(wg26_p.wg26_buff_tail>=WG26_BUFF_SIZE) { wg26_p.wg26_buff_tail=0; } wg_output(); current_status=WG_WAIT; wg26_timer.expires=jiffies+WG_WAIT_TIME; add_timer(&wg26_timer); } else if(current_status==WG_WAIT) { if(wg26_p.wg26_buff_tail==wg26_p.wg26_buff_head) { current_status=WG_FREE; del_timer(&wg26_timer); //kfree(wg26_p); } else { current_status=WG_BUSY; wg26_timer.expires=jiffies+1; add_timer(&wg26_timer); } } else;}static void begin_weigand_output(void){ current_status=WG_BUSY; init_timer(&(wg26_timer)); wg26_timer.function=wg26_function;
wg26_timer.expires = jiffies +1;
add_timer(&(wg26_timer));}static intwg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg) { switch(cmd) { case WG_26_CMD: { if(current_status==WG_FREE) { //wg26_p=kmalloc(sizeof(*wg26_p),GFP_KERNEL); //wg26_p=kmalloc(208,GFP_KERNEL); memset(&wg26_p,0,sizeof(struct wg26_data_ctl)); if(wg26_p.wg26_buff_head>=WG26_BUFF_SIZE) wg26_p.wg26_buff_head=0; copy_from_user(&(wg26_p.wg26_data[wg26_p.wg26_buff_head]),(unsigned char *)arg,3); //PRIN_DEBUG("WG_FREE:%d %d %d \n",wg26_p.wg26_data[wg26_p.wg26_buff_head],wg26_p.wg26_data[wg26_p.wg26_buff_head+1],wg26_p.wg26_data[wg26_p.wg26_buff_head]+2); wg26_p.wg26_buff_head+=3; begin_weigand_output(); //printk(" into ioctl \n"); } else { copy_from_user(&(wg26_p.wg26_data[wg26_p.wg26_buff_head]),(unsigned char *)arg,3); //PRIN_DEBUG("WG_OTHER:%d %d %d \n",wg26_p.wg26_data[wg26_p.wg26_buff_head],wg26_p.wg26_data[wg26_p.wg26_buff_head+1],wg26_p.wg26_data[wg26_p.wg26_buff_head]+2); wg26_p.wg26_buff_head+=3; } return RET_OK; } case WG_34_CMD: /* read the time/date from RTC */ { return RET_OK; } case WG_37_CMD: /* read the time/date from RTC */ { return RET_OK; } default: return -1; }}/* The various file operations we support. */static struct file_operations wg_fops = { owner: THIS_MODULE, ioctl: wg_ioctl, open: wg_open, release: wg_close,}; /* Just probe for the RTC and register the device to handle the ioctl needed. */int __initwg_init(void) { int ret; ret = register_chrdev(0, wg_name, &wg_fops);
if (ret < 0) {
printk("Driver register error!\n");
return ret; }
WG_MAJOR_NR=ret; devfs_handle = devfs_register(NULL, wg_name, DEVFS_FL_DEFAULT,WG_MAJOR_NR, 0, S_IFCHR | S_IRUSR | S_IWUSR,&wg_fops, NULL); return 0;}int wg_release(struct inode*inode, struct file *filp)
{
devfs_unregister(devfs_handle);
unregister_chrdev(WG_MAJOR_NR, wg_name);
}int wg_open(struct inode*inode, struct file *filp)
{ set_gpio_ctrl(GPIO_MODE_OUT | WG_DATA0); write_gpio_bit(GPIO_MODE_OUT | WG_DATA0,1); set_gpio_ctrl(GPIO_MODE_OUT | WG_DATA1); write_gpio_bit(GPIO_MODE_OUT | WG_DATA1,1);
return 0;
}int wg_close(struct inode*inode, struct file *filp)
{
return 0;
}module_init(wg_init);
module_exit(wg_release);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -