in hid-ft260.c [596:702]
static int ft260_smbus_xfer(struct i2c_adapter *adapter, u16 addr, u16 flags,
char read_write, u8 cmd, int size,
union i2c_smbus_data *data)
{
int ret;
struct ft260_device *dev = i2c_get_adapdata(adapter);
struct hid_device *hdev = dev->hdev;
ft260_dbg("smbus size %d\n", size);
mutex_lock(&dev->lock);
ret = hid_hw_power(hdev, PM_HINT_FULLON);
if (ret < 0) {
hid_err(hdev, "power management error: %d\n", ret);
mutex_unlock(&dev->lock);
return ret;
}
switch (size) {
case I2C_SMBUS_QUICK:
if (read_write == I2C_SMBUS_READ)
ret = ft260_i2c_read(dev, addr, &data->byte, 0,
FT260_FLAG_START_STOP);
else
ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
FT260_FLAG_START_STOP);
break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_READ)
ret = ft260_i2c_read(dev, addr, &data->byte, 1,
FT260_FLAG_START_STOP);
else
ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
FT260_FLAG_START_STOP);
break;
case I2C_SMBUS_BYTE_DATA:
if (read_write == I2C_SMBUS_READ) {
ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
FT260_FLAG_START);
if (ret)
goto smbus_exit;
ret = ft260_i2c_read(dev, addr, &data->byte, 1,
FT260_FLAG_START_STOP_REPEATED);
} else {
ret = ft260_smbus_write(dev, addr, cmd, &data->byte, 1,
FT260_FLAG_START_STOP);
}
break;
case I2C_SMBUS_WORD_DATA:
if (read_write == I2C_SMBUS_READ) {
ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
FT260_FLAG_START);
if (ret)
goto smbus_exit;
ret = ft260_i2c_read(dev, addr, (u8 *)&data->word, 2,
FT260_FLAG_START_STOP_REPEATED);
} else {
ret = ft260_smbus_write(dev, addr, cmd,
(u8 *)&data->word, 2,
FT260_FLAG_START_STOP);
}
break;
case I2C_SMBUS_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
FT260_FLAG_START);
if (ret)
goto smbus_exit;
ret = ft260_i2c_read(dev, addr, data->block,
data->block[0] + 1,
FT260_FLAG_START_STOP_REPEATED);
} else {
ret = ft260_smbus_write(dev, addr, cmd, data->block,
data->block[0] + 1,
FT260_FLAG_START_STOP);
}
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
FT260_FLAG_START);
if (ret)
goto smbus_exit;
ret = ft260_i2c_read(dev, addr, data->block + 1,
data->block[0],
FT260_FLAG_START_STOP_REPEATED);
} else {
ret = ft260_smbus_write(dev, addr, cmd, data->block + 1,
data->block[0],
FT260_FLAG_START_STOP);
}
break;
default:
hid_err(hdev, "unsupported smbus transaction size %d\n", size);
ret = -EOPNOTSUPP;
}
smbus_exit:
hid_hw_power(hdev, PM_HINT_NORMAL);
mutex_unlock(&dev->lock);
return ret;
}