平台 | 内核版本 | 安卓版本 |
---|---|---|
RK3399 | Linux4.4 | Android7.1 |
Pin Configuration
Encryption Flow
i2c驱动
I2C
的设备驱动是通过i2c_add_driver(&my_driver)
向i2c-core
注册的
#define DRV_NAME "adasplus"
static const struct i2c_device_id hp_SE_id[] = {
{ DRV_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, hp_SE_id);
static struct i2c_driver hq_SE_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(SE_ids),
},
.id_table = hp_SE_id,
.probe = hq_SE_probe,
.remove = hq_SE_remove,
.shutdown = hq_SE_shutdown,
};
static int __init hq_SE_init(void)
{
int nRet = 0;
nRet = i2c_add_driver(&hq_SE_driver);
if(nRet < 0){
printk("i2c_add_driver err, ret = %d\n", nRet);
}
printk("init ret:%d\n", nRet);
return nRet;
}
匹配设备和驱动的时候,使用的是of_match_table
里的数据和DTB
里的compatible
数据
static struct of_device_id SE_ids[] = {
{.compatible = DRV_NAME},
{}
};
MODULE_DEVICE_TABLE(of, SE_ids);
probe
函数在设备驱动注册最后收尾工作,当设备的device
和其对应的driver
在总线上完成配对之后,系统就调用总线设备的probe
函数完成驱动注册最后工作。
static int hq_SE_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
printk("probe enter\n");
int nRet = 0;
mClient = client;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
nRet = -ENODEV;
printk("i2c_check_functionality fail\n");
kfree(client);
return nRet;
}
nRet = misc_register(&SE_miscdev);
if (nRet < 0)
{
return nRet;
}
printk("probe ok\n");
return 0;
}
miscdevice
static struct file_operations SE_fops={
.owner = THIS_MODULE,
.open = SE_open,
.read = SE_read,
.write = SE_write,
.release = SE_release,
.unlocked_ioctl = SE_unlocked_ioctl,
.compat_ioctl = SE_unlocked_ioctl,
};
static struct miscdevice SE_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "i2c-se0",
.fops = &SE_fops,
};
向上数据交互
static long SE_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct SE_DATA data[1];
if(cmd >= SE_IOC_SIZE)
return -EINVAL;
switch(cmd)
{
case SE_IOC_GET_DATA:
if (copy_from_user((void*)data,(void __user*)arg, sizeof(struct SE_DATA)))
{
printk("copy_from_user error\n");
return -EFAULT;
}
printk("cmd:%s, reg:0x%x, size:%d\n", "SE_IOC_GET_DATA", data->reg, data->size);
if(hqSE_read_data(mClient, data->reg, data->buff, data->size) != 0)
{
printk("read data failed, reg:0x%x, size:%d\n", data->reg, data->size);
return -EFAULT;
}
if (copy_to_user((void __user*)arg, (void*)data, sizeof(struct SE_DATA)))
{
printk("copy_to_user error\n");
return -EFAULT;
}
break;
case SE_IOC_SET_DATA:
if (copy_from_user((void*)data,(void __user*)arg, sizeof(struct SE_DATA)))
{
printk("copy_from_user error\n");
return -EFAULT;
}
printk("cmd:%s, reg:0x%x, size:%d\n", "SE_IOC_SET_DATA", data->reg, data->size);
hqSE_write_data(mClient, data->reg, data->buff, data->size);
break;
default:
printk("cmd:0x%x error\n", cmd);
break;
}
return 0;
}
hqSE_write_data
hqSE_read_data
hqSE_write_data
static int hqSE_write_data(struct i2c_client *client, const char reg,const char *data, unsigned char len)
{
u8 buf[BUFFSIZE+1];
int rc;
int ret = 0;
int i;
buf[0] = reg;
printk("write: %x ",buf[0]);
if (len >= BUFFSIZE+1) {
printk("%s (%d) : FAILED: buffer size is limitted(BUFFSIZE+1) %d\n", __func__, __LINE__, len);
dev_err(&client->dev, "hqSE_write_data FAILED: buffer size is limitted(BUFFSIZE+1)\n");
return -1;
}
for( i=0 ; i<len; i++ ) {
buf[i+1] = data[i];
printk("%x ",buf[i+1]);
}
printk(" \n");
rc = i2c_master_send(client, buf, len+1);
if (rc != len+1) {
printk("%s (%d) : FAILED: writing to reg 0x%x\n", __func__, __LINE__, reg);
ret = -1;
}
return ret;
}
hqSE_read_data
static int hqSE_read_data(struct i2c_client *client, const char reg, char *data, unsigned char len)
{
u8 buf[BUFFSIZE];
int rc;
int i = 0;
if(len > BUFFSIZE)
{
printk("len > BUFFSIZE, buffer size is out\n");
return -1;
}
buf[0] = reg;
printk(" read: %x ",buf[0]);
rc = i2c_master_recv_(client, buf, len);
if (rc != len) {
printk("%s (%d) : FAILED: reading data, rc:%d\n", __func__, __LINE__, rc);
return -1;
}
for(i = 0; i < len; i++){
data[i] = buf[i] ;
printk("%x ",data[i]);
}
printk(" \n");
return 0;
}
int i2c_master_recv_(const struct i2c_client *client, char *buf, int count)
{
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg[2];
int ret;
char reg = buf[0] & 0xff;
msg[0].addr = client->addr;
msg[0].flags = I2C_M_TEN;
msg[0].len = 1;
msg[0].buf = ®
msg[1].addr = client->addr;
//msg[1].flags = client->flags & I2C_M_TEN;
msg[1].flags = I2C_M_RD;
msg[1].len = count;
msg[1].buf = buf;
ret = i2c_transfer(adap, &msg, 2);
/*
* If everything went ok (i.e. 1 msg received), return #bytes received,
* else error code.
*/
return (ret == 2) ? count : ret;
}