i2c-dev-zlg7290led.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*)®, 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 + -