请教Android在用户空间操作I2C
板砖先生 2017-11-24 04:06:33 小弟最近在RK3128调试一款I2C接口的GPS,u-blox MAX-7Q。
源码是供应商给的,放在hardware/u-blox/gps/目录下。
以下是hardware操作I2C代码:
ssize_t CSerialPort::i2cGetNumAvailBytes(void) const
{
if (m_fd <= 0)
return -1;
struct i2c_rdwr_ioctl_data {
struct i2c_msg __user *msgs;
__u32 nmsgs;
};
struct i2c_rdwr_ioctl_data rdwr;
struct i2c_msg out_in[2], *out, *in;
unsigned char out_data;
unsigned char in_data[2];
ssize_t result = -1;
out = out_in;
in = out_in + 1;
out_data = 0xFD;
out->addr = s_i2cRecvAddr;
out->flags = 0; // indicates a write
out->len = 1;
out->buf = &out_data;
in->addr = s_i2cRecvAddr;
in->flags = I2C_M_RD;
in->len = 2;
in->buf = in_data;
in_data[0] = 0;
in_data[1] = 0;
rdwr.nmsgs = 2;
rdwr.msgs = out_in;
int io = ioctl(m_fd, I2C_RDWR, &rdwr);
if (io < 0)
{
UBXSERLOG("IOCTL for reading nob registers failed. io = %d",io);
}
else
{
result = in_data[0] * 256 + in_data[1];
}
return result;
}
ioctl返回-1,然后去kernel中添加log,发现在i2cdev_ioctl_rdrw时出错了。
以下是添加的log:
static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
unsigned long arg)
{
struct i2c_rdwr_ioctl_data rdwr_arg;
struct i2c_msg *rdwr_pa;
u8 __user **data_ptrs;
int i, res;
if (copy_from_user(&rdwr_arg,
(struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
printk("rdwr_arg.msgs[1].len = %d\n",rdwr_arg.msgs[1].len);
rdwr_pa = memdup_user(rdwr_arg.msgs,
rdwr_arg.nmsgs * sizeof(struct i2c_msg));
if (IS_ERR(rdwr_pa))
return PTR_ERR(rdwr_pa);
data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
kfree(rdwr_pa);
return -ENOMEM;
}
res = 0;
for (i = 0; i < rdwr_arg.nmsgs; i++) {
/* Limit the size of the message to a sane amount */
printk("rdwr_pa[%d].len = %d \n",i, rdwr_pa[i].len);
if (rdwr_pa[i].len > 8192) {
printk("i2cdev_ioctl_rdrw 111 res = %d, rdwr_pa[%d].len = %d\n", res, i, rdwr_pa[i].len);
res = -EINVAL;
break;
}
打印如下:
[ 78.822079] rdwr_arg.msgs[1].len = 42684
[ 78.822187] rdwr_pa[0].len = 1
[ 78.822213] rdwr_pa[1].len = 42684
[ 78.822236] i2cdev_ioctl_rdrw 111 res = 0, rdwr_pa[1].len = 42684
很奇怪length怎么就不对了呢?
可以看到copy_from_user之后就已经不对了,百思不得其解,求大神指点!