blob: 35089b60cb26733c0b5dac6827ef32b060a70301 [file] [log] [blame]
// Copyright 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "i2c_device.h"
I2CDevice::I2CDevice(const char* device_filename,
const uint8_t device_address) :
// Does nothing except store the constant values.
address_(device_address),
filename_(device_filename)
{
LOG(INFO) << "New i2c device for " << address_ << " at " << filename_;
}
int I2CDevice::Begin() {
// First, this opens the /dev device.
int rc = open_i2c();
if (rc < 0) {
return rc;
}
// Then, registers it as a slave.
rc = enslave_i2c();
if (rc < 0) {
return rc;
}
return 0;
}
int I2CDevice::End() {
return close(fd_);
}
int I2CDevice::open_i2c() {
// Opening the device is just a R/W file open.
int fd = open(filename_, O_RDWR);
if (-1 == fd) {
PLOG(ERROR) << "Could not open i2c device.";
return -1;
}
LOG(INFO) << "i2c device opened at " << filename_;
fd_ = fd;
return fd;
}
int I2CDevice::enslave_i2c() {
// The I2C_SLAVE ioctl is sent to the device at the given address.
int rc = ioctl(fd_, I2C_SLAVE, address_);
if (rc < 0) {
PLOG(ERROR) << "i2c device failed to become a slave.";
return rc;
}
printf("yes %x\n", address_);
LOG(INFO) << "i2c device is a slave at" << filename_;
return rc;
}
int I2CDevice::Send(struct i2c_msg messages[],
const size_t count) {
// Sending messages requires them to be wrapped in the i2c_rdwr_ioctl_data
// struct and sending them using the I2C_RDWR ioctl.
struct i2c_rdwr_ioctl_data data = {
.msgs = messages,
.nmsgs = count
};
int rc = ioctl(fd_, I2C_RDWR, &data);
if (rc < 0) {
PLOG(ERROR) << "Unable to send data.";
}
return rc;
}
int I2CDevice::SetRegister(const uint8_t register_address,
const uint8_t value) {
// Setting a register involves sending a single message with a 2-byte payload.
// The first byte is the register address, and the second is the value.
uint8_t outbuf[] = {register_address, value};
struct i2c_msg messages[1];
messages[0] = {
.addr = address_,
.flags = 0,
.len = sizeof(outbuf),
.buf = outbuf
};
return Send(messages, 1);
}
int I2CDevice::GetRegister(const uint8_t register_address,
uint8_t& value) {
// Reading a register involves sending two messages, each with a single-byte
// payload. The first message contains the register address and the second
// message is empty and will contain the response value.
struct i2c_msg messages[2];
uint8_t outbuf = register_address;
// Both messages need the addr value set.
messages[0] = {
.addr = address_,
.flags = 0,
.len = 1,
.buf = &outbuf
};
// Needs to pass the I2C_M_RD flag in order to get the value.
messages[1] = {
.addr = address_,
.flags = I2C_M_RD,
.len = 1,
.buf = &value,
};
// Will contain the register value.
int rc = Send(messages, 2);
return rc;
}