驱动版本的i2cdetect

    这里写了一个驱动版本的i2cdect。其中先写/proc/i2cdetectall节点,然后读可以探测所有的i2c地址,

写节点/proc/i2cdetect然后读可以探测单条总线的i2c地址。对于检测不到的i2c地址,可重新看下芯片手册

或者检查硬件电路(如芯片有没有上电,i2c有没有上拉)。

原理:往i2c总线的所有可能地址发一个字节,如果应答了表示该地址存在。

源码如下

#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/i2c.h>
#include <linux/delay.h>

//i2cdetect all
//echo > /proc/i2cdetectall
//cat  /proc/i2cdetectall

//i2cdect i2_n address
//echo n > /proc/i2cdetect
//cat /proc/i2cdetect
unsigned char tbuf=0;
unsigned int i2c_bus;
unsigned int i2c_bus_count=0;
unsigned int i2c_bus_list[20];
unsigned char i2c_addr[256];

struct i2c_msg msg={
	.flags = 0,
	.buf   = &tbuf,
	.len=1,
};

static int i2c_detect_show(struct seq_file *m, void *v)
{
	unsigned char addr;
	seq_printf(m,"found i2c_%d address:\n",i2c_bus);
	for(addr=0x1;addr<0x80;addr++)
	{	
		if(i2c_addr[addr]!=0xff)
			seq_printf(m,"0x%x ",i2c_addr[addr]);
	}
	seq_printf(m,"\n");
	return 0;
}

ssize_t i2c_detect_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
	
    	int addr;
	int ret;
	struct i2c_adapter *adapter;
	memset(i2c_addr,0xff,sizeof(i2c_addr));
	i2c_bus=simple_strtoul(buffer,NULL,10);
	printk("i2c_bus=%d\n",i2c_bus);
    	adapter = i2c_get_adapter(i2c_bus); 
    	if (!adapter) {
        	printk("get i2c_%d adapter err\n",i2c_bus);  
        	return -ENODEV;
    	} else {
        	printk("get i2c_%d adapter ok\n",i2c_bus);
    	}
	for(addr=0x1;addr<0x80;addr++){
		msg.addr=addr;
		ret=i2c_transfer(adapter, &msg, 1);
		if(ret>0)
		{
			printk("found i2c addr 0x%0x\n",addr);
			i2c_addr[addr]=addr;
		}
	};
	i2c_put_adapter(adapter); 
	return count;
}

//0xff addr1 addr2 0xff addr3 addr4 0xff
static int i2c_detect_all_show(struct seq_file *m, void *v)
{
	int i=0;
	int j=0;
	for(i=0;i<i2c_bus_count;i++)
	{
		seq_printf(m,"i2c_%d address:\n",i2c_bus_list[i]);
		j++;
		while(i2c_addr[j]!=0xff)
		{	
			seq_printf(m,"0x%x ",i2c_addr[j]);
			j++;
		}
		seq_printf(m,"\n");
	}	
	return 0;
}

ssize_t i2c_detect_all_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
	int i;
	int ret;
	int addr;
	int addr_count=0;
	struct i2c_adapter *adapter;
	memset(i2c_addr,0xff,sizeof(i2c_addr));
	for(i=0;i<i2c_bus_count;i++)
	{
    		adapter = i2c_get_adapter(i2c_bus_list[i]); 
    		if (!adapter) {
        		printk("get i2c-%d adapter err\n",i2c_bus);  
        		return -ENODEV;
    		} else {
        		printk("get i2c-%d adapter ok\n",i2c_bus);
    		}
		addr_count++;
		for(addr=0x1;addr<0x80;addr++){
			msg.addr=addr;
			ret=i2c_transfer(adapter, &msg, 1);
			if(ret>0)
			{
				printk("found i2c-%d address  0x%0x\n",i2c_bus_list[i],addr);
				i2c_addr[addr_count++]=addr;
			}
		};
		i2c_put_adapter(adapter); 
	}
	return count;
}

static int i2c_detect_open(struct inode *inode, struct file *file)
{	
	return single_open(file, i2c_detect_show, NULL);
}

static int i2c_detect_all_open(struct inode *inode, struct file *file)
{	
	return single_open(file, i2c_detect_all_show, NULL);
}

static const struct file_operations i2c_detect_fops = 
{
	.owner   = THIS_MODULE,
	.open    = i2c_detect_open,
	.read    = seq_read,
	.write   = i2c_detect_write,
};

static const struct file_operations i2c_detect_all_fops = 
{
	.owner   = THIS_MODULE,
	.open    = i2c_detect_all_open,
	.read    = seq_read,
	.write   = i2c_detect_all_write,
};

void i2c_bus_detect(void)
{
	int i;
	struct i2c_adapter *adapter;
	memset(i2c_bus_list,0,sizeof(i2c_bus_list));
	for(i=0;i<20;i++)
	{
		adapter=i2c_get_adapter(i);
		if(adapter)
		{
			i2c_bus_list[i2c_bus_count++]=i;
			i2c_put_adapter(adapter);
		}
	}
	printk("i2c bus %d\n",i2c_bus_count);
	for(i=0;i<i2c_bus_count;i++)
		printk("found i2c-%d\n",i2c_bus_list[i]);
					
}
static int __init i2c_detect_init(void)
{
	i2c_bus_detect();
	memset(i2c_addr,0xff,sizeof(i2c_addr));
	proc_create("i2cdetect", S_IRWXUGO, NULL, &i2c_detect_fops);
	proc_create("i2cdetectall", S_IRWXUGO, NULL, &i2c_detect_all_fops);
	return 0;
}

static void __exit i2c_detect_exit(void)
{
	remove_proc_entry("i2cdetect", NULL);	
}

module_init(i2c_detect_init);  
module_exit(i2c_detect_exit);  
MODULE_AUTHOR("www");
MODULE_LICENSE("GPL");

猜你喜欢

转载自blog.csdn.net/mike8825/article/details/74231728