1. I2C 协议

 

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;
}

 

现在分析下i2cdev_ioctl_smbus()函数是怎么进行通信:

你可能感兴趣的:(c,struct,user,command,null,byte)