i2c驱动程序的核心是创建i2c_driver结构体
/*This is the driver that will be inserted*/
static struct i2c_driver at24cxx_driver ={
.driver={
.name= "at24cxx",
},
.id=I2C_DRIVERID_AT24Cxx,
.attach_adapter=at24cxx_attach_adapter,
.detach_client=at24cxx_detach_client,
};
再at24cxx_attach_adapter里面
static int at24cxx_attach_adapter(struct i2c_adapter *adapter)
{return i2c_probe(adapter, &addr_data, at24cxx_detect);
}
当probe到设备后, at24cxx_detect会被调用
这里有两个需要完成的
(1) 配置addr_data
(2)at24cxx_detect
对于addr_data
/** Generic i2c probe
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so ‘>>1‘*/
static unsigned short normal_i2c[] ={0x50, /*7位地址*/I2C_CLIENT_END,
};static unsigned short ignore =I2C_CLIENT_END;static struct i2c_client_address_data addr_data ={
.normal_i2c=normal_i2c,
.probe= &ignore,
.ignore= &ignore,
};
而在 at24cxx_detect中主要有
(1) 设置一个i2c_client 结构体变量
(2) 设置它
(3) 注册
首先创建全局i2c_client变量
static struct i2c_client *at24cxx_client;
static int at24cxx_detect(struct i2c_adapter *adapter, int address, intkind)
{
printk(KERN_INFO"at24cxx_detect \n");int err = 0;/*分配*/at24cxx_client= kzalloc(sizeof(structi2c_client), GFP_KERNEL);/*设置*/at24cxx_client->addr =address;
at24cxx_client->adapter =adapter;
at24cxx_client->driver = &at24cxx_driver;
at24cxx_client->flags = 0;/*Fill in the remaining client fields*/strlcpy(at24cxx_client->name, "at24cxx", I2C_NAME_SIZE);/*Tell the I2C layer a new client has arrived*/
if ((err =i2c_attach_client(at24cxx_client)))gotoexit_kfree;
exit_kfree:
kfree(at24cxx_client);returnerr;
}
i2c设置好了, 数据传输使用i2c_transfer
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
因此, 数据传送是需要构造设置msg
与用户程序交互的读:
static int at24cxx_read (struct file *file, char __user *usrbuf, size_t len, loff_t *offset)
{/** buf[0] addr
* buf[1] data*/
intret;
unsignedcharaddress;
unsignedchardata;struct i2c_msg msg[2];if(len != 2)return -EFAULT;if(copy_from_user(&address, usrbuf, 1))
res= -EFAULT;/*i2c 传输*/
/*先发送地址*/msg[0].addr = at24cxx_client->addr; //dest
msg[0].buf = &address; //src
msg[0].flags = 0; //write
msg[0].len = 1; //len
/*再读*/msg[1].addr = at24cxx_client->addr; //dest
msg[2].buf = &data; //src
msg[1].flags = I2C_M_RD; //read
msg[1].len = 1; //len
ret= i2c_transfer(at24cxx_client->adapter, msg, 2);if(ret == 2)
{if(copy_to_user(&usrbuf, &data, 1))
res= -EFAULT;return 1;
}else
return -EIO;return 0;
}
写:
static int at24cxx_write (struct file *file, const char __user *usrbuf, size_t len, loff_t *offset)
{/** buf[0] addr
* buf[1] data*/
intret;
unsignedchar buf[2];struct i2c_msg msg[1];if(len != 2)return -EFAULT;if(copy_from_user(buf, usrbuf, 2))
res= -EFAULT;/*i2c 传输*/msg[0].addr = at24cxx_client->addr; //dest
msg[0].buf = buf; //src
msg[0].flags = 0; //write
msg[0].len = 2; //len
ret = i2c_transfer(at24cxx_client->adapter, msg, 1);if(ret == 1)return 2;else
return -EIO;
}
原文:https://www.cnblogs.com/hulig7/p/9901760.html