}
}
break;
+ case VKI_I2C_SMBUS:
+ if ( ARG3 ) {
+ struct vki_i2c_smbus_ioctl_data *vkis
+ = (struct vki_i2c_smbus_ioctl_data *) ARG3;
+ PRE_MEM_READ("ioctl(VKI_I2C_SMBUS).i2c_smbus_ioctl_data.read_write",
+ (Addr)&vkis->read_write, sizeof(vkis->read_write));
+ PRE_MEM_READ("ioctl(VKI_I2C_SMBUS).i2c_smbus_ioctl_data.size",
+ (Addr)&vkis->size, sizeof(vkis->size));
+ PRE_MEM_READ("ioctl(VKI_I2C_SMBUS).i2c_smbus_ioctl_data.command",
+ (Addr)&vkis->command, sizeof(vkis->command));
+ /* i2c_smbus_write_quick hides its value in read_write, so
+ this variable can hava a different meaning */
+ /* to make matters worse i2c_smbus_write_byte stores its
+ value in command */
+ if ( ! (((vkis->size == VKI_I2C_SMBUS_QUICK)
+ && (vkis->command == VKI_I2C_SMBUS_QUICK)) ||
+ ((vkis->size == VKI_I2C_SMBUS_BYTE)
+ && (vkis->read_write == VKI_I2C_SMBUS_WRITE)))) {
+ /* the rest uses the byte array to store the data,
+ some the first byte for size */
+ UInt size;
+ switch(vkis->size) {
+ case VKI_I2C_SMBUS_BYTE_DATA:
+ size = 1;
+ break;
+ case VKI_I2C_SMBUS_WORD_DATA:
+ case VKI_I2C_SMBUS_PROC_CALL:
+ size = 2;
+ break;
+ case VKI_I2C_SMBUS_BLOCK_DATA:
+ case VKI_I2C_SMBUS_I2C_BLOCK_BROKEN:
+ case VKI_I2C_SMBUS_BLOCK_PROC_CALL:
+ case VKI_I2C_SMBUS_I2C_BLOCK_DATA:
+ size = vkis->data->block[0];
+ break;
+ default:
+ size = 0;
+ }
+
+ if ((vkis->read_write == VKI_I2C_SMBUS_READ)
+ || (vkis->size == VKI_I2C_SMBUS_PROC_CALL)
+ || (vkis->size == VKI_I2C_SMBUS_BLOCK_PROC_CALL))
+ PRE_MEM_WRITE("ioctl(VKI_I2C_SMBUS)"
+ ".i2c_smbus_ioctl_data.data",
+ (Addr)&vkis->data->block[0], size);
+ else
+ PRE_MEM_READ("ioctl(VKI_I2C_SMBUS)."
+ "i2c_smbus_ioctl_data.data",
+ (Addr)&vkis->data->block[0], size);
+ }
+ }
+ break;
/* Wireless extensions ioctls */
case VKI_SIOCSIWCOMMIT:
}
}
break;
+ case VKI_I2C_SMBUS:
+ if ( ARG3 ) {
+ struct vki_i2c_smbus_ioctl_data *vkis
+ = (struct vki_i2c_smbus_ioctl_data *) ARG3;
+ /* i2c_smbus_write_quick hides its value in read_write, so
+ this variable can hava a different meaning */
+ /* to make matters worse i2c_smbus_write_byte stores its
+ value in command */
+ if ((vkis->read_write == VKI_I2C_SMBUS_READ)
+ || (vkis->size == VKI_I2C_SMBUS_PROC_CALL)
+ || (vkis->size == VKI_I2C_SMBUS_BLOCK_PROC_CALL)) {
+ if ( ! ((vkis->size == VKI_I2C_SMBUS_QUICK)
+ && (vkis->command == VKI_I2C_SMBUS_QUICK))) {
+ UInt size;
+ switch(vkis->size) {
+ case VKI_I2C_SMBUS_BYTE:
+ case VKI_I2C_SMBUS_BYTE_DATA:
+ size = 1;
+ break;
+ case VKI_I2C_SMBUS_WORD_DATA:
+ case VKI_I2C_SMBUS_PROC_CALL:
+ size = 2;
+ break;
+ case VKI_I2C_SMBUS_BLOCK_DATA:
+ case VKI_I2C_SMBUS_I2C_BLOCK_BROKEN:
+ case VKI_I2C_SMBUS_BLOCK_PROC_CALL:
+ case VKI_I2C_SMBUS_I2C_BLOCK_DATA:
+ size = vkis->data->block[0];
+ break;
+ default:
+ size = 0;
+ }
+ POST_MEM_WRITE((Addr)&vkis->data->block[0], size);
+ }
+ }
+ }
+ break;
/* Wireless extensions ioctls */
case VKI_SIOCSIWCOMMIT:
// From linux-2.6.20.1/include/linux/i2c.h
//----------------------------------------------------------------------
-#define VKI_I2C_SLAVE 0x0703 /* Change slave address */
- /* Attn.: Slave address is 7 or 10 bits */
-#define VKI_I2C_SLAVE_FORCE 0x0706 /* Change slave address */
- /* Attn.: Slave address is 7 or 10 bits */
- /* This changes the address, even if it */
- /* is already taken! */
-#define VKI_I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
-#define VKI_I2C_FUNCS 0x0705 /* Get the adapter functionality */
-#define VKI_I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */
-#define VKI_I2C_PEC 0x0708 /* != 0 for SMBus PEC */
+#define VKI_I2C_SMBUS_QUICK 0
+#define VKI_I2C_SMBUS_BYTE 1
+#define VKI_I2C_SMBUS_BYTE_DATA 2
+#define VKI_I2C_SMBUS_WORD_DATA 3
+#define VKI_I2C_SMBUS_PROC_CALL 4
+#define VKI_I2C_SMBUS_BLOCK_DATA 5
+#define VKI_I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define VKI_I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define VKI_I2C_SMBUS_I2C_BLOCK_DATA 8
+
+/* smbus_access read or write markers */
+#define VKI_I2C_SMBUS_READ 1
+#define VKI_I2C_SMBUS_WRITE 0
+
+#define VKI_I2C_SLAVE 0x0703 /* Change slave address */
+ /* Attn.: Slave address is 7 or 10 bits */
+#define VKI_I2C_SLAVE_FORCE 0x0706 /* Change slave address */
+ /* Attn.: Slave address is 7 or 10 bits */
+ /* This changes the address, even if it */
+ /* is already taken! */
+#define VKI_I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
+#define VKI_I2C_FUNCS 0x0705 /* Get the adapter functionality */
+#define VKI_I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */
+#define VKI_I2C_PEC 0x0708 /* != 0 for SMBus PEC */
+#define VKI_I2C_SMBUS 0x0720 /* SMBus transfer */
+
+#define VKI_I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+union vki_i2c_smbus_data {
+ __vki_u8 byte;
+ __vki_u16 word;
+ __vki_u8 block[VKI_I2C_SMBUS_BLOCK_MAX + 2];
+ /* block[0] is used for length */
+ /* and one more for PEC */
+};
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct vki_i2c_smbus_ioctl_data {
+ __vki_u8 read_write;
+ __vki_u8 command;
+ __vki_u32 size;
+ union vki_i2c_smbus_data __user *data;
+};
struct vki_i2c_msg {
__vki_u16 addr; /* slave address */