diff --git a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c index 38dbaab9a0f..c21b8f67753 100644 --- a/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/sbs_gauge.c @@ -35,6 +35,16 @@ static int sbs_cmd_reg_read(const struct device *dev, uint8_t reg_addr, uint16_t return 0; } +static int sbs_cmd_reg_write(const struct device *dev, uint8_t reg_addr, uint16_t val) +{ + const struct sbs_gauge_config *config = dev->config; + uint8_t buf[2]; + + sys_put_le16(val, buf); + + return i2c_burst_write_dt(&config->i2c, reg_addr, buf, sizeof(buf)); +} + static int sbs_gauge_get_prop(const struct device *dev, struct fuel_gauge_get_property *prop) { int rc = 0; @@ -94,6 +104,27 @@ static int sbs_gauge_get_prop(const struct device *dev, struct fuel_gauge_get_pr return rc; } +static int sbs_gauge_set_prop(const struct device *dev, struct fuel_gauge_set_property *prop) +{ + int rc = 0; + uint16_t val = 0; + + switch (prop->property_type) { + + case FUEL_GAUGE_SBS_MFR_ACCESS: + rc = sbs_cmd_reg_write(dev, SBS_GAUGE_CMD_MANUFACTURER_ACCESS, + prop->value.sbs_mfr_access_word); + prop->value.sbs_mfr_access_word = val; + break; + default: + rc = -ENOTSUP; + } + + prop->status = rc; + + return rc; +} + static int sbs_gauge_get_props(const struct device *dev, struct fuel_gauge_get_property *props, size_t len) { @@ -110,6 +141,22 @@ static int sbs_gauge_get_props(const struct device *dev, struct fuel_gauge_get_p return err_count; } +static int sbs_gauge_set_props(const struct device *dev, struct fuel_gauge_set_property *props, + size_t len) +{ + int err_count = 0; + + for (int i = 0; i < len; i++) { + int ret = sbs_gauge_set_prop(dev, props + i); + + err_count += ret ? 1 : 0; + } + + err_count = (err_count == len) ? -1 : err_count; + + return err_count; +} + /** * @brief initialize the fuel gauge * @@ -131,6 +178,7 @@ static int sbs_gauge_init(const struct device *dev) static const struct battery_driver_api sbs_gauge_driver_api = { .get_property = &sbs_gauge_get_props, + .set_property = &sbs_gauge_set_props, }; /* FIXME: fix init priority */ diff --git a/subsys/emul/i2c/emul_sbs_gauge.c b/subsys/emul/i2c/emul_sbs_gauge.c index 32ab45764be..5b9937368e5 100644 --- a/subsys/emul/i2c/emul_sbs_gauge.c +++ b/subsys/emul/i2c/emul_sbs_gauge.c @@ -25,7 +25,7 @@ LOG_MODULE_REGISTER(sbs_sbs_gauge); /** Run-time data used by the emulator */ struct sbs_gauge_emul_data { - /* Stub */ + uint16_t mfr_acc; }; /** Static configuration for the emulator */ @@ -36,10 +36,13 @@ struct sbs_gauge_emul_cfg { static int emul_sbs_gauge_reg_write(const struct emul *target, int reg, int val) { - ARG_UNUSED(target); + struct sbs_gauge_emul_data *data = target->data; LOG_INF("write %x = %x", reg, val); switch (reg) { + case SBS_GAUGE_CMD_MANUFACTURER_ACCESS: + data->mfr_acc = val; + break; default: LOG_INF("Unknown write %x", reg); return -EIO; @@ -50,10 +53,12 @@ static int emul_sbs_gauge_reg_write(const struct emul *target, int reg, int val) static int emul_sbs_gauge_reg_read(const struct emul *target, int reg, int *val) { - ARG_UNUSED(target); + struct sbs_gauge_emul_data *data = target->data; switch (reg) { case SBS_GAUGE_CMD_MANUFACTURER_ACCESS: + *val = data->mfr_acc; + break; case SBS_GAUGE_CMD_VOLTAGE: case SBS_GAUGE_CMD_AVG_CURRENT: case SBS_GAUGE_CMD_TEMP: diff --git a/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c b/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c index bf35c228cfa..a7a927ff0fe 100644 --- a/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c +++ b/tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c @@ -88,6 +88,79 @@ ZTEST_F(sbs_gauge_new_api, test_get_some_props_failed_returns_failed_prop_count) zassert_equal(ret, 2); } +ZTEST_F(sbs_gauge_new_api, test_set_all_props_failed_returns_negative) +{ + struct fuel_gauge_set_property props[] = { + { + /* Invalid property */ + .property_type = FUEL_GAUGE_PROP_MAX, + }, + }; + + int ret = fixture->api->set_property(fixture->dev, props, ARRAY_SIZE(props)); + + zassert_equal(props[0].status, -ENOTSUP, "Setting bad property %d has a good status.", + props[0].property_type); + + zassert_true(ret < 0); +} + +ZTEST_F(sbs_gauge_new_api, test_set_some_props_failed_returns_failed_prop_count) +{ + struct fuel_gauge_set_property props[] = { + { + /* First invalid property */ + .property_type = FUEL_GAUGE_PROP_MAX, + }, + { + /* Second invalid property */ + .property_type = FUEL_GAUGE_PROP_MAX, + }, + { + /* Valid property */ + .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, + /* Set Manufacturer's Access to arbitrary word */ + .value.sbs_mfr_access_word = 1, + }, + + }; + + int ret = fixture->api->set_property(fixture->dev, props, ARRAY_SIZE(props)); + + zassert_equal(props[0].status, -ENOTSUP, "Setting bad property %d has a good status.", + props[0].property_type); + + zassert_equal(props[1].status, -ENOTSUP, "Setting bad property %d has a good status.", + props[1].property_type); + + zassert_ok(props[2].status, "Property %d setting %d has a bad status.", 2, + props[2].property_type); + + zassert_equal(ret, 2); +} + +ZTEST_F(sbs_gauge_new_api, test_set_prop_can_be_get) +{ + uint16_t word = BIT(15) | BIT(0); + struct fuel_gauge_set_property set_prop = { + /* Valid property */ + .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, + /* Set Manufacturer's Access to 16 bit word*/ + .value.sbs_mfr_access_word = word, + }; + + zassert_ok(fixture->api->set_property(fixture->dev, &set_prop, 1)); + zassert_ok(set_prop.status); + + struct fuel_gauge_get_property get_prop = { + .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, + }; + + zassert_ok(fixture->api->get_property(fixture->dev, &get_prop, 1)); + zassert_ok(get_prop.status); + zassert_equal(get_prop.value.sbs_mfr_access_word, word); +} + ZTEST_F(sbs_gauge_new_api, test_get_props__returns_ok) { /* Validate what props are supported by the driver */ @@ -138,4 +211,24 @@ ZTEST_F(sbs_gauge_new_api, test_get_props__returns_ok) zassert_ok(ret); } +ZTEST_F(sbs_gauge_new_api, test_set_props__returns_ok) +{ + /* Validate what props are supported by the driver */ + + struct fuel_gauge_set_property props[] = { + { + .property_type = FUEL_GAUGE_SBS_MFR_ACCESS, + }, + }; + + int ret = fixture->api->set_property(fixture->dev, props, ARRAY_SIZE(props)); + + for (int i = 0; i < ARRAY_SIZE(props); i++) { + zassert_ok(props[i].status, "Property %d writing %d has a bad status.", i, + props[i].property_type); + } + + zassert_ok(ret); +} + ZTEST_SUITE(sbs_gauge_new_api, NULL, sbs_gauge_new_api_setup, NULL, NULL, NULL);