IIC协议

r = ioctl(fd, I2C_FUNCS, &funcs)是查看其功能,它最终调用algo通信方式中的functionality()函数

r = ioctl(fd, I2C_SLAVE, addr)这个函数设置要通信的从设备地址,如下:

case I2C_SLAVE:
 case I2C_SLAVE_FORCE:
  
  if ((arg > 0x3ff) ||
      (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
   return -EINVAL;
  if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
   return -EBUSY;
  
  client->addr = arg;
  return 0;

 

 

ioctl(file,I2C_SMBUS,&args);实现读写,通过args

struct i2c_smbus_ioctl_data args;


struct i2c_smbus_ioctl_data {
 __u8 read_write;
 __u8 command;
 __u32 size;
 union i2c_smbus_data __user *data;
};
union i2c_smbus_data {
 __u8 byte;
 __u16 word;
 __u8 block[I2C_SMBUS_BLOCK_MAX + 2];
         
};

每次通信都是通过给args参数不同进行不同的操作

调用关系

case I2C_SMBUS:
  return i2cdev_ioctl_smbus(client, arg);

static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
  unsigned long arg)
{
 struct i2c_smbus_ioctl_data data_arg;
 union i2c_smbus_data temp;
 int datasize, res;

 if (copy_from_user(&data_arg,
      (struct i2c_smbus_ioctl_data __user *) arg,
      sizeof(struct i2c_smbus_ioctl_data)))
  return -EFAULT;
 if ((data_arg.size != I2C_SMBUS_BYTE) &&
     (data_arg.size != I2C_SMBUS_QUICK) &&
     (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
     (data_arg.size != I2C_SMBUS_WORD_DATA) &&
     (data_arg.size != I2C_SMBUS_PROC_CALL) &&
     (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
     (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
     (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
     (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
  dev_dbg(&client->adapter->dev,
   "size out of range (%x) in ioctl I2C_SMBUS.\n",
   data_arg.size);
  return -EINVAL;
 }
 
 if ((data_arg.read_write != I2C_SMBUS_READ) &&
     (data_arg.read_write != I2C_SMBUS_WRITE)) {
  dev_dbg(&client->adapter->dev,
   "read_write out of range (%x) in ioctl I2C_SMBUS.\n",
   data_arg.read_write);
  return -EINVAL;
 }

 

 if ((data_arg.size == I2C_SMBUS_QUICK) ||
     ((data_arg.size == I2C_SMBUS_BYTE) &&
     (data_arg.read_write == I2C_SMBUS_WRITE)))
  
  return i2c_smbus_xfer(client->adapter, client->addr,
          client->flags, data_arg.read_write,
          data_arg.command, data_arg.size, NULL);

 if (data_arg.data == NULL) {
  dev_dbg(&client->adapter->dev,
   "data is NULL pointer in ioctl I2C_SMBUS.\n");
  return -EINVAL;
 }

 if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
     (data_arg.size == I2C_SMBUS_BYTE))
  datasize = sizeof(data_arg.data->byte);
 else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
   (data_arg.size == I2C_SMBUS_PROC_CALL))
  datasize = sizeof(data_arg.data->word);
 else
  datasize = sizeof(data_arg.data->block);

 if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
     (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
     (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
     (data_arg.read_write == I2C_SMBUS_WRITE)) {
  if (copy_from_user(&temp, data_arg.data, datasize))
   return -EFAULT;
 }
 if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
  
  data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
  if (data_arg.read_write == I2C_SMBUS_READ)
   temp.block[0] = I2C_SMBUS_BLOCK_MAX;
 }
 res = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
       data_arg.read_write, data_arg.command, data_arg.size, &temp);
 if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
       (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
       (data_arg.read_write == I2C_SMBUS_READ))) {
  if (copy_to_user(data_arg.data, &temp, datasize))
   return -EFAULT;
 }
 return res;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值