- 论坛徽章:
- 0
|
这两天挺累的,频繁的应酬,都有点受不了了,下了班也不敢加班,赶紧跑回家,结果发现,跑回家也没有作用。。。
放出一个atmel24c512的设备驱动框架。可以使用,但是使用这要对read和write进行一些修改,需要能指定地址的访问。。。
感谢网上的某位兄弟放出的部分源码,linux开源的力量无穷!!!
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static unsigned short normal_i2c[] = { 0x50,I2C_CLIENT_END };
#define EEPROM_SIZE 65536
#define DEVICE_NAME "at24c512"
#define AT24C512_EEPROM_MAJOR 251
#define SEEK_END 2
#define SEEK_CUR 1
#define SEEK_SET 0
static DECLARE_MUTEX(at24c512_eeprom_read_sem);
static DECLARE_MUTEX(at24c512_eeprom_write_sem);
struct i2c_client *new_client;
/* possible types of eeprom devices */
enum eeprom_nature {
UNKNOWN,
VAIO,
};
/* Module parameters */
/*这一句很重要得,不然的addr_data会找不到,因为i2c.h文件只是定义了几种宏,这里才真正定义这个变量,今天才真正理解了这个addr_data如何产生的,
每个i2c设备都有一个addr_data结构,这样就好理解i2c的框架(i2c_probe)驱动为何这样写,*/
I2C_CLIENT_INSMOD;
static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
memset(buf,0x88,10);
return 10;
}
static ssize_t eeprom_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
return 10;
}
static struct i2c_driver eeprom_driver;
static struct bin_attribute eeprom_attr = {
.attr = {
.name = "at24c512",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = EEPROM_SIZE,
.read = eeprom_read,
.write=eeprom_write,
};
struct eeprom_data {
struct i2c_client client;
struct mutex update_lock;
unsigned char valid; /* bitfield, bit!=0 if slice is valid */
unsigned long last_updated[8]; /* In jiffies, 8 slices */
unsigned char data[EEPROM_SIZE]; /* Register values */
enum eeprom_nature nature;
};
/* This function is called by i2c_probe */
static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct eeprom_data *data;
int err = 0;
printk("eeprom_detect!\n");
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit;
}
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
new_client = &data->client;
memset(data->data, 0xff, EEPROM_SIZE);
i2c_set_clientdata(new_client, data);
new_client->addr = address;
printk("address==%x\n",new_client->addr);
new_client->adapter = adapter;
new_client->driver = &eeprom_driver;
new_client->flags = 0;
/* Fill in the remaining client fields */
strlcpy(new_client->name, eeprom_driver.driver.name, I2C_NAME_SIZE);
data->valid = 0;
mutex_init(&data->update_lock);
data->nature = UNKNOWN;
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_kfree;
/* Detect the Vaio nature of EEPROMs.
We use the "PCG-" prefix as the signature. */
/*
if (address == 0x57) {
if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
&& i2c_smbus_read_byte(new_client) == 'C'
&& i2c_smbus_read_byte(new_client) == 'G'
&& i2c_smbus_read_byte(new_client) == '-') {
dev_info(&new_client->dev, "Vaio EEPROM detected, "
"enabling password protection\n");
data->nature = VAIO;
}
}
*/
/* create the sysfs eeprom file */
err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
if (err)
goto exit_detach;
printk("eeprom_detect ok!\n");
return 0;
exit_detach:
i2c_detach_client(new_client);
exit_kfree:
kfree(data);
exit:
return err;
}
static int eeprom_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter, &addr_data, eeprom_detect);
}
static int eeprom_detach_client(struct i2c_client *client)
{
int err;
sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
err = i2c_detach_client(client);
if (err)
return err;
kfree(i2c_get_clientdata(client));
return 0;
}
/* This is the driver that will be inserted */
static struct i2c_driver eeprom_driver = {
.driver = {
.name = "at24c512",
},
.id = I2C_DRIVERID_EEPROM,
.attach_adapter = eeprom_attach_adapter,
.detach_client = eeprom_detach_client,
};
static int at24c512_eeprom_open(struct inode * inode, struct file * filp)
{
filp->private_data = new_client;
printk("at24c512 open success!\n");
return 0;
}
static int at24c512_eeprom_release(struct inode * inode, struct file * filp)
{
printk("at24c512 realse success!\n");
return 0;
}
static loff_t at24c512_eeprom_llseek (struct file *filp, loff_t off, int whence)
{
//struct i2c_dev *dev = filp->private_data;
loff_t newpos=-1;
filp->private_data=new_client;
switch(whence)
{
case SEEK_SET:
newpos = off;
break;
case SEEK_CUR:
newpos = filp->f_pos + off;
break;
case SEEK_END:
//newpos = (filp->private_data)->size + off;
break;
default: /* can't happen */
return -EINVAL;
}
if (newpos f_pos = newpos;
return newpos;
}
static ssize_t at24c512_eeprom_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
ssize_t ret;
int result;
struct i2c_client *client = new_client;
struct i2c_msg msg[1];
char *tmp;
printk("this is in reading!\n");
if(down_interruptible(&at24c512_eeprom_read_sem))
goto out;
if (!(tmp = kzalloc(count, GFP_KERNEL)))
return - ENOMEM;
printk("the number is %d\n",count);
result=i2c_master_recv(client, tmp ,count);
printk("read result===%x\n",result);
ret = copy_to_user(buffer, tmp, count);
if(ret != 0)
{
kfree(tmp);
return -EFAULT;
}
out:
{
up(&at24c512_eeprom_read_sem);
return 0;
}
kfree(tmp);
return ret;
}
static ssize_t at24c512_eeprom_write(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
ssize_t ret;
int result,i;
struct i2c_client *client=new_client;
struct i2c_msg msg[1];
char *tmp;
if(down_interruptible(&at24c512_eeprom_write_sem))
goto out;
printk("this is in writting!\n");
if (!(tmp = kzalloc(count, GFP_KERNEL)))
return - ENOMEM;
ret = copy_from_user(tmp, buffer, count);
if(ret != 0)
{
kfree(tmp);
return -EFAULT;
}
result=i2c_master_send(client,tmp ,count);
printk("write result===%x\n",result);
out:
{
up(&at24c512_eeprom_write_sem);
return 0;
}
kfree(tmp);
return result;
}
/*to user*/
static struct file_operations at24c512_eeprom_fops = {
.owner = THIS_MODULE,
.open=at24c512_eeprom_open,
//.poll = tsmb_eeprom_select,
.read = at24c512_eeprom_read,
.write = at24c512_eeprom_write,
.llseek = at24c512_eeprom_llseek,
.release=at24c512_eeprom_release,
};
static int __init eeprom_init(void)
{
int ret,result;
result = register_chrdev(AT24C512_EEPROM_MAJOR, DEVICE_NAME, &at24c512_eeprom_fops);
if (result eeprom_detect ok!
at24c512: init OK
at24c512 open success!
this is in reading!
the number is 8192
i2c_adapter i2c-0: master_xfer[0] R, addr=0x50, len=8192
i2c_adapter i2c-0: at91_xfer: processing 1 messages:
i2c_adapter i2c-0: #0: reading 8192 bytes from 0x50
i2c_adapter i2c-0: transfer complete
read result===2000
at24c512 realse success!
说明通信成功。。。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/38038/showart_715294.html |
|