欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

i2c-dev-zlg7290led.c

本字符设备驱动在Linux2.6中测试通过
C
字号:
/*    i2c-dev-7290led.c - i2c-bus driver, comunicate to zlg7290      Written by Richard R.Zhang    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//* $Id: i2c-dev.c,v 1.2 2004/02/06 13:19:45 laputa Exp $ */#include <linux/config.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/slab.h>#include <linux/version.h>//#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)#include <linux/smp_lock.h>//#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) *///#ifdef CONFIG_DEVFS_FS#include <linux/devfs_fs_kernel.h>//#endif/* If you want debugging uncomment: *//* #define DEBUG */#include <linux/init.h>#include <asm/uaccess.h>#include <linux/i2c.h>#include <linux/poll.h>#include <linux/delay.h>//#include "dbg_msg.h"//#include "i2c-zlg7290.h"//#include "cmd_kbd_mouse.h"/* debug macros */#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK(x...) {printk(__FUNCTION__"(%d): ",__LINE__);printk(##x);}#else#define DPRINTK( x... )#endifstatic int i2c_zlg7290_attach_adapter(struct i2c_adapter *adap);static int i2c_zlg7290_detach_client(struct i2c_client *client);static int i2c_zlg7290_command(struct i2c_client *client, unsigned int cmd, void *arg);static int __init i2c_zlg7290_init(void);static void i2c_zlg7290_cleanup(void);#define I2CDEV_ADAPS_MAX  0x08               //I2C_ADAP_MAXstatic struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];//#define I2COWNER_ADDRESS		(0x10>>1)#define ZLG7290_I2CADDRESS		(0x70>>1)			//ZLG7290 的从地址 slave address 为70H,写为71Hstatic struct i2c_driver i2c_zlg7290_driver = {	name:			"I2C ZLG7290 Driver",	id:				I2C_DRIVERID_I2CDEV,	flags:			I2C_DF_NOTIFY,	attach_adapter:	i2c_zlg7290_attach_adapter,	detach_client:		i2c_zlg7290_detach_client,	command:		i2c_zlg7290_command,/*	inc_use:	NULL,	dec_use:	NULL, */};static struct i2c_client zlg7290_client = {	name:		"I2C ZLG7290",	//id:			2,							//modified by quentin	flags:		0,	addr:		ZLG7290_I2CADDRESS,	adapter:	NULL,	driver:		&i2c_zlg7290_driver,//	slvRecvNotify:	i2c_zlg7290_slvRcv,	};/*========================================================	zlg7290 led.========================================================*/static ssize_t zlg7290_read (struct file *file, char *buf, size_t count,  loff_t *offset);static ssize_t zlg7290_write (struct file *file, const char *buf, size_t count,loff_t *offset);static int zlg7290_open (struct inode *inode, struct file *file);static int zlg7290_release (struct inode *inode, struct file *file);static int zlg7290_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);#define ZLG7290_MINOR		5#define ZLG7290_NAME		"ZLG7290 LED"static int zlg7290major=0;//#ifdef  CONFIG_DEVFS_FS//static devfs_handle_t devfs_handle=NULL;//static devfs_handle_t devfs_dir=NULL;#define zlg7290_Devfs_path "zlg7290/0"//#endifstruct REG_MODE {	unsigned char addr;	//寄存器接口方式	unsigned char ctrl;}__attribute__ ((packed)) ;//一个完整的指令须在一个I2C 帧中起始信号和结束信号间连续传输到命令缓冲区//CmdBuf0 CmdBuf1 中否则会引起错误/*struct PURECMD_MODE  {			//纯指令方式	unsigned char cmd;	unsigned char ctrl;} __attribute__ ((packed)) ;*//*struct CPLXCMD_MODE  {			//复合指令方式	unsigned char cmd_buf0;	unsigned char ctrl0;		unsigned char cmd_buf1;		unsigned char ctrl1;	} __attribute__ ((packed)) ;*/struct CPLXCMD_MODE  {			//复合指令方式	unsigned char cmd_buf0;	unsigned char ctrl0;		unsigned char ctrl1;	} __attribute__ ((packed)) ;//ZLG7290 addr#define ZLG7290_ADDR_SystemReg		0x00		#define ZLG7290_ADDR_FlashOnOff		0x0c		#define ZLG7290_ADDR_ScanNum				0x0d		#define ZLG7290_ADDR_DpRam0			0x10		#define ZLG7290_ADDR_DpRamBase		ZLG7290_ADDR_DpRam0		#define ZLG7290_ADDR_DpRam1	     (ZLG7290_ADDR_DpRamBase+0x01)		#define ZLG7290_ADDR_DpRam2	     (ZLG7290_ADDR_DpRamBase+0x02)		#define ZLG7290_ADDR_DpRam3	     (ZLG7290_ADDR_DpRamBase+0x03)		#define ZLG7290_ADDR_DpRam4	     (ZLG7290_ADDR_DpRamBase+0x04)		#define ZLG7290_ADDR_DpRam5	     (ZLG7290_ADDR_DpRamBase+0x05)		#define ZLG7290_ADDR_DpRam6	     (ZLG7290_ADDR_DpRamBase+0x06)		#define ZLG7290_ADDR_DpRam7	     (ZLG7290_ADDR_DpRamBase+0x07)		#define ZLG7290_ADDR_CmdBuf0			0x07		/* in */#define ZLG7290_ADDR_CmdBuf1	     (ZLG7290_ADDR_CmdBuf0+0x01)/* in *///left keyborad, added by quentin//ZLG7290 instructions//pure instructions#define ZLG7290_INS_LSL				(0x10)		/* 逻辑左移Mask */#define ZLG7290_INS_LSR				(0x20)		/* 逻辑右移Mask */#define ZLG7290_INS_ROL				(0x30)		/* 循环左移Mask */#define ZLG7290_INS_ROR				(0x40)		/* 循环右移Mask */#define ZLG7290_INS_SystemReg			(0x50)		/* 循环右移Mask *///compound  instructions#define ZLG7290_INS_Dispt0			(0x01)		/* 显示象素寻址Mask */#define ZLG7290_INS_Dispt1			(0x00)		#define ZLG7290_INS_DlDecod0			(0x60)		/* 下载并译码Mask */#define ZLG7290_INS_DlDecod1			(0x00)		#define ZLG7290_INS_Wink0			(0x70)		/* 闪烁Mask */#define ZLG7290_INS_Wink1			(0x00)		static struct file_operations zlg7290_fops = {	.owner=     THIS_MODULE,	.read=      zlg7290_read,	.write=     zlg7290_write,	.open=  	zlg7290_open,	.ioctl=	zlg7290_ioctl,	.release=	zlg7290_release,//	poll:			zlg7290_poll,};static ssize_t zlg7290_read (struct file *file, char *buf, size_t count,loff_t *offset){	return 0;}static ssize_t zlg7290_write (struct file *file, const char *buf, size_t count,loff_t *offset){	int ret;	unsigned char *tmp;     // +- modify 030903 	struct i2c_client *client = &zlg7290_client;	DPRINTK("==>i2c dev  write buf [%s] addr[%x] \n",buf,client->addr);	tmp = kmalloc(count,GFP_KERNEL);	if (tmp==NULL)		return -ENOMEM;		if (copy_from_user(tmp,buf,count)) {		kfree(tmp);		return -EFAULT;	}	DPRINTK("i2c/zlg7290/0  writing %d bytes.\n", count);		ret =i2c_master_send(client,tmp,count);		kfree(tmp);	return ret;}static int zlg7290_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 				unsigned long arg){	int ret;	struct REG_MODE reg;	struct CPLXCMD_MODE cplx;	struct i2c_client *client = &zlg7290_client;		switch(cmd) {	case ZLG7290_ADDR_FlashOnOff:	case ZLG7290_ADDR_ScanNum:	case ZLG7290_ADDR_DpRam0:	case ZLG7290_ADDR_DpRam1:	case ZLG7290_ADDR_DpRam2:	case ZLG7290_ADDR_DpRam3:	case ZLG7290_ADDR_DpRam4:	case ZLG7290_ADDR_DpRam5:	case ZLG7290_ADDR_DpRam6:	case ZLG7290_ADDR_DpRam7:			case ZLG7290_ADDR_CmdBuf0:	case ZLG7290_ADDR_CmdBuf1:		reg.addr=(unsigned char)cmd;		reg.ctrl=(unsigned char)arg;ret = i2c_master_send(client, (const char*)&reg, sizeof(struct REG_MODE));		if(ret<0){			DPRINTK("i2c_master_send exception %d",ret);		}		break;			case ((ZLG7290_ADDR_CmdBuf1 <<4)|ZLG7290_ADDR_CmdBuf0):		cplx.cmd_buf0=(unsigned char) ZLG7290_ADDR_CmdBuf0;//		cplx.cmd_buf1=(unsigned char) ZLG7290_ADDR_CmdBuf1;		cplx.ctrl0=(unsigned char) (arg& 0xff);		cplx.ctrl1=(unsigned char) ((arg& 0xff00)>>8);		ret = i2c_master_send(client, (const char*)&cplx, sizeof(struct CPLXCMD_MODE));		break;	/*			case ((ZLG7290_ADDR_CmdBuf1 <<4)|ZLG7290_ADDR_CmdBuf0):		cplx.cmd_buf0=(unsigned char) ZLG7290_ADDR_CmdBuf0;		cplx.cmd_buf1=(unsigned char) ZLG7290_ADDR_CmdBuf1;		cplx.ctrl0=(unsigned char) (arg& 0xff);		cplx.ctrl1=(unsigned char) ((arg& 0xff00)>>8);		ret = i2c_master_send(client, (const char*)&cplx, sizeof(struct CPLXCMD_MODE));		break;	*/	default:		break;		}		return 0;}static int zlg7290_release (struct inode *inode, struct file *file){	return 0;}static int zlg7290_open (struct inode *inode, struct file *file){	return 0;}//#ifdef CONFIG_DEVFS_FS//static devfs_handle_t zlg7290_init (devfs_handle_t parent)//#else   //#endifstatic int zlg7290_init(void){	int ret;	ret = register_chrdev(0, ZLG7290_NAME, &zlg7290_fops);	if (ret < 0) {		DPRINTK(ZLG7290_NAME" can't be registered\n");//#ifdef CONFIG_DEVFS_FS		//return NULL;//#else		//return ret;//#endif	}		zlg7290major = ret;//#ifdef CONFIG_DEVFS_FS      devfs_mk_cdev(MKDEV(zlg7290major, ZLG7290_MINOR),S_IFCHR | S_IRUSR | S_IWUSR,zlg7290_Devfs_path);    	//devfs_dir = devfs_mk_dir(parent, "zlg7290", NULL);	//devfs_handle = devfs_register (devfs_dir, "0",			//DEVFS_FL_DEFAULT,zlg7290major, ZLG7290_MINOR,			//S_IFCHR | S_IRUSR | S_IWUSR,			///&zlg7290_fops, NULL);//#endif	DPRINTK("Registered '%s' as minor %d\n","led", ZLG7290_MINOR);//#ifdef CONFIG_DEVFS_FS	return  0;   //devfs_handle;//#else	//return 0;//#endif}static void zlg7290_exit (void){//#ifdef	CONFIG_DEVFS_FS	//devfs_unregister(devfs_handle);	//devfs_unregister(devfs_dir);	//devfs_handle = NULL;	//devfs_dir = NULL;//#endif        devfs_remove(zlg7290_Devfs_path);	unregister_chrdev(zlg7290major, ZLG7290_NAME);}static int i2c_zlg7290_attach_adapter(struct i2c_adapter *adap){	int i;	char name[8];	if ((i = i2c_adapter_id(adap)) < 0) {		DPRINTK("Unknown adapter ?!?\n");		return -ENODEV;	}		if (i >= I2CDEV_ADAPS_MAX) {		DPRINTK("Adapter number too large?!? (%d)\n",i);		return -ENODEV;	}	sprintf (name, "%d", i);	if (! i2cdev_adaps[i]) {		i2cdev_adaps[i] = adap;		zlg7290_client.adapter = adap;				//链表挂载		i2c_attach_client(&zlg7290_client);			//链表挂载//	DPRINTK("in i2c_zlg7290_attach_adapter\n");//#if (CONFIG_I2C_ZLG7290_LED || CONFIG_I2C_ZLG7290_LED_MODULE)		/* init zlg7290 led*///#ifdef CONFIG_DEVFS_FS		//zlg7290_init (devfs_find_handle(NULL, "i2c", 0, 0, 0, 0));//#else		zlg7290_init();///#endif//#endif //#ifdef CONFIG_I2C_ZLG7290_LED#ifdef DEBUG		DPRINTK("Adapter registered: %s\n",adap->name);#endif	} else {		i2cdev_adaps[i] = NULL;		DPRINTK ("detach_client\n");		i2c_detach_client (&zlg7290_client);		//#if (CONFIG_I2C_ZLG7290_LED || CONFIG_I2C_ZLG7290_LED_MODULE)		/* init zlg7290 led*///#ifdef CONFIG_DEVFS_FS		zlg7290_exit ();//#endif//#endif //#ifdef CONFIG_I2C_ZLG7290_LED#ifdef DEBUG		DPRINTK("Adapter unregistered: %s\n",adap->name);#endif	}	return 0;}static int i2c_zlg7290_detach_client(struct i2c_client *client){	return 0;}static int i2c_zlg7290_command(struct i2c_client *client, unsigned int cmd,                           void *arg){	return -1;}//static int i2c_zlg7290_initialized;static int __init i2c_zlg7290_init(void){	int res;	DPRINTK(KERN_DEBUG "i2c /dev entries driver module\n");	if ((res = i2c_add_driver(&i2c_zlg7290_driver))) {		DPRINTK("Driver registration failed, module not inserted.\n");		i2c_zlg7290_cleanup();		return res;	}	//	i2c_zlg7290_initialized ++;	if(res<0){		DPRINTK("set ower address failed!.\n");		DPRINTK("set chip controller failed!.\n");	}		return 0;}static void i2c_zlg7290_cleanup(void){	int res;#if 0	if (i2c_zlg7290_initialized >= 2) {		if ((res = i2c_del_driver(&i2c_zlg7290_driver))) {			DPRINTK("Driver deregistration failed, "			       "module not removed.\n");			return;		}		i2c_zlg7290_initialized --;	}	if (i2c_zlg7290_initialized >= 1) {		i2c_zlg7290_initialized --;	}#endif	if ((res = i2c_del_driver(&i2c_zlg7290_driver))) {		DPRINTK("Driver deregistration failed, "		       "module not removed.\n");		return;	}	}//EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Richard R.Zhang");MODULE_DESCRIPTION("I2C ZLG7290 driver");MODULE_LICENSE("GPL");module_init(i2c_zlg7290_init);module_exit(i2c_zlg7290_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -