aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertrand SIMONNET <bsimonnet@google.com>2016-03-24 14:15:02 -0700
committerTreehugger Robot <treehugger-gerrit@google.com>2016-04-25 23:18:52 +0000
commit8ad824905e84f8b001211eb88b8f18fbf3b5dd8c (patch)
treea91942dd35da42e3ce3a5353be7cd0b1b7bb9f0f
parent954874f0897fa810e2bdfbd44d1694c4da2fd461 (diff)
downloadperipheralmanager-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.h23
-rw-r--r--daemon/i2c_driver_i2cdev.cc126
-rw-r--r--daemon/i2c_driver_i2cdev.h21
-rw-r--r--daemon/i2c_manager.h35
-rw-r--r--daemon/peripheral_manager_client.cc114
-rw-r--r--daemon/peripheral_manager_client.h40
-rw-r--r--ipc/android/os/IPeripheralManagerClient.aidl21
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);
}