diff --git a/libraries/AP_HAL/I2CDriver.h b/libraries/AP_HAL/I2CDriver.h index 59a9117f23..00c30bc3ed 100644 --- a/libraries/AP_HAL/I2CDriver.h +++ b/libraries/AP_HAL/I2CDriver.h @@ -26,11 +26,18 @@ public: /* readRegister: read from a device register - writes the register, * then reads back an 8-bit value. */ virtual uint8_t readRegister(uint8_t addr, uint8_t reg, uint8_t* data) = 0; - /* readRegister: read contigious device registers - writes the first + + /* readRegisters: read contigious device registers - writes the first * register, then reads back multiple bytes */ virtual uint8_t readRegisters(uint8_t addr, uint8_t reg, uint8_t len, uint8_t* data) = 0; + /* readRegistersMultiple: read contigious device registers. + Equivalent to count calls to readRegisters() */ + virtual uint8_t readRegistersMultiple(uint8_t addr, uint8_t reg, + uint8_t len, uint8_t count, + uint8_t* data) = 0; + virtual uint8_t lockup_count() = 0; void ignore_errors(bool b) { _ignore_errors = b; } virtual AP_HAL::Semaphore* get_semaphore() = 0; diff --git a/libraries/AP_HAL_Linux/I2CDriver.cpp b/libraries/AP_HAL_Linux/I2CDriver.cpp index f553e7af8b..f4ba4bd196 100644 --- a/libraries/AP_HAL_Linux/I2CDriver.cpp +++ b/libraries/AP_HAL_Linux/I2CDriver.cpp @@ -137,15 +137,59 @@ uint8_t LinuxI2CDriver::read(uint8_t addr, uint8_t len, uint8_t* data) uint8_t LinuxI2CDriver::readRegisters(uint8_t addr, uint8_t reg, uint8_t len, uint8_t* data) { - if (!set_address(addr)) { + struct i2c_msg msgs[] = { + { + addr : addr, + flags : 0, + len : 1, + buf : ® + }, + { + addr : addr, + flags : I2C_M_RD, + len : len, + buf : data, + } + }; + struct i2c_rdwr_ioctl_data i2c_data = { + msgs : msgs, + nmsgs : 2 + }; + + if (ioctl(_fd, I2C_RDWR, &i2c_data) == -1) { return 1; } - // send the address to read from - if (::write(_fd, ®, 1) != 1) { - return 1; - } - if (::read(_fd, data, len) != len) { - return 1; + + return 0; +} + + +uint8_t LinuxI2CDriver::readRegistersMultiple(uint8_t addr, uint8_t reg, + uint8_t len, + uint8_t count, uint8_t* data) +{ + while (count > 0) { + uint8_t n = count>8?8:count; + struct i2c_msg msgs[2*n]; + struct i2c_rdwr_ioctl_data i2c_data = { + msgs : msgs, + nmsgs : 2*n + }; + for (uint8_t i=0; i