Skip to content

Commit 66c568e

Browse files
Peter Rowleynashif
authored andcommitted
drivers: fuel_gauge: sbs_gauge: Add support for buffer registers
The buffer registers (chemistry, manufacturer name, device name) were not implemented. Implemented by adding a new api interface for retrieving buffer properties. fuel_gauge_get_block_property has been added, and uses a memory buffer allocated in the app in order to store the fuel gauge information. Signed-off-by: Peter Rowley <[email protected]>
1 parent 251f269 commit 66c568e

File tree

6 files changed

+230
-4
lines changed

6 files changed

+230
-4
lines changed

drivers/fuel_gauge/fuel_gauge_syscall_handlers.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright 2023 Google LLC
3+
* Copyright 2023 Microsoft Corporation
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -46,3 +47,26 @@ static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev,
4647
}
4748

4849
#include <syscalls/fuel_gauge_set_prop_mrsh.c>
50+
51+
static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev,
52+
struct fuel_gauge_get_buffer_property *prop,
53+
void *dst, size_t dst_len)
54+
{
55+
struct fuel_gauge_get_buffer_property k_prop;
56+
57+
Z_OOPS(Z_SYSCALL_DRIVER_FUEL_GAUGE(dev, get_buffer_property));
58+
59+
Z_OOPS(z_user_from_copy(&k_prop, prop,
60+
sizeof(struct fuel_gauge_get_buffer_property)));
61+
62+
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(dst, dst_len));
63+
64+
int ret = z_impl_fuel_gauge_get_buffer_prop(dev, &k_prop, dst, dst_len);
65+
66+
Z_OOPS(z_user_to_copy(prop, &k_prop,
67+
sizeof(struct fuel_gauge_get_buffer_property)));
68+
69+
return ret;
70+
}
71+
72+
#include <syscalls/fuel_gauge_get_buffer_prop_mrsh.c>

drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright 2022 Google LLC
3+
* Copyright 2023 Microsoft Corporation
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*
@@ -20,6 +21,7 @@ LOG_MODULE_REGISTER(sbs_sbs_gauge);
2021
#include <zephyr/drivers/i2c.h>
2122
#include <zephyr/drivers/i2c_emul.h>
2223
#include <zephyr/sys/byteorder.h>
24+
#include <zephyr/drivers/fuel_gauge.h>
2325

2426
#include "sbs_gauge.h"
2527

@@ -119,6 +121,37 @@ static int emul_sbs_gauge_reg_read(const struct emul *target, int reg, int *val)
119121
return 0;
120122
}
121123

124+
static int emul_sbs_gauge_buffer_read(const struct emul *target, int reg, char *val)
125+
{
126+
char mfg[] = "ACME";
127+
char dev[] = "B123456";
128+
char chem[] = "LiPO";
129+
struct sbs_gauge_manufacturer_name *mfg_name = (struct sbs_gauge_manufacturer_name *)val;
130+
struct sbs_gauge_device_name *dev_name = (struct sbs_gauge_device_name *)val;
131+
struct sbs_gauge_device_chemistry *dev_chem = (struct sbs_gauge_device_chemistry *)val;
132+
133+
switch (reg) {
134+
case SBS_GAUGE_CMD_MANUFACTURER_NAME:
135+
mfg_name->manufacturer_name_length = sizeof(mfg);
136+
memcpy(mfg_name->manufacturer_name, mfg, mfg_name->manufacturer_name_length);
137+
break;
138+
case SBS_GAUGE_CMD_DEVICE_NAME:
139+
dev_name->device_name_length = sizeof(dev);
140+
memcpy(dev_name->device_name, dev, dev_name->device_name_length);
141+
break;
142+
143+
case SBS_GAUGE_CMD_DEVICE_CHEMISTRY:
144+
dev_chem->device_chemistry_length = sizeof(chem);
145+
memcpy(dev_chem->device_chemistry, chem, dev_chem->device_chemistry_length);
146+
break;
147+
default:
148+
LOG_ERR("Unknown register 0x%x read", reg);
149+
return -EIO;
150+
}
151+
152+
return 0;
153+
}
154+
122155
static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs,
123156
int num_msgs, int addr)
124157
{
@@ -148,8 +181,8 @@ static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg
148181
/* Now process the 'read' part of the message */
149182
msgs++;
150183
if (msgs->flags & I2C_MSG_READ) {
151-
switch (msgs->len - 1) {
152-
case 1:
184+
switch (msgs->len) {
185+
case 2:
153186
rc = emul_sbs_gauge_reg_read(target, reg, &val);
154187
if (rc) {
155188
/* Return before writing bad value to message buffer */
@@ -158,6 +191,11 @@ static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg
158191

159192
/* SBS uses SMBus, which sends data in little-endian format. */
160193
sys_put_le16(val, msgs->buf);
194+
break;
195+
/* buffer properties */
196+
case (sizeof(struct sbs_gauge_manufacturer_name)):
197+
case (sizeof(struct sbs_gauge_device_chemistry)):
198+
rc = emul_sbs_gauge_buffer_read(target, reg, (char *)msgs->buf);
161199
break;
162200
default:
163201
LOG_ERR("Unexpected msg1 length %d", msgs->len);

drivers/fuel_gauge/sbs_gauge/sbs_gauge.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) 2022 Leica Geosystems AG
33
*
44
* Copyright 2022 Google LLC
5+
* Copyright 2023 Microsoft Corporation
56
*
67
* SPDX-License-Identifier: Apache-2.0
78
*/
@@ -45,6 +46,22 @@ static int sbs_cmd_reg_write(const struct device *dev, uint8_t reg_addr, uint16_
4546
return i2c_burst_write_dt(&config->i2c, reg_addr, buf, sizeof(buf));
4647
}
4748

49+
static int sbs_cmd_buffer_read(const struct device *dev, uint8_t reg_addr, char *buffer,
50+
const uint8_t buffer_size)
51+
{
52+
const struct sbs_gauge_config *cfg;
53+
int status;
54+
55+
cfg = dev->config;
56+
status = i2c_burst_read_dt(&cfg->i2c, reg_addr, buffer, buffer_size);
57+
if (status < 0) {
58+
LOG_ERR("Unable to read register");
59+
return status;
60+
}
61+
62+
return 0;
63+
}
64+
4865
static int sbs_gauge_get_prop(const struct device *dev, struct fuel_gauge_get_property *prop)
4966
{
5067
int rc = 0;
@@ -196,6 +213,45 @@ static int sbs_gauge_set_prop(const struct device *dev, struct fuel_gauge_set_pr
196213
return rc;
197214
}
198215

216+
static int sbs_gauge_get_buffer_prop(const struct device *dev,
217+
struct fuel_gauge_get_buffer_property *prop, void *dst,
218+
size_t dst_len)
219+
{
220+
int rc = 0;
221+
222+
switch (prop->property_type) {
223+
case FUEL_GAUGE_MANUFACTURER_NAME:
224+
if (dst_len == sizeof(struct sbs_gauge_manufacturer_name)) {
225+
rc = sbs_cmd_buffer_read(dev, SBS_GAUGE_CMD_MANUFACTURER_NAME, (char *)dst,
226+
dst_len);
227+
} else {
228+
rc = -EINVAL;
229+
}
230+
break;
231+
case FUEL_GAUGE_DEVICE_NAME:
232+
if (dst_len == sizeof(struct sbs_gauge_device_name)) {
233+
rc = sbs_cmd_buffer_read(dev, SBS_GAUGE_CMD_DEVICE_NAME, (char *)dst,
234+
dst_len);
235+
} else {
236+
rc = -EINVAL;
237+
}
238+
break;
239+
case FUEL_GAUGE_DEVICE_CHEMISTRY:
240+
if (dst_len == sizeof(struct sbs_gauge_device_chemistry)) {
241+
rc = sbs_cmd_buffer_read(dev, SBS_GAUGE_CMD_DEVICE_CHEMISTRY, (char *)dst,
242+
dst_len);
243+
} else {
244+
rc = -EINVAL;
245+
}
246+
break;
247+
default:
248+
rc = -ENOTSUP;
249+
}
250+
251+
prop->status = rc;
252+
return rc;
253+
}
254+
199255
static int sbs_gauge_get_props(const struct device *dev, struct fuel_gauge_get_property *props,
200256
size_t len)
201257
{
@@ -250,6 +306,7 @@ static int sbs_gauge_init(const struct device *dev)
250306
static const struct fuel_gauge_driver_api sbs_gauge_driver_api = {
251307
.get_property = &sbs_gauge_get_props,
252308
.set_property = &sbs_gauge_set_props,
309+
.get_buffer_property = &sbs_gauge_get_buffer_prop,
253310
};
254311

255312
/* FIXME: fix init priority */

drivers/fuel_gauge/sbs_gauge/sbs_gauge.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#define SBS_GAUGE_CMD_SN 0x1C /* SerialNumber */
4343
#define SBS_GAUGE_CMD_MANUFACTURER_NAME 0x20 /* ManufacturerName */
4444
#define SBS_GAUGE_CMD_DEVICE_NAME 0x21 /* DeviceName */
45-
#define SBS_GAUGE_CMD_DEVICE_CHEM 0x22 /* DeviceChemistry */
45+
#define SBS_GAUGE_CMD_DEVICE_CHEMISTRY 0x22 /* DeviceChemistry */
4646
#define SBS_GAUGE_CMD_MANUFACTURER_DATA 0x23 /* ManufacturerData */
4747

4848
#define SBS_GAUGE_DELAY 1000

include/zephyr/drivers/fuel_gauge.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright 2022 Google LLC
3+
* Copyright 2023 Microsoft Corporation
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -90,9 +91,15 @@ extern "C" {
9091
#define FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM FUEL_GAUGE_SBS_ATRATE_OK + 1
9192
/** Remaining Time Alarm (minutes) */
9293
#define FUEL_GAUGE_SBS_REMAINING_TIME_ALARM FUEL_GAUGE_SBS_REMAINING_CAPACITY_ALARM + 1
94+
/** Manufacturer of pack (1 byte length + 20 bytes data) */
95+
#define FUEL_GAUGE_MANUFACTURER_NAME FUEL_GAUGE_SBS_REMAINING_TIME_ALARM + 1
96+
/** Name of pack (1 byte length + 20 bytes data) */
97+
#define FUEL_GAUGE_DEVICE_NAME FUEL_GAUGE_MANUFACTURER_NAME + 1
98+
/** Chemistry (1 byte length + 4 bytes data) */
99+
#define FUEL_GAUGE_DEVICE_CHEMISTRY FUEL_GAUGE_DEVICE_NAME + 1
93100

94101
/** Reserved to demark end of common fuel gauge properties */
95-
#define FUEL_GAUGE_COMMON_COUNT FUEL_GAUGE_DESIGN_VOLTAGE + 1
102+
#define FUEL_GAUGE_COMMON_COUNT FUEL_GAUGE_DEVICE_CHEMISTRY + 1
96103
/**
97104
* Reserved to demark downstream custom properties - use this value as the actual value may change
98105
* over future versions of this API
@@ -198,6 +205,37 @@ struct fuel_gauge_set_property {
198205
} value;
199206
};
200207

208+
/** Buffer properties are separated due to size */
209+
struct fuel_gauge_get_buffer_property {
210+
/** Battery fuel gauge property to get */
211+
uint16_t property_type;
212+
213+
/** Negative error status set by callee e.g. -ENOTSUP for an unsupported property */
214+
int status;
215+
};
216+
217+
/**
218+
* Data structures for reading SBS buffer properties
219+
*/
220+
#define SBS_GAUGE_MANUFACTURER_NAME_MAX_SIZE 20
221+
#define SBS_GAUGE_DEVICE_NAME_MAX_SIZE 20
222+
#define SBS_GAUGE_DEVICE_CHEMISTRY_MAX_SIZE 4
223+
224+
struct sbs_gauge_manufacturer_name {
225+
uint8_t manufacturer_name_length;
226+
char manufacturer_name[SBS_GAUGE_MANUFACTURER_NAME_MAX_SIZE];
227+
} __packed;
228+
229+
struct sbs_gauge_device_name {
230+
uint8_t device_name_length;
231+
char device_name[SBS_GAUGE_DEVICE_NAME_MAX_SIZE];
232+
} __packed;
233+
234+
struct sbs_gauge_device_chemistry {
235+
uint8_t device_chemistry_length;
236+
char device_chemistry[SBS_GAUGE_DEVICE_CHEMISTRY_MAX_SIZE];
237+
} __packed;
238+
201239
/**
202240
* @typedef fuel_gauge_get_property_t
203241
* @brief Callback API for getting a fuel_gauge property.
@@ -216,11 +254,23 @@ typedef int (*fuel_gauge_get_property_t)(const struct device *dev,
216254
typedef int (*fuel_gauge_set_property_t)(const struct device *dev,
217255
struct fuel_gauge_set_property *props, size_t props_len);
218256

257+
/**
258+
* @typedef fuel_gauge_get_buffer_property_t
259+
* @brief Callback API for getting a fuel_gauge buffer property.
260+
*
261+
* See fuel_gauge_get_buffer_property() for argument description
262+
*/
263+
typedef int (*fuel_gauge_get_buffer_property_t)(const struct device *dev,
264+
struct fuel_gauge_get_buffer_property *prop,
265+
void *dst, size_t dst_len);
266+
267+
219268
/* Caching is entirely on the onus of the client */
220269

221270
__subsystem struct fuel_gauge_driver_api {
222271
fuel_gauge_get_property_t get_property;
223272
fuel_gauge_set_property_t set_property;
273+
fuel_gauge_get_buffer_property_t get_buffer_property;
224274
};
225275

226276
/**
@@ -280,6 +330,35 @@ static inline int z_impl_fuel_gauge_set_prop(const struct device *dev,
280330
return api->set_property(dev, props, props_len);
281331
}
282332

333+
/**
334+
* @brief Fetch a battery fuel-gauge buffer property
335+
*
336+
* @param dev Pointer to the battery fuel-gauge device
337+
* @param prop pointer to single fuel_gauge_get_buffer_property struct where the property struct
338+
* field is set by the caller to determine what property is read from the
339+
* fuel gauge device into the dst field.
340+
* @param dst byte array or struct that will hold the buffer data that is read from the fuel gauge
341+
* @param dst_len the length of the destination array in bytes
342+
*
343+
* @return return=0 if successful, return < 0 if getting property failed, return 0 on success
344+
*/
345+
__syscall int fuel_gauge_get_buffer_prop(const struct device *dev,
346+
struct fuel_gauge_get_buffer_property *prop, void *dst,
347+
size_t dst_len);
348+
349+
static inline int z_impl_fuel_gauge_get_buffer_prop(const struct device *dev,
350+
struct fuel_gauge_get_buffer_property *prop,
351+
void *dst, size_t dst_len)
352+
{
353+
const struct fuel_gauge_driver_api *api = (const struct fuel_gauge_driver_api *)dev->api;
354+
355+
if (api->get_buffer_property == NULL) {
356+
return -ENOSYS;
357+
}
358+
359+
return api->get_buffer_property(dev, prop, dst, dst_len);
360+
}
361+
283362
/**
284363
* @}
285364
*/

tests/drivers/fuel_gauge/sbs_gauge/src/test_sbs_gauge.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright 2022 Google LLC
3+
* Copyright 2023 Microsoft Corporation
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -317,4 +318,31 @@ ZTEST_USER_F(sbs_gauge_new_api, test_set_props__returns_ok)
317318
zassert_ok(ret);
318319
}
319320

321+
322+
ZTEST_USER_F(sbs_gauge_new_api, test_get_buffer_props__returns_ok)
323+
{
324+
/* Validate what properties are supported by the driver */
325+
struct fuel_gauge_get_buffer_property prop;
326+
struct sbs_gauge_manufacturer_name mfg_name;
327+
struct sbs_gauge_device_name dev_name;
328+
struct sbs_gauge_device_chemistry chem;
329+
int ret;
330+
331+
prop.property_type = FUEL_GAUGE_MANUFACTURER_NAME;
332+
ret = fuel_gauge_get_buffer_prop(fixture->dev, &prop, &mfg_name, sizeof(mfg_name));
333+
zassert_ok(prop.status, "Property %d has a bad status.", prop.property_type);
334+
zassert_ok(ret);
335+
336+
prop.property_type = FUEL_GAUGE_DEVICE_NAME;
337+
ret = fuel_gauge_get_buffer_prop(fixture->dev, &prop, &dev_name, sizeof(dev_name));
338+
zassert_ok(prop.status, "Property %d has a bad status.", prop.property_type);
339+
zassert_ok(ret);
340+
341+
prop.property_type = FUEL_GAUGE_DEVICE_CHEMISTRY;
342+
ret = fuel_gauge_get_buffer_prop(fixture->dev, &prop, &chem, sizeof(chem));
343+
zassert_ok(prop.status, "Property %d has a bad status.", prop.property_type);
344+
zassert_ok(ret);
345+
}
346+
347+
320348
ZTEST_SUITE(sbs_gauge_new_api, NULL, sbs_gauge_new_api_setup, NULL, NULL, NULL);

0 commit comments

Comments
 (0)