fuel_gauge: Add fuel_guage_get_props()
The fuel_gauge_get_prop() function prototype declares a function that retrieves multiple fuel gauge properties at once. The naming suggests it ought to fetch a singular property at a time. Moreso, some clients may just want to fetch properties one at a time and may feel uncomfortable using a prototype for fetching multiple properties when wanting to fetch them one at a time. Modify fuel_gauge_get_prop() to fetch a single property and add fuel_gauge_get_props() to support fetching multiple properties. Modify existing tests/drivers/samples. This is part of #61818 work. Signed-off-by: Aaron Massey <aaronmassey@google.com>
This commit is contained in:
parent
18eff4ea00
commit
e294b16a2f
|
@ -20,8 +20,9 @@ Fundamentally, a property is a quantity that a fuel gauge device can measure.
|
|||
Fuel gauges typically support multiple properties, such as temperature readings of the battery-pack
|
||||
or present-time current/voltage.
|
||||
|
||||
Properties are fetched using a client allocated array of :c:struct:`fuel_gauge_property`. This
|
||||
array is then populated by values as according to its `property_type` field.
|
||||
Properties are fetched one at a time using a client allocated :c:struct:`fuel_gauge_property` or
|
||||
fetched all at once using a client allocated array of :c:struct:`fuel_gauge_property`. Each
|
||||
:c:struct:`fuel_gauge_property` is populated by values according to its `property_type` field.
|
||||
|
||||
Battery Cutoff
|
||||
==============
|
||||
|
|
|
@ -260,22 +260,6 @@ static int bq27z746_set_prop(const struct device *dev, struct fuel_gauge_propert
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int bq27z746_get_props(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t len)
|
||||
{
|
||||
int err_count = 0;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ret = bq27z746_get_prop(dev, props + i);
|
||||
|
||||
err_count += ret ? 1 : 0;
|
||||
}
|
||||
|
||||
err_count = (err_count == len) ? -1 : err_count;
|
||||
|
||||
return err_count;
|
||||
}
|
||||
|
||||
static int bq27z746_set_props(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t len)
|
||||
{
|
||||
|
@ -307,7 +291,7 @@ static int bq27z746_init(const struct device *dev)
|
|||
}
|
||||
|
||||
static const struct fuel_gauge_driver_api bq27z746_driver_api = {
|
||||
.get_property = &bq27z746_get_props,
|
||||
.get_property = &bq27z746_get_prop,
|
||||
.set_property = &bq27z746_set_props,
|
||||
.get_buffer_property = &bq27z746_get_buffer_prop,
|
||||
};
|
||||
|
|
|
@ -9,24 +9,40 @@
|
|||
#include <zephyr/drivers/fuel_gauge.h>
|
||||
|
||||
static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev,
|
||||
struct fuel_gauge_property *props,
|
||||
size_t props_len)
|
||||
struct fuel_gauge_property *prop)
|
||||
{
|
||||
struct fuel_gauge_property k_prop;
|
||||
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property));
|
||||
|
||||
Z_OOPS(z_user_from_copy(&k_prop, prop, sizeof(struct fuel_gauge_property)));
|
||||
|
||||
int ret = z_impl_fuel_gauge_get_prop(dev, &k_prop);
|
||||
|
||||
Z_OOPS(z_user_to_copy(prop, &k_prop, sizeof(struct fuel_gauge_property)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <syscalls/fuel_gauge_get_prop_mrsh.c>
|
||||
|
||||
static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev,
|
||||
struct fuel_gauge_property *props, size_t props_len)
|
||||
{
|
||||
struct fuel_gauge_property k_props[props_len];
|
||||
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_property));
|
||||
|
||||
Z_OOPS(z_user_from_copy(k_props, props,
|
||||
props_len * sizeof(struct fuel_gauge_property)));
|
||||
Z_OOPS(z_user_from_copy(k_props, props, props_len * sizeof(struct fuel_gauge_property)));
|
||||
|
||||
int ret = z_impl_fuel_gauge_get_prop(dev, k_props, props_len);
|
||||
int ret = z_impl_fuel_gauge_get_props(dev, k_props, props_len);
|
||||
|
||||
Z_OOPS(z_user_to_copy(props, k_props, props_len * sizeof(struct fuel_gauge_property)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <syscalls/fuel_gauge_get_prop_mrsh.c>
|
||||
#include <syscalls/fuel_gauge_get_props_mrsh.c>
|
||||
|
||||
static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev,
|
||||
struct fuel_gauge_property *props,
|
||||
|
|
|
@ -175,7 +175,7 @@ static int max17048_init(const struct device *dev)
|
|||
/**
|
||||
* Get a single property from the fuel gauge
|
||||
*/
|
||||
static int max17048_get_prop(const struct device *dev, struct fuel_gauge_property *prop)
|
||||
static int max17048_get_single_prop_impl(const struct device *dev, struct fuel_gauge_property *prop)
|
||||
{
|
||||
struct max17048_data *data = dev->data;
|
||||
int rc = 0;
|
||||
|
@ -203,15 +203,14 @@ static int max17048_get_prop(const struct device *dev, struct fuel_gauge_propert
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all possible properties from the fuel gague
|
||||
* Get properties from the fuel gauge
|
||||
*/
|
||||
static int max17048_get_props(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t len)
|
||||
static int max17048_get_prop(const struct device *dev, struct fuel_gauge_property *prop)
|
||||
{
|
||||
int err_count = 0;
|
||||
struct max17048_data *data = dev->data;
|
||||
int rc = max17048_percent(dev, &data->charge);
|
||||
int16_t crate;
|
||||
int ret;
|
||||
|
||||
if (rc < 0) {
|
||||
LOG_ERR("Error while reading battery percentage");
|
||||
|
@ -242,7 +241,6 @@ static int max17048_get_props(const struct device *dev, struct fuel_gauge_proper
|
|||
*/
|
||||
data->charging = crate > 0;
|
||||
|
||||
|
||||
/**
|
||||
* In the following code, we multiply by 1000 the charge to increase the
|
||||
* precision. If we just truncate the division without this multiplier,
|
||||
|
@ -266,12 +264,6 @@ static int max17048_get_props(const struct device *dev, struct fuel_gauge_proper
|
|||
data->time_to_empty = hours_pending * 60 / 1000;
|
||||
data->time_to_full = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ret = max17048_get_prop(dev, props + i);
|
||||
|
||||
err_count += ret ? 1 : 0;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* This case is to avoid a division by 0 when the charge rate is the same
|
||||
|
@ -283,13 +275,13 @@ static int max17048_get_props(const struct device *dev, struct fuel_gauge_proper
|
|||
data->time_to_empty = 0;
|
||||
}
|
||||
|
||||
err_count = (err_count == len) ? -1 : err_count;
|
||||
ret = max17048_get_single_prop_impl(dev, prop);
|
||||
|
||||
return err_count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct fuel_gauge_driver_api max17048_driver_api = {
|
||||
.get_property = &max17048_get_props,
|
||||
.get_property = &max17048_get_prop,
|
||||
};
|
||||
|
||||
#define MAX17048_DEFINE(inst) \
|
||||
|
|
|
@ -274,22 +274,6 @@ static int sbs_gauge_get_buffer_prop(const struct device *dev,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int sbs_gauge_get_props(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t len)
|
||||
{
|
||||
int err_count = 0;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ret = sbs_gauge_get_prop(dev, props + i);
|
||||
|
||||
err_count += ret ? 1 : 0;
|
||||
}
|
||||
|
||||
err_count = (err_count == len) ? -1 : err_count;
|
||||
|
||||
return err_count;
|
||||
}
|
||||
|
||||
static int sbs_gauge_set_props(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t len)
|
||||
{
|
||||
|
@ -326,7 +310,7 @@ static int sbs_gauge_init(const struct device *dev)
|
|||
}
|
||||
|
||||
static const struct fuel_gauge_driver_api sbs_gauge_driver_api = {
|
||||
.get_property = &sbs_gauge_get_props,
|
||||
.get_property = &sbs_gauge_get_prop,
|
||||
.set_property = &sbs_gauge_set_props,
|
||||
.get_buffer_property = &sbs_gauge_get_buffer_prop,
|
||||
.battery_cutoff = &sbs_gauge_do_battery_cutoff,
|
||||
|
|
|
@ -222,7 +222,7 @@ struct sbs_gauge_device_chemistry {
|
|||
* See fuel_gauge_get_property() for argument description
|
||||
*/
|
||||
typedef int (*fuel_gauge_get_property_t)(const struct device *dev,
|
||||
struct fuel_gauge_property *props, size_t props_len);
|
||||
struct fuel_gauge_property *prop);
|
||||
|
||||
/**
|
||||
* @typedef fuel_gauge_set_property_t
|
||||
|
@ -254,6 +254,12 @@ typedef int (*fuel_gauge_battery_cutoff_t)(const struct device *dev);
|
|||
/* Caching is entirely on the onus of the client */
|
||||
|
||||
__subsystem struct fuel_gauge_driver_api {
|
||||
/**
|
||||
* Note: Historically this API allowed drivers to implement a custom multi-get/set property
|
||||
* function, this was added so drivers could potentially optimize batch read with their
|
||||
* specific chip. However, it was removed because of no existing concrete case upstream.
|
||||
* If this need is demonstrated, we can add this back in as an API field.
|
||||
*/
|
||||
fuel_gauge_get_property_t get_property;
|
||||
fuel_gauge_set_property_t set_property;
|
||||
fuel_gauge_get_buffer_property_t get_buffer_property;
|
||||
|
@ -264,21 +270,17 @@ __subsystem struct fuel_gauge_driver_api {
|
|||
* @brief Fetch a battery fuel-gauge property
|
||||
*
|
||||
* @param dev Pointer to the battery fuel-gauge device
|
||||
* @param props pointer to array of fuel_gauge_property struct where the property struct
|
||||
* @param prop pointer to a fuel_gauge_property struct where the property struct
|
||||
* field is set by the caller to determine what property is read from the
|
||||
* fuel gauge device into the fuel_gauge_property struct's value field. The props array
|
||||
* maintains the same order of properties as it was given.
|
||||
* @param props_len number of properties in props array
|
||||
*
|
||||
* @return return=0 if successful, return < 0 if getting all properties failed, return > 0 if some
|
||||
* properties failed where return=number of failing properties.
|
||||
* @return 0 if successful, negative errno code if failure.
|
||||
*/
|
||||
__syscall int fuel_gauge_get_prop(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t props_len);
|
||||
__syscall int fuel_gauge_get_prop(const struct device *dev, struct fuel_gauge_property *prop);
|
||||
|
||||
static inline int z_impl_fuel_gauge_get_prop(const struct device *dev,
|
||||
struct fuel_gauge_property *props,
|
||||
size_t props_len)
|
||||
struct fuel_gauge_property *prop)
|
||||
{
|
||||
const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
|
||||
|
||||
|
@ -286,7 +288,41 @@ static inline int z_impl_fuel_gauge_get_prop(const struct device *dev,
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return api->get_property(dev, props, props_len);
|
||||
return api->get_property(dev, prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch multiple battery fuel-gauge properies. The default implementation is the same as
|
||||
* calling fuel_gauge_get_prop() multiple times. A driver may implement the `get_properties` field
|
||||
* of the fuel gauge driver APIs struct to override this implementation.
|
||||
*
|
||||
* @param dev Pointer to the battery fuel-gauge device
|
||||
* @param props pointer to array of fuel_gauge_property struct where the property struct
|
||||
* field is set by the caller to determine what property is read from the
|
||||
* fuel gauge device into the fuel_gauge_property struct's value field. The props array
|
||||
* maintains the same order of properties as it was given.
|
||||
* @param len number of properties in props array
|
||||
*
|
||||
* @return return=0 if successful, return < 0 if getting all properties failed, return > 0 if some
|
||||
* properties failed where return=number of failing properties.
|
||||
*/
|
||||
__syscall int fuel_gauge_get_props(const struct device *dev, struct fuel_gauge_property *props,
|
||||
size_t len);
|
||||
static inline int z_impl_fuel_gauge_get_props(const struct device *dev,
|
||||
struct fuel_gauge_property *props, size_t len)
|
||||
{
|
||||
int err_count = 0;
|
||||
const struct fuel_gauge_driver_api *api = dev->api;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ret = api->get_property(dev, props + i);
|
||||
|
||||
err_count += ret ? 1 : 0;
|
||||
}
|
||||
|
||||
err_count = (err_count == len) ? -1 : err_count;
|
||||
|
||||
return err_count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -53,7 +53,7 @@ int main(void)
|
|||
}
|
||||
};
|
||||
|
||||
ret = fuel_gauge_get_prop(dev, props, ARRAY_SIZE(props));
|
||||
ret = fuel_gauge_get_props(dev, props, ARRAY_SIZE(props));
|
||||
if (ret < 0) {
|
||||
printk("Error: cannot get properties\n");
|
||||
} else {
|
||||
|
|
|
@ -40,7 +40,7 @@ ZTEST_USER_F(bq27z746, test_get_all_props_failed_returns_negative)
|
|||
},
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.",
|
||||
props[0].property_type);
|
||||
|
@ -66,7 +66,7 @@ ZTEST_USER_F(bq27z746, test_get_some_props_failed_returns_failed_prop_count)
|
|||
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.",
|
||||
props[0].property_type);
|
||||
|
@ -191,7 +191,7 @@ ZTEST_USER_F(bq27z746, test_get_props__returns_ok)
|
|||
},
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
/* All props shall have a good status */
|
||||
for (int i = 0; i < ARRAY_SIZE(props); i++) {
|
||||
|
|
|
@ -41,7 +41,7 @@ ZTEST_USER_F(max17048, test_get_all_props_failed_returns_negative)
|
|||
},
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.",
|
||||
props[0].property_type);
|
||||
|
@ -67,7 +67,7 @@ ZTEST_USER_F(max17048, test_get_some_props_failed_returns_failed_prop_count)
|
|||
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.",
|
||||
props[0].property_type);
|
||||
|
@ -101,7 +101,7 @@ ZTEST_USER_F(max17048, test_get_props__returns_ok)
|
|||
}
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(props); i++) {
|
||||
zassert_ok(props[i].status, "Property %d getting %d has a bad status.", i,
|
||||
|
@ -128,7 +128,7 @@ ZTEST_USER_F(max17048, test_current_rate_zero)
|
|||
* it will cause a division by zero
|
||||
*/
|
||||
emul_max17048_set_crate_status(0);
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(props); i++) {
|
||||
zassert_ok(props[i].status, "Property %d getting %d has a bad status.", i,
|
||||
|
|
|
@ -41,7 +41,7 @@ ZTEST_USER_F(sbs_gauge_new_api, test_get_all_props_failed_returns_negative)
|
|||
},
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.",
|
||||
props[0].property_type);
|
||||
|
@ -67,7 +67,7 @@ ZTEST_USER_F(sbs_gauge_new_api, test_get_some_props_failed_returns_failed_prop_c
|
|||
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
zassert_equal(props[0].status, -ENOTSUP, "Getting bad property %d has a good status.",
|
||||
props[0].property_type);
|
||||
|
@ -184,7 +184,7 @@ ZTEST_USER_F(sbs_gauge_new_api, test_set_prop_can_be_get)
|
|||
set_props[i].property_type);
|
||||
}
|
||||
|
||||
zassert_ok(fuel_gauge_get_prop(fixture->dev, get_props, ARRAY_SIZE(get_props)));
|
||||
zassert_ok(fuel_gauge_get_props(fixture->dev, get_props, ARRAY_SIZE(get_props)));
|
||||
for (int i = 0; i < ARRAY_SIZE(get_props); i++) {
|
||||
zassert_ok(get_props[i].status, "Property %d getting %d has a bad status.", i,
|
||||
get_props[i].property_type);
|
||||
|
@ -276,7 +276,7 @@ ZTEST_USER_F(sbs_gauge_new_api, test_get_props__returns_ok)
|
|||
},
|
||||
};
|
||||
|
||||
int ret = fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props));
|
||||
int ret = fuel_gauge_get_props(fixture->dev, props, ARRAY_SIZE(props));
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(props); i++) {
|
||||
zassert_ok(props[i].status, "Property %d getting %d has a bad status.", i,
|
||||
|
@ -350,26 +350,25 @@ ZTEST_USER_F(sbs_gauge_new_api, test_charging_5v_3a)
|
|||
uint32_t expected_uV = 5000 * 1000;
|
||||
uint32_t expected_uA = 3000 * 1000;
|
||||
|
||||
struct fuel_gauge_property props[] = {
|
||||
{
|
||||
.property_type = FUEL_GAUGE_VOLTAGE,
|
||||
},
|
||||
{
|
||||
.property_type = FUEL_GAUGE_CURRENT,
|
||||
},
|
||||
struct fuel_gauge_property voltage = {
|
||||
.property_type = FUEL_GAUGE_VOLTAGE,
|
||||
};
|
||||
struct fuel_gauge_property current = {
|
||||
.property_type = FUEL_GAUGE_CURRENT,
|
||||
};
|
||||
|
||||
zassume_ok(emul_fuel_gauge_set_battery_charging(fixture->sbs_fuel_gauge, expected_uV,
|
||||
expected_uA));
|
||||
zassert_ok(fuel_gauge_get_prop(fixture->dev, props, ARRAY_SIZE(props)));
|
||||
zassert_ok(fuel_gauge_get_prop(fixture->dev, &voltage));
|
||||
zassert_ok(fuel_gauge_get_prop(fixture->dev, ¤t));
|
||||
|
||||
zassert_ok(props[0].status);
|
||||
zassert_equal(props[0].value.voltage, expected_uV, "Got %d instead of %d",
|
||||
props[0].value.voltage, expected_uV);
|
||||
zassert_ok(voltage.status);
|
||||
zassert_equal(voltage.value.voltage, expected_uV, "Got %d instead of %d",
|
||||
voltage.value.voltage, expected_uV);
|
||||
|
||||
zassert_ok(props[1].status);
|
||||
zassert_equal(props[1].value.current, expected_uA, "Got %d instead of %d",
|
||||
props[1].value.current, expected_uA);
|
||||
zassert_ok(current.status);
|
||||
zassert_equal(current.value.current, expected_uA, "Got %d instead of %d",
|
||||
current.value.current, expected_uA);
|
||||
}
|
||||
|
||||
ZTEST_SUITE(sbs_gauge_new_api, NULL, sbs_gauge_new_api_setup, NULL, NULL, NULL);
|
||||
|
|
Loading…
Reference in a new issue