static int i2c_addressable_tx(i2c_slave *s, uint8_t data) { I2CAddressableDeviceInfo *t = DO_UPCAST(I2CAddressableDeviceInfo, i2c, s->info); I2CAddressableState *dev = FROM_I2C_SLAVE(I2CAddressableState, s); if (dev->num < t->size) { /* First fully get control register address byte after byte */ if (!t->rev) { /* Less significant bytes come first */ dev->addr |= data << (dev->num * 8); } else { /* More significant bytes come first */ dev->addr |= data << ((t->size - dev->num - 1) * 8); } } else { /* Then get corresponding data byte after byte */ if (t->write) { t->write(dev, dev->addr, dev->num - t->size, data); } } dev->num++; return 1; }
static int i2c_addressable_device_init(i2c_slave *s) { I2CAddressableDeviceInfo *t = DO_UPCAST(I2CAddressableDeviceInfo, i2c, s->info); I2CAddressableState *dev = FROM_I2C_SLAVE(I2CAddressableState, s); return t->init(dev); }
static int i2c_addressable_rx(i2c_slave *s) { I2CAddressableDeviceInfo *t = DO_UPCAST(I2CAddressableDeviceInfo, i2c, s->info); I2CAddressableState *dev = FROM_I2C_SLAVE(I2CAddressableState, s); /* Get next byte of the value and transfer it */ if (t->read) { return t->read(dev, dev->addr, dev->num++); } return 0; }
static int aer915_send(I2CSlave *i2c, uint8_t data) { AER915State *s = FROM_I2C_SLAVE(AER915State, i2c); s->buf[s->len] = data; if (s->len++ > 2) { DPRINTF("%s: message too long (%i bytes)\n", __func__, s->len); return 1; } if (s->len == 2) { DPRINTF("%s: reg %d value 0x%02x\n", __func__, s->buf[0], s->buf[1]); } return 0; }
static void i2c_addressable_event(i2c_slave *s, enum i2c_event event) { I2CAddressableState *dev = FROM_I2C_SLAVE(I2CAddressableState, s); switch (event) { case I2C_START_SEND: dev->addr = 0; /* fallthrough */ case I2C_START_RECV: /* Save address from the previous send */ dev->num = 0; break; case I2C_FINISH: default: break; } }
static void aer915_event(I2CSlave *i2c, enum i2c_event event) { AER915State *s = FROM_I2C_SLAVE(AER915State, i2c); switch (event) { case I2C_START_SEND: s->len = 0; break; case I2C_START_RECV: if (s->len != 1) { DPRINTF("%s: short message!?\n", __func__); } break; case I2C_FINISH: break; default: break; } }
static int aer915_recv(I2CSlave *slave) { int retval = 0x00; AER915State *s = FROM_I2C_SLAVE(AER915State, slave); switch (s->buf[0]) { /* Return hardcoded battery voltage, * 0xf0 means ~4.1V */ case 0x02: retval = 0xf0; break; /* Return 0x00 for other regs, * we don't know what they are for, * anyway they return 0x00 on real hardware. */ default: break; } return retval; }