diff options
author | Bertrand SIMONNET <bsimonnet@google.com> | 2016-03-24 14:15:02 -0700 |
---|---|---|
committer | Treehugger Robot <treehugger-gerrit@google.com> | 2016-04-25 23:18:52 +0000 |
commit | 8ad824905e84f8b001211eb88b8f18fbf3b5dd8c (patch) | |
tree | a91942dd35da42e3ce3a5353be7cd0b1b7bb9f0f | |
parent | 954874f0897fa810e2bdfbd44d1694c4da2fd461 (diff) | |
download | peripheralmanager-8ad824905e84f8b001211eb88b8f18fbf3b5dd8c.tar.gz |
Implement the backend for more I2C functions.
Implements the driver and AIDL interface for:
* Read
* ReadRegBuffer
* Write
* WriteRegByte
* WriteRegWord
* WriteRegBuffer
Bug: 27831222
Change-Id: I792661a47330ea3c7d864b6373440e6369a58d77
-rw-r--r-- | daemon/i2c_driver.h | 23 | ||||
-rw-r--r-- | daemon/i2c_driver_i2cdev.cc | 126 | ||||
-rw-r--r-- | daemon/i2c_driver_i2cdev.h | 21 | ||||
-rw-r--r-- | daemon/i2c_manager.h | 35 | ||||
-rw-r--r-- | daemon/peripheral_manager_client.cc | 114 | ||||
-rw-r--r-- | daemon/peripheral_manager_client.h | 40 | ||||
-rw-r--r-- | ipc/android/os/IPeripheralManagerClient.aidl | 21 |
7 files changed, 352 insertions, 28 deletions
diff --git a/daemon/i2c_driver.h b/daemon/i2c_driver.h index dbb5c84..4b8c079 100644 --- a/daemon/i2c_driver.h +++ b/daemon/i2c_driver.h @@ -36,9 +36,24 @@ class I2cDriverInterface { // TODO(leecam): Init should have generic params. virtual bool Init(uint32_t bus_id, uint32_t address) = 0; - virtual bool ReadRegByte(uint8_t reg, uint8_t* val) = 0; - virtual bool ReadRegWord(uint8_t reg, uint16_t* val) = 0; - + // Returns 0 on success, errno on errors. + virtual int32_t Read(void* data, uint32_t size, uint32_t* bytes_read) = 0; + virtual int32_t ReadRegByte(uint8_t reg, uint8_t* val) = 0; + virtual int32_t ReadRegWord(uint8_t reg, uint16_t* val) = 0; + virtual int32_t ReadRegBuffer(uint8_t reg, + uint8_t* data, + uint32_t size, + uint32_t* bytes_read) = 0; + + virtual int32_t Write(const void* data, + uint32_t size, + uint32_t* bytes_written) = 0; + virtual int32_t WriteRegByte(uint8_t reg, uint8_t val) = 0; + virtual int32_t WriteRegWord(uint8_t reg, uint16_t val) = 0; + virtual int32_t WriteRegBuffer(uint8_t reg, + const uint8_t* data, + uint32_t size, + uint32_t* bytes_written) = 0; }; class I2cDriverInfoBase { @@ -68,4 +83,4 @@ class I2cDriverInfo : public I2cDriverInfoBase { } // namespace android -#endif // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_H_
\ No newline at end of file +#endif // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_H_ diff --git a/daemon/i2c_driver_i2cdev.cc b/daemon/i2c_driver_i2cdev.cc index 2dbc4c4..b4f2280 100644 --- a/daemon/i2c_driver_i2cdev.cc +++ b/daemon/i2c_driver_i2cdev.cc @@ -70,42 +70,138 @@ bool I2cDriverI2cDev::Init(uint32_t bus_id, uint32_t address) { return true; } -bool I2cDriverI2cDev::ReadRegByte(uint8_t reg, uint8_t* val) { - union i2c_smbus_data data; +int32_t I2cDriverI2cDev::Read(void* data, uint32_t size, uint32_t* bytes_read) { + *bytes_read = char_interface_->Read(fd_, data, size); + return *bytes_read == size ? 0 : EIO; +} + +int32_t I2cDriverI2cDev::ReadRegByte(uint8_t reg, uint8_t* val) { + union i2c_smbus_data read_data; + struct i2c_smbus_ioctl_data smbus_args { + .command = reg, .read_write = I2C_SMBUS_READ, .size = I2C_SMBUS_BYTE_DATA, + .data = &read_data, + }; + + if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) { + LOG(INFO) << "Failed I2C_SMBUS"; + return EIO; + } + + *val = read_data.byte; + return 0; +} + +int32_t I2cDriverI2cDev::ReadRegWord(uint8_t reg, uint16_t* val) { + union i2c_smbus_data read_data; + struct i2c_smbus_ioctl_data smbus_args { + .command = reg, .read_write = I2C_SMBUS_READ, .size = I2C_SMBUS_WORD_DATA, + .data = &read_data, + }; + + if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) { + LOG(INFO) << "Failed I2C_SMBUS"; + return EIO; + } + + *val = read_data.word; + return 0; +} + +int32_t I2cDriverI2cDev::ReadRegBuffer(uint8_t reg, + uint8_t* data, + uint32_t size, + uint32_t* bytes_read) { + *bytes_read = 0; + if (size > I2C_SMBUS_BLOCK_MAX) { + LOG(WARNING) << "Can't read more than 32 bytes at a time."; + return EINVAL; + } + + union i2c_smbus_data read_data; + read_data.block[0] = size; struct i2c_smbus_ioctl_data smbus_args; smbus_args.command = reg; smbus_args.read_write = I2C_SMBUS_READ; - smbus_args.size = I2C_SMBUS_BYTE_DATA; - smbus_args.data = &data; + smbus_args.size = I2C_SMBUS_I2C_BLOCK_DATA; + smbus_args.data = &read_data; if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) { LOG(ERROR) << "Failed I2C_SMBUS"; - return false; + return EIO; } - *val = data.byte; + memcpy(data, &read_data.block[1], size); + *bytes_read = size; - return true; + return 0; } -bool I2cDriverI2cDev::ReadRegWord(uint8_t reg, uint16_t* val) { - union i2c_smbus_data data; +int32_t I2cDriverI2cDev::Write(const void* data, + uint32_t size, + uint32_t* bytes_written) { + *bytes_written = char_interface_->Write(fd_, data, size); + return *bytes_written == size ? 0 : EIO; +} +int32_t I2cDriverI2cDev::WriteRegByte(uint8_t reg, uint8_t val) { + union i2c_smbus_data write_data; + write_data.byte = val; struct i2c_smbus_ioctl_data smbus_args; smbus_args.command = reg; - smbus_args.read_write = I2C_SMBUS_READ; + smbus_args.read_write = I2C_SMBUS_WRITE; + smbus_args.size = I2C_SMBUS_BYTE_DATA; + smbus_args.data = &write_data; + + if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) { + return EIO; + } + return 0; +} + +int32_t I2cDriverI2cDev::WriteRegWord(uint8_t reg, uint16_t val) { + union i2c_smbus_data write_data; + write_data.word = val; + struct i2c_smbus_ioctl_data smbus_args; + smbus_args.command = reg; + smbus_args.read_write = I2C_SMBUS_WRITE; smbus_args.size = I2C_SMBUS_WORD_DATA; - smbus_args.data = &data; + smbus_args.data = &write_data; + + if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) { + return EIO; + } + return 0; +} + +int32_t I2cDriverI2cDev::WriteRegBuffer(uint8_t reg, + const uint8_t* data, + uint32_t size, + uint32_t* bytes_written) { + *bytes_written = 0; + if (size > I2C_SMBUS_BLOCK_MAX) { + LOG(WARNING) << "Can't write more than 32 bytes at a time."; + return EINVAL; + } + + union i2c_smbus_data write_data; + write_data.block[0] = size; + memcpy(&write_data.block[1], data, size); + + struct i2c_smbus_ioctl_data smbus_args; + smbus_args.command = reg; + smbus_args.read_write = I2C_SMBUS_WRITE; + smbus_args.size = I2C_SMBUS_I2C_BLOCK_DATA; + smbus_args.data = &write_data; if (char_interface_->Ioctl(fd_, I2C_SMBUS, &smbus_args) < 0) { LOG(ERROR) << "Failed I2C_SMBUS"; - return false; + return EIO; } - *val = data.word; + *bytes_written = size; - return true; + return 0; } -} // namespace
\ No newline at end of file +} // namespace diff --git a/daemon/i2c_driver_i2cdev.h b/daemon/i2c_driver_i2cdev.h index 680494a..ee9c1ce 100644 --- a/daemon/i2c_driver_i2cdev.h +++ b/daemon/i2c_driver_i2cdev.h @@ -37,8 +37,23 @@ class I2cDriverI2cDev : public I2cDriverInterface { bool Init(uint32_t bus_id, uint32_t address) override; - bool ReadRegByte(uint8_t reg, uint8_t* val) override; - bool ReadRegWord(uint8_t reg, uint16_t* val) override; + int32_t Read(void* data, uint32_t size, uint32_t* bytes_read) override; + int32_t ReadRegByte(uint8_t reg, uint8_t* val) override; + int32_t ReadRegWord(uint8_t reg, uint16_t* val) override; + int32_t ReadRegBuffer(uint8_t reg, + uint8_t* data, + uint32_t size, + uint32_t* bytes_read) override; + + int32_t Write(const void* data, + uint32_t size, + uint32_t* bytes_written) override; + int32_t WriteRegByte(uint8_t reg, uint8_t val) override; + int32_t WriteRegWord(uint8_t reg, uint16_t val) override; + int32_t WriteRegBuffer(uint8_t reg, + const uint8_t* data, + uint32_t size, + uint32_t* bytes_written) override; private: int fd_; @@ -52,4 +67,4 @@ class I2cDriverI2cDev : public I2cDriverInterface { } // namespace android -#endif // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_I2CDEV_H_
\ No newline at end of file +#endif // SYSTEM_PERIPHERALMANAGER_DAEMON_I2C_DRIVER_I2CDEV_H_ diff --git a/daemon/i2c_manager.h b/daemon/i2c_manager.h index 16842d7..e6011ae 100644 --- a/daemon/i2c_manager.h +++ b/daemon/i2c_manager.h @@ -51,14 +51,45 @@ class I2cDevice { bus_->driver_.erase(address_); } - bool ReadRegByte(uint8_t reg, uint8_t* val) { + int32_t Read(void* data, uint32_t size, uint32_t* bytes_read) { + return bus_->driver_[address_]->Read(data, size, bytes_read); + } + + int32_t ReadRegByte(uint8_t reg, uint8_t* val) { return bus_->driver_[address_]->ReadRegByte(reg, val); } - bool ReadRegWord(uint8_t reg, uint16_t* val) { + int32_t ReadRegWord(uint8_t reg, uint16_t* val) { return bus_->driver_[address_]->ReadRegWord(reg, val); } + int32_t ReadRegBuffer(uint8_t reg, + uint8_t* data, + uint32_t size, + uint32_t* bytes_read) { + return bus_->driver_[address_]->ReadRegBuffer(reg, data, size, bytes_read); + } + + int32_t Write(const void* data, uint32_t size, uint32_t* bytes_written) { + return bus_->driver_[address_]->Write(data, size, bytes_written); + } + + int32_t WriteRegByte(uint8_t reg, uint8_t val) { + return bus_->driver_[address_]->WriteRegByte(reg, val); + } + + int32_t WriteRegWord(uint8_t reg, uint16_t val) { + return bus_->driver_[address_]->WriteRegWord(reg, val); + } + + int32_t WriteRegBuffer(uint8_t reg, + const uint8_t* data, + uint32_t size, + uint32_t* bytes_written) { + return bus_->driver_[address_]->WriteRegBuffer( + reg, data, size, bytes_written); + } + private: I2cDevBus* bus_; uint32_t address_; diff --git a/daemon/peripheral_manager_client.cc b/daemon/peripheral_manager_client.cc index d279a9f..b862dba 100644 --- a/daemon/peripheral_manager_client.cc +++ b/daemon/peripheral_manager_client.cc @@ -346,14 +346,37 @@ Status PeripheralManagerClient::ReleaseI2cDevice(const std::string& name, return Status::ok(); } +Status PeripheralManagerClient::I2cRead(const std::string& name, + int32_t address, + std::vector<uint8_t>* data, + int32_t size, + int32_t* bytes_read) { + if (!i2c_devices_.count({name, address})) + return Status::fromServiceSpecificError(EPERM); + + if (size < 0) { + return Status::fromServiceSpecificError(EINVAL); + } + data->resize(size); + + uint32_t* nread = reinterpret_cast<uint32_t*>(bytes_read); + int32_t ret = i2c_devices_.find({name, address}) + ->second->Read(data->data(), data->size(), nread); + data->resize(*nread); + + return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret); +} + Status PeripheralManagerClient::I2cReadRegByte(const std::string& name, int32_t address, int32_t reg, int32_t* val) { if (!i2c_devices_.count({name, address})) return Status::fromServiceSpecificError(EPERM); + uint8_t tmp_val = 0; - if (i2c_devices_.find({name, address})->second->ReadRegByte(reg, &tmp_val)) { + if (i2c_devices_.find({name, address})->second->ReadRegByte(reg, &tmp_val) == + 0) { *val = tmp_val; return Status::ok(); } @@ -367,8 +390,10 @@ Status PeripheralManagerClient::I2cReadRegWord(const std::string& name, int32_t* val) { if (!i2c_devices_.count({name, address})) return Status::fromServiceSpecificError(EPERM); + uint16_t tmp_val = 0; - if (i2c_devices_.find({name, address})->second->ReadRegWord(reg, &tmp_val)) { + if (i2c_devices_.find({name, address})->second->ReadRegWord(reg, &tmp_val) == + 0) { *val = tmp_val; return Status::ok(); } @@ -376,4 +401,89 @@ Status PeripheralManagerClient::I2cReadRegWord(const std::string& name, return Status::fromServiceSpecificError(EREMOTEIO); } +Status PeripheralManagerClient::I2cReadRegBuffer(const std::string& name, + int32_t address, + int32_t reg, + std::vector<uint8_t>* data, + int32_t size, + int32_t* bytes_read) { + if (!i2c_devices_.count({name, address})) + return Status::fromServiceSpecificError(EPERM); + + if (size < 0) { + return Status::fromServiceSpecificError(EINVAL); + } + data->resize(size); + + uint32_t* nread = reinterpret_cast<uint32_t*>(bytes_read); + int32_t ret = + i2c_devices_.find({name, address}) + ->second->ReadRegBuffer(reg, data->data(), data->size(), nread); + + data->resize(*nread); + return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret); +} + +Status PeripheralManagerClient::I2cWrite(const std::string& name, + int32_t address, + const std::vector<uint8_t>& data, + int32_t* bytes_written) { + if (!i2c_devices_.count({name, address})) + return Status::fromServiceSpecificError(EPERM); + + int ret = i2c_devices_.find({name, address}) + ->second->Write(data.data(), + data.size(), + reinterpret_cast<uint32_t*>(bytes_written)); + + return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret); +} + +Status PeripheralManagerClient::I2cWriteRegByte(const std::string& name, + int32_t address, + int32_t reg, + int8_t val) { + if (!i2c_devices_.count({name, address})) + return Status::fromServiceSpecificError(EPERM); + + if (i2c_devices_.find({name, address})->second->WriteRegByte(reg, val) == 0) { + return Status::ok(); + } + + return Status::fromServiceSpecificError(EREMOTEIO); +} + +Status PeripheralManagerClient::I2cWriteRegWord(const std::string& name, + int32_t address, + int32_t reg, + int32_t val) { + if (!i2c_devices_.count({name, address})) + return Status::fromServiceSpecificError(EPERM); + + if (i2c_devices_.find({name, address})->second->WriteRegWord(reg, val) == 0) { + return Status::ok(); + } + + return Status::fromServiceSpecificError(EREMOTEIO); +} + +Status PeripheralManagerClient::I2cWriteRegBuffer( + const std::string& name, + int32_t address, + int32_t reg, + const std::vector<uint8_t>& data, + int32_t* bytes_written) { + if (!i2c_devices_.count({name, address})) + return Status::fromServiceSpecificError(EPERM); + + int32_t ret = + i2c_devices_.find({name, address}) + ->second->WriteRegBuffer(reg, + data.data(), + data.size(), + reinterpret_cast<uint32_t*>(bytes_written)); + + return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret); +} + } // namespace android diff --git a/daemon/peripheral_manager_client.h b/daemon/peripheral_manager_client.h index 23d15c7..6955b8d 100644 --- a/daemon/peripheral_manager_client.h +++ b/daemon/peripheral_manager_client.h @@ -40,8 +40,7 @@ class PeripheralManagerClient : public BnPeripheralManagerClient { PeripheralManagerClient(); ~PeripheralManagerClient(); - // Binder functions. - + // Gpio functions. virtual Status ListGpio(std::vector<std::string>* gpios) override; virtual Status OpenGpio(const std::string& name) override; @@ -62,6 +61,7 @@ class PeripheralManagerClient : public BnPeripheralManagerClient { virtual Status GetGpioPollingFd(const std::string& name, ScopedFd* fd) override; + // Spi functions. virtual Status ListSpiBuses(std::vector<std::string>* buses) override; virtual Status OpenSpiDevice(const std::string& name) override; @@ -95,6 +95,7 @@ class PeripheralManagerClient : public BnPeripheralManagerClient { virtual Status SpiDeviceSetDelay(const std::string& name, int delay_usecs) override; + // Led functions. virtual Status ListLeds(std::vector<std::string>* leds) override; virtual Status OpenLed(const std::string& name) override; @@ -108,6 +109,7 @@ class PeripheralManagerClient : public BnPeripheralManagerClient { virtual Status LedSetBrightness(const std::string& name, int brightness) override; + // I2c functions. virtual Status ListI2cBuses(std::vector<std::string>* buses) override; virtual Status OpenI2cDevice(const std::string& name, @@ -116,6 +118,12 @@ class PeripheralManagerClient : public BnPeripheralManagerClient { virtual Status ReleaseI2cDevice(const std::string& name, int32_t address) override; + virtual Status I2cRead(const std::string& name, + int32_t address, + std::vector<uint8_t>* data, + int32_t size, + ssize_t* bytes_read) override; + virtual Status I2cReadRegByte(const std::string& name, int32_t address, int32_t reg, @@ -126,6 +134,34 @@ class PeripheralManagerClient : public BnPeripheralManagerClient { int32_t reg, int32_t* val) override; + virtual Status I2cReadRegBuffer(const std::string& name, + int32_t address, + int32_t reg, + std::vector<uint8_t>* data, + int32_t size, + ssize_t* bytes_read) override; + + virtual Status I2cWrite(const std::string& name, + int32_t address, + const std::vector<uint8_t>& data, + ssize_t* bytes_written) override; + + virtual Status I2cWriteRegByte(const std::string& name, + int32_t address, + int32_t reg, + int8_t val) override; + + virtual Status I2cWriteRegWord(const std::string& name, + int32_t address, + int32_t reg, + int32_t val) override; + + virtual Status I2cWriteRegBuffer(const std::string& name, + int32_t address, + int32_t reg, + const std::vector<uint8_t>& data, + ssize_t* bytes_written) override; + private: std::map<std::string, std::unique_ptr<GpioPin>> gpios_; std::map<std::pair<std::string, uint32_t>, std::unique_ptr<I2cDevice>> diff --git a/ipc/android/os/IPeripheralManagerClient.aidl b/ipc/android/os/IPeripheralManagerClient.aidl index bc99415..61a0e5a 100644 --- a/ipc/android/os/IPeripheralManagerClient.aidl +++ b/ipc/android/os/IPeripheralManagerClient.aidl @@ -17,6 +17,7 @@ package android.os; interface IPeripheralManagerClient { + // Gpio functions. void ListGpio(out @utf8InCpp List<String> gpios); void OpenGpio(@utf8InCpp String name); @@ -35,6 +36,8 @@ interface IPeripheralManagerClient { FileDescriptor GetGpioPollingFd(@utf8InCpp String name); + + // Spi functions. void ListSpiBuses(out @utf8InCpp List<String> buses); void OpenSpiDevice(@utf8InCpp String name); @@ -59,6 +62,8 @@ interface IPeripheralManagerClient { void SpiDeviceSetDelay(@utf8InCpp String name, int delay_usecs); + + // Leds functions. void ListLeds(out @utf8InCpp List<String> leds); void OpenLed(@utf8InCpp String name); @@ -71,13 +76,29 @@ interface IPeripheralManagerClient { void LedSetBrightness(@utf8InCpp String name, int brightness); + + // I2c functions. void ListI2cBuses(out @utf8InCpp List<String> buses); void OpenI2cDevice(@utf8InCpp String name, int address); void ReleaseI2cDevice(@utf8InCpp String name, int address); + int I2cRead(@utf8InCpp String name, int address, out byte[] data, int size); + int I2cReadRegByte(@utf8InCpp String name, int address, int reg); int I2cReadRegWord(@utf8InCpp String name, int address, int reg); + + int I2cReadRegBuffer(@utf8InCpp String name, int address, int reg, + out byte[] data, int size); + + int I2cWrite(@utf8InCpp String name, int address, in byte[] data); + + void I2cWriteRegByte(@utf8InCpp String name, int address, int reg, byte val); + + void I2cWriteRegWord(@utf8InCpp String name, int address, int reg, int val); + + int I2cWriteRegBuffer(@utf8InCpp String name, int address, int reg, + in byte[] data); } |