⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wg_output.c

📁 linux 2.4 的用gpio 模拟韦根输出的驱动!与标准韦根设备对接.反应灵敏!
💻 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 + -