diff options
Diffstat (limited to 'hw/i2c')
-rw-r--r-- | hw/i2c/core.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/hw/i2c/core.c b/hw/i2c/core.c index d03b0eea5c..3a7bae311d 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -77,6 +77,30 @@ int i2c_bus_busy(I2CBus *bus) return !QLIST_EMPTY(&bus->current_devs); } +bool i2c_scan_bus(I2CBus *bus, uint8_t address, bool broadcast, + I2CNodeList *current_devs) +{ + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { + DeviceState *qdev = kid->child; + I2CSlave *candidate = I2C_SLAVE(qdev); + I2CSlaveClass *sc = I2C_SLAVE_GET_CLASS(candidate); + + if (sc->match_and_add(candidate, address, broadcast, current_devs)) { + if (!broadcast) { + return true; + } + } + } + + /* + * If broadcast was true, and the list was full or empty, return true. If + * broadcast was false, return false. + */ + return broadcast; +} + /* TODO: Make this handle multiple masters. */ /* * Start or continue an i2c transaction. When this is called for the @@ -93,7 +117,6 @@ int i2c_bus_busy(I2CBus *bus) */ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) { - BusChild *kid; I2CSlaveClass *sc; I2CNode *node; bool bus_scanned = false; @@ -115,17 +138,8 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) * terminating the previous transaction. */ if (QLIST_EMPTY(&bus->current_devs)) { - QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) { - DeviceState *qdev = kid->child; - I2CSlave *candidate = I2C_SLAVE(qdev); - sc = I2C_SLAVE_GET_CLASS(candidate); - if (sc->match_and_add(candidate, address, bus->broadcast, - &bus->current_devs)) { - if (!bus->broadcast) { - break; - } - } - } + /* Disregard whether devices were found. */ + (void)i2c_scan_bus(bus, address, bus->broadcast, &bus->current_devs); bus_scanned = true; } |