Refactor I2C SMBUS
Add SI7021 chipset, partially done.
This commit is contained in:
178
src/mgos_i2c.c
178
src/mgos_i2c.c
@ -89,117 +89,80 @@ bool mgos_i2c_set_freq(struct mgos_i2c *i2c, int freq) {
|
||||
}
|
||||
|
||||
int mgos_i2c_read_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) {
|
||||
uint8_t data;
|
||||
uint8_t value;
|
||||
|
||||
if (!i2c) {
|
||||
LOG(LL_ERROR, ("No I2C bus"));
|
||||
if (!mgos_i2c_read_reg_n(i2c, addr, reg, 1, &value))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
|
||||
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
if (1 != write(i2c->fd, ®, 1)) {
|
||||
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
if (1 != i2c_read_timeout(i2c, &data, 1)) {
|
||||
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
return data;
|
||||
return value;
|
||||
}
|
||||
|
||||
int mgos_i2c_read_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg) {
|
||||
uint16_t data;
|
||||
uint16_t value;
|
||||
uint8_t data[2];
|
||||
|
||||
if (!i2c) {
|
||||
LOG(LL_ERROR, ("No I2C bus"));
|
||||
if (!mgos_i2c_read_reg_n(i2c, addr, reg, 2, data))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
|
||||
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
if (1 != write(i2c->fd, ®, 1)) {
|
||||
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
if (2 != i2c_read_timeout(i2c, &data, 2)) {
|
||||
LOG(LL_ERROR, ("Cannot read register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
return data;
|
||||
value=(data[1]<<8)+data[0];
|
||||
return value;
|
||||
}
|
||||
|
||||
bool mgos_i2c_read_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_t n, uint8_t *buf) {
|
||||
uint8_t outbuf;
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
struct i2c_msg messages[2];
|
||||
|
||||
if (!i2c) {
|
||||
LOG(LL_ERROR, ("No I2C bus"));
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
|
||||
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
if (1 != write(i2c->fd, ®, 1)) {
|
||||
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
if (n != i2c_read_timeout(i2c, buf, n)) {
|
||||
LOG(LL_ERROR, ("Cannot read %lu bytes at register 0x%02x on device 0x%04x: %s", n, reg, addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* In order to read a register, we first do a "dummy write" by writing
|
||||
* 0 bytes to the register we want to read from. This is similar to
|
||||
* the packet in set_i2c_register, except it's 1 byte rather than 2.
|
||||
*/
|
||||
outbuf = reg;
|
||||
messages[0].addr = addr;
|
||||
messages[0].flags = 0;
|
||||
messages[0].len = sizeof(outbuf);
|
||||
messages[0].buf = &outbuf;
|
||||
|
||||
bool mgos_i2c_write_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint8_t value) {
|
||||
uint8_t data[2];
|
||||
/* The data will get returned in this structure */
|
||||
messages[1].addr = addr;
|
||||
messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
|
||||
messages[1].len = n;
|
||||
messages[1].buf = buf;
|
||||
|
||||
if (!i2c) {
|
||||
LOG(LL_ERROR, ("No I2C bus"));
|
||||
/* Send the request to the kernel and get the result back */
|
||||
packets.msgs = messages;
|
||||
packets.nmsgs = 2;
|
||||
if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
|
||||
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
data[0]=reg;
|
||||
data[1]=value;
|
||||
if (2 != write(i2c->fd, data, 2)) {
|
||||
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mgos_i2c_write_reg_w(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint16_t value) {
|
||||
uint8_t data[3];
|
||||
uint8_t data[2];
|
||||
data[0]=value>>8;
|
||||
data[1]=value&0xFF;
|
||||
|
||||
if (!i2c) {
|
||||
LOG(LL_ERROR, ("No I2C bus"));
|
||||
return false;
|
||||
}
|
||||
return mgos_i2c_write_reg_n(i2c, addr, reg, 2, data);
|
||||
}
|
||||
|
||||
if (ioctl(i2c->fd,I2C_SLAVE,addr) < 0) {
|
||||
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
data[0]=reg;
|
||||
data[1]=(uint8_t)(0xFF & (value >> 0));
|
||||
data[2]=(uint8_t)(0xFF & (value >> 8));
|
||||
|
||||
if (3 != write(i2c->fd, data, 3)) {
|
||||
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
bool mgos_i2c_write_reg_b(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, uint8_t value) {
|
||||
return mgos_i2c_write_reg_n(i2c, addr, reg, 1, &value);
|
||||
}
|
||||
|
||||
bool mgos_i2c_write_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size_t n, const uint8_t *buf) {
|
||||
unsigned char outbuf[n+1];
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
struct i2c_msg messages[1];
|
||||
|
||||
if (!i2c) {
|
||||
LOG(LL_ERROR, ("No I2C bus"));
|
||||
return false;
|
||||
@ -209,13 +172,18 @@ bool mgos_i2c_write_reg_n(struct mgos_i2c *i2c, uint16_t addr, uint8_t reg, size
|
||||
LOG(LL_ERROR, ("Cannot select slave 0x%04x on I2C bus: %s", addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
if (1 != write(i2c->fd, ®, 1)) {
|
||||
LOG(LL_ERROR, ("Cannot select register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n != write(i2c->fd, buf, n)) {
|
||||
LOG(LL_ERROR, ("Cannot write to register 0x%02x on device 0x%04x: %s", reg, addr, strerror(errno)));
|
||||
messages[0].addr=addr;
|
||||
messages[0].flags=0;
|
||||
messages[0].len=sizeof(outbuf);
|
||||
messages[0].buf=outbuf;
|
||||
|
||||
outbuf[0]=reg;
|
||||
memcpy(outbuf+1, buf, n);
|
||||
|
||||
packets.msgs = messages;
|
||||
packets.nmsgs = 1;
|
||||
if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -229,42 +197,6 @@ struct mgos_i2c *mgos_i2c_get_global(void) {
|
||||
return s_global_i2c_bus;
|
||||
}
|
||||
|
||||
int get_i2c_register(struct mgos_i2c *i2c, uint8_t addr, uint8_t reg, uint8_t *val) {
|
||||
unsigned char inbuf, outbuf;
|
||||
struct i2c_rdwr_ioctl_data packets;
|
||||
struct i2c_msg messages[2];
|
||||
|
||||
/*
|
||||
* In order to read a register, we first do a "dummy write" by writing
|
||||
* 0 bytes to the register we want to read from. This is similar to
|
||||
* the packet in set_i2c_register, except it's 1 byte rather than 2.
|
||||
*/
|
||||
outbuf = reg;
|
||||
messages[0].addr = addr;
|
||||
messages[0].flags = 0;
|
||||
messages[0].len = sizeof(outbuf);
|
||||
messages[0].buf = &outbuf;
|
||||
|
||||
/* The data will get returned in this structure */
|
||||
messages[1].addr = addr;
|
||||
messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
|
||||
messages[1].len = sizeof(inbuf);
|
||||
messages[1].buf = &inbuf;
|
||||
|
||||
/* Send the request to the kernel and get the result back */
|
||||
packets.msgs = messages;
|
||||
packets.nmsgs = 2;
|
||||
if(ioctl(i2c->fd, I2C_RDWR, &packets) < 0) {
|
||||
LOG(LL_ERROR, ("Unable to send data"));
|
||||
return 1;
|
||||
}
|
||||
*val = inbuf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// User provided function to interface with Linux I2C driver
|
||||
bool mgos_i2c_open(int busnr) {
|
||||
int fd;
|
||||
|
Reference in New Issue
Block a user