sensing: support multiple sensor types in one device

Many sensors have multiple functions, for example, icm42688 supports
accel, gyro and temperature, and the sensor streaming api always mixes
the multiple functions in one function call. So we need add a layer in
sensing subsystem to dispatch the result returned from sensor streaming
api for each function.
I changed the sensor-type(int) to sensor-types(array) in sensing sensor
device bindings, so that one device can map to multiple instances of
sensing sensor.

Signed-off-by: Zhang Lixu <lixu.zhang@intel.com>
This commit is contained in:
Zhang Lixu 2023-11-27 14:28:56 +08:00 committed by Carles Cufí
parent 91774cb0eb
commit f5595b4b9c
6 changed files with 81 additions and 113 deletions

View file

@ -7,8 +7,8 @@ description: Sensing subsystem sensor common properties bindings.
include: sensor-device.yaml
properties:
sensor-type:
type: int
sensor-types:
type: array
required: true
description: sensor type id (follow HID spec definition)
@ -24,6 +24,10 @@ properties:
type: phandles
description: sensor reporters
reporters-index:
type: array
description: the index in sensor-types of reporter if the reporter support multiple sensor-types
stream-mode:
type: boolean
description: sensor works on stream mode or poll mode

View file

@ -112,82 +112,78 @@ struct sensing_sensor {
struct sensing_connection *conns;
};
#define PHANDLE_DEVICE_BY_IDX(idx, node, prop) \
DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node, prop, idx))
#define SENSING_SENSOR_INFO_NAME(node, idx) \
_CONCAT(_CONCAT(__sensing_sensor_info_, idx), DEVICE_DT_NAME_GET(node))
#define PHANDLE_DEVICE_LIST(node, prop) \
{ \
LISTIFY(DT_PROP_LEN_OR(node, prop, 0), \
PHANDLE_DEVICE_BY_IDX, \
(,), \
node, \
prop) \
}
#define SENSING_SENSOR_INFO_NAME(node) \
_CONCAT(__sensing_sensor_info_, DEVICE_DT_NAME_GET(node))
#define SENSING_SENSOR_INFO_DEFINE(node) \
#define SENSING_SENSOR_INFO_DEFINE(node, idx) \
const static STRUCT_SECTION_ITERABLE(sensing_sensor_info, \
SENSING_SENSOR_INFO_NAME(node)) = { \
.type = DT_PROP(node, sensor_type), \
SENSING_SENSOR_INFO_NAME(node, idx)) = { \
.type = DT_PROP_BY_IDX(node, sensor_types, idx), \
.name = DT_NODE_FULL_NAME(node), \
.friendly_name = DT_PROP(node, friendly_name), \
.vendor = DT_NODE_VENDOR_OR(node, NULL), \
.model = DT_NODE_MODEL_OR(node, NULL), \
.minimal_interval = DT_PROP(node, minimal_interval), \
.minimal_interval = DT_PROP(node, minimal_interval),\
};
#define SENSING_CONNECTIONS_NAME(node) \
_CONCAT(__sensing_connections, DEVICE_DT_NAME_GET(node))
#define SENSING_CONNECTIONS_NAME(node, idx) \
_CONCAT(_CONCAT(__sensing_connections_, idx), DEVICE_DT_NAME_GET(node))
#define SENSING_SENSOR_SOURCE_NAME(idx, node) \
SENSING_SENSOR_NAME(DT_PHANDLE_BY_IDX(node, reporters, idx), \
DT_PROP_BY_IDX(node, reporters_index, idx))
#define SENSING_SENSOR_SOURCE_EXTERN(idx, node) \
extern struct sensing_sensor SENSING_SENSOR_NAME(DT_PHANDLE_BY_IDX(node, reporters, idx));
extern struct sensing_sensor SENSING_SENSOR_SOURCE_NAME(idx, node); \
#define SENSING_CONNECTION_INITIALIZER(source_node, cb_list_ptr) \
#define SENSING_CONNECTION_INITIALIZER(source_name, cb_list_ptr) \
{ \
.callback_list = *cb_list_ptr, \
.source = &SENSING_SENSOR_NAME(source_node), \
.source = &source_name, \
}
#define SENSING_CONNECTION_DEFINE(idx, node, cb_list_ptr) \
SENSING_CONNECTION_INITIALIZER(DT_PHANDLE_BY_IDX(node, reporters, idx), cb_list_ptr)
#define SENSING_CONNECTION_DEFINE(idx, node, cb_list_ptr) \
SENSING_CONNECTION_INITIALIZER(SENSING_SENSOR_SOURCE_NAME(idx, node), \
cb_list_ptr)
#define SENSING_CONNECTIONS_DEFINE(node, num, cb_list_ptr) \
#define SENSING_CONNECTIONS_DEFINE(node, idx, num, cb_list_ptr) \
LISTIFY(num, SENSING_SENSOR_SOURCE_EXTERN, \
(), node) \
static struct sensing_connection \
SENSING_CONNECTIONS_NAME(node)[(num)] = { \
SENSING_CONNECTIONS_NAME(node, idx)[(num)] = { \
LISTIFY(num, SENSING_CONNECTION_DEFINE, \
(,), node, cb_list_ptr) \
};
#define SENSING_SENSOR_IODEV_NAME(node) \
_CONCAT(__sensing_iodev_, DEVICE_DT_NAME_GET(node))
#define SENSING_SENSOR_IODEV_NAME(node, idx) \
_CONCAT(_CONCAT(__sensing_iodev_, idx), DEVICE_DT_NAME_GET(node))
#define SENSING_SENSOR_IODEV_DEFINE(node) \
#define SENSING_SENSOR_IODEV_DEFINE(node, idx) \
COND_CODE_1(DT_PROP(node, stream_mode), \
(SENSOR_DT_STREAM_IODEV(SENSING_SENSOR_IODEV_NAME(node), node)), \
(SENSOR_DT_READ_IODEV(SENSING_SENSOR_IODEV_NAME(node), node)));
(SENSOR_DT_STREAM_IODEV(SENSING_SENSOR_IODEV_NAME(node, idx), node)), \
(SENSOR_DT_READ_IODEV(SENSING_SENSOR_IODEV_NAME(node, idx), node)));
#define SENSING_SENSOR_NAME(node) \
_CONCAT(__sensing_sensor_, DEVICE_DT_NAME_GET(node))
#define SENSING_SENSOR_NAME(node, idx) \
_CONCAT(_CONCAT(__sensing_sensor_, idx), DEVICE_DT_NAME_GET(node))
#define SENSING_SENSOR_DEFINE(node, reg_ptr, cb_list_ptr) \
SENSING_SENSOR_INFO_DEFINE(node) \
SENSING_CONNECTIONS_DEFINE(node, \
#define SENSING_SENSOR_DEFINE(node, prop, idx, reg_ptr, cb_list_ptr) \
SENSING_SENSOR_INFO_DEFINE(node, idx) \
SENSING_CONNECTIONS_DEFINE(node, idx, \
DT_PROP_LEN_OR(node, reporters, 0), cb_list_ptr)\
SENSING_SENSOR_IODEV_DEFINE(node) \
SENSING_SENSOR_IODEV_DEFINE(node, idx) \
STRUCT_SECTION_ITERABLE(sensing_sensor, \
SENSING_SENSOR_NAME(node)) = { \
SENSING_SENSOR_NAME(node, idx)) = { \
.dev = DEVICE_DT_GET(node), \
.info = &SENSING_SENSOR_INFO_NAME(node), \
.info = &SENSING_SENSOR_INFO_NAME(node, idx), \
.register_info = reg_ptr, \
.reporter_num = DT_PROP_LEN_OR(node, reporters, 0), \
.conns = SENSING_CONNECTIONS_NAME(node), \
.iodev = &SENSING_SENSOR_IODEV_NAME(node), \
.conns = SENSING_CONNECTIONS_NAME(node, idx), \
.iodev = &SENSING_SENSOR_IODEV_NAME(node, idx), \
};
#define SENSING_SENSORS_DEFINE(node, reg_ptr, cb_list_ptr) \
DT_FOREACH_PROP_ELEM_VARGS(node, sensor_types, \
SENSING_SENSOR_DEFINE, reg_ptr, cb_list_ptr)
/**
* @brief Like SENSOR_DEVICE_DT_DEFINE() with sensing specifics.
*
@ -217,7 +213,7 @@ extern struct sensing_sensor SENSING_SENSOR_NAME(DT_PHANDLE_BY_IDX(node, reporte
* @param api_ptr Provides an initial pointer to the API function struct used
* by the driver. Can be NULL.
*/
#define SENSING_SENSOR_DT_DEFINE(node_id, reg_ptr, cb_list_ptr, \
#define SENSING_SENSORS_DT_DEFINE(node_id, reg_ptr, cb_list_ptr, \
init_fn, pm_device, \
data_ptr, cfg_ptr, level, prio, \
api_ptr, ...) \
@ -225,19 +221,19 @@ extern struct sensing_sensor SENSING_SENSOR_NAME(DT_PHANDLE_BY_IDX(node, reporte
data_ptr, cfg_ptr, level, prio, \
api_ptr, __VA_ARGS__); \
\
SENSING_SENSOR_DEFINE(node_id, reg_ptr, cb_list_ptr);
SENSING_SENSORS_DEFINE(node_id, reg_ptr, cb_list_ptr);
/**
* @brief Like SENSING_SENSOR_DT_DEFINE() for an instance of a DT_DRV_COMPAT
* @brief Like SENSING_SENSORS_DT_DEFINE() for an instance of a DT_DRV_COMPAT
* compatible
*
* @param inst instance number. This is replaced by
* <tt>DT_DRV_COMPAT(inst)</tt> in the call to SENSING_SENSOR_DT_DEFINE().
* <tt>DT_DRV_COMPAT(inst)</tt> in the call to SENSING_SENSORS_DT_DEFINE().
*
* @param ... other parameters as expected by SENSING_SENSOR_DT_DEFINE().
* @param ... other parameters as expected by SENSING_SENSORS_DT_DEFINE().
*/
#define SENSING_SENSOR_DT_INST_DEFINE(inst, reg_ptr, cb_list_ptr, ...) \
SENSING_SENSOR_DT_DEFINE(DT_DRV_INST(inst), reg_ptr, \
#define SENSING_SENSORS_DT_INST_DEFINE(inst, reg_ptr, cb_list_ptr, ...) \
SENSING_SENSORS_DT_DEFINE(DT_DRV_INST(inst), reg_ptr, \
cb_list_ptr, __VA_ARGS__)
/**

View file

@ -4,6 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/sensing/sensing_sensor_types.h>
&i2c0 {
bmi160_i2c: bmi@68 {
compatible = "bosch,bmi160";
@ -24,20 +26,20 @@
compatible = "zephyr,sensing";
status = "okay";
base_accel: base-accel {
base_accel_gyro: base-accel-gyro {
compatible = "zephyr,sensing-phy-3d-sensor";
status = "okay";
sensor-type = <0x73>;
friendly-name = "Base Accelerometer Sensor";
sensor-types = <SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D>;
friendly-name = "Base Accel Gyro Sensor";
minimal-interval = <625>;
underlying-device = <&bmi160_i2c>;
};
lid_accel: lid-accel {
lid_accel_gyro: lid-accel-gyro {
compatible = "zephyr,sensing-phy-3d-sensor";
status = "okay";
sensor-type = <0x73>;
friendly-name = "Lid Accelerometer Sensor";
sensor-types = <SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D>;
friendly-name = "Lid Accel Gyro Sensor";
minimal-interval = <625>;
underlying-device = <&bmi160_spi>;
};
@ -45,9 +47,10 @@
hinge_angle: hinge-angle {
compatible = "zephyr,sensing-hinge-angle";
status = "okay";
sensor-type = <0x20B>;
sensor-types = <SENSING_SENSOR_TYPE_MOTION_HINGE_ANGLE>;
friendly-name = "Hinge Angle Sensor";
reporters = <&base_accel &lid_accel>;
reporters = <&base_accel_gyro &lid_accel_gyro>;
reporters-index = <0 0>;
minimal-interval = <100000>;
stream-mode;
};

View file

@ -43,20 +43,17 @@ int main(void)
const struct sensing_callback_list base_acc_cb_list = {
.on_data_event = &acc_data_event_callback,
};
const struct sensing_callback_list lid_acc_cb_list = {
.on_data_event = &acc_data_event_callback,
};
const struct sensing_callback_list hinge_angle_cb_list = {
.on_data_event = &hinge_angle_data_event_callback,
};
const struct sensing_sensor_info *info;
sensing_sensor_handle_t base_acc;
sensing_sensor_handle_t lid_acc;
sensing_sensor_handle_t hinge_angle;
struct sensing_sensor_config base_acc_config;
struct sensing_sensor_config lid_acc_config;
struct sensing_sensor_config hinge_angle_config;
const struct sensing_sensor_info *tmp_sensor_info;
const struct sensing_sensor_info *tmp_sensor_info = NULL;
const struct sensing_sensor_info *accle_info = NULL;
const struct sensing_sensor_info *hinge_info = NULL;
int ret, i, num = 0;
ret = sensing_get_sensors(&num, &info);
@ -71,25 +68,27 @@ int main(void)
info[i].name,
info[i].friendly_name,
info[i].type);
switch (info[i].type) {
case SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D:
accle_info = &info[i];
break;
case SENSING_SENSOR_TYPE_MOTION_HINGE_ANGLE:
hinge_info = &info[i];
break;
default:
break;
}
}
LOG_INF("sensing subsystem run successfully");
ret = sensing_open_sensor(&info[0], &base_acc_cb_list, &base_acc);
ret = sensing_open_sensor(accle_info, &base_acc_cb_list, &base_acc);
if (ret) {
LOG_ERR("sensing_open_sensor, type:0x%x index:0 error:%d",
SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D, ret);
}
ret = sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_NODELABEL(lid_accel)),
&lid_acc_cb_list,
&lid_acc);
if (ret) {
LOG_ERR("sensing_open_sensor_by_dt, type:0x%x index:1 error:%d",
SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D, ret);
}
ret = sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_NODELABEL(hinge_angle)),
&hinge_angle_cb_list,
ret = sensing_open_sensor(hinge_info, &hinge_angle_cb_list,
&hinge_angle);
if (ret) {
LOG_ERR("sensing_open_sensor_by_type, type:0x%x index:0 error:%d",
@ -104,13 +103,6 @@ int main(void)
LOG_ERR("base_acc sensing_set_interval error:%d\n", ret);
}
lid_acc_config.attri = SENSING_SENSOR_ATTRIBUTE_INTERVAL;
lid_acc_config.interval = 100 * USEC_PER_MSEC;
ret = sensing_set_config(lid_acc, &lid_acc_config, 1);
if (ret) {
LOG_ERR("lid_acc sensing_set_interval error:%d\n", ret);
}
tmp_sensor_info = sensing_get_sensor_info(hinge_angle);
hinge_angle_config.attri = SENSING_SENSOR_ATTRIBUTE_INTERVAL;
hinge_angle_config.interval = tmp_sensor_info->minimal_interval;
@ -120,7 +112,6 @@ int main(void)
}
memset(&base_acc_config, 0x00, sizeof(struct sensing_sensor_config));
memset(&lid_acc_config, 0x00, sizeof(struct sensing_sensor_config));
memset(&hinge_angle_config, 0x00, sizeof(struct sensing_sensor_config));
/* get base acc, lid acc, hinge sensor interval */
@ -130,12 +121,6 @@ int main(void)
LOG_ERR("base_acc sensing_get_interval error:%d\n", ret);
}
lid_acc_config.attri = SENSING_SENSOR_ATTRIBUTE_INTERVAL;
ret = sensing_get_config(lid_acc, &lid_acc_config, 1);
if (ret) {
LOG_ERR("lid_acc sensing_get_interval error:%d\n", ret);
}
hinge_angle_config.attri = SENSING_SENSOR_ATTRIBUTE_INTERVAL;
ret = sensing_get_config(hinge_angle, &hinge_angle_config, 1);
if (ret) {
@ -151,14 +136,6 @@ int main(void)
LOG_ERR("base_acc sensing_set_sensitivity error:%d\n", ret);
}
lid_acc_config.attri = SENSING_SENSOR_ATTRIBUTE_SENSITIVITY;
lid_acc_config.data_field = SENSING_SENSITIVITY_INDEX_ALL;
lid_acc_config.sensitivity = 0;
ret = sensing_set_config(lid_acc, &lid_acc_config, 1);
if (ret) {
LOG_ERR("lid_acc sensing_set_sensitivity error:%d\n", ret);
}
hinge_angle_config.attri = SENSING_SENSOR_ATTRIBUTE_SENSITIVITY;
hinge_angle_config.data_field = SENSING_SENSITIVITY_INDEX_ALL;
hinge_angle_config.sensitivity = 1;
@ -168,7 +145,6 @@ int main(void)
}
memset(&base_acc_config, 0x00, sizeof(struct sensing_sensor_config));
memset(&lid_acc_config, 0x00, sizeof(struct sensing_sensor_config));
memset(&hinge_angle_config, 0x00, sizeof(struct sensing_sensor_config));
/* get base acc, lid acc, hinge sensor sensitivity */
@ -179,13 +155,6 @@ int main(void)
LOG_ERR("base_acc sensing_get_sensitivity error:%d\n", ret);
}
lid_acc_config.attri = SENSING_SENSOR_ATTRIBUTE_SENSITIVITY;
lid_acc_config.data_field = SENSING_SENSITIVITY_INDEX_ALL;
ret = sensing_get_config(lid_acc, &lid_acc_config, 1);
if (ret) {
LOG_ERR("lid_acc sensing_get_sensitivity error:%d\n", ret);
}
hinge_angle_config.attri = SENSING_SENSOR_ATTRIBUTE_SENSITIVITY;
hinge_angle_config.data_field = SENSING_SENSITIVITY_INDEX_ALL;
ret = sensing_get_config(hinge_angle, &hinge_angle_config, 1);
@ -193,10 +162,5 @@ int main(void)
LOG_ERR("hinge_angle sensing_get_sensitivity error:%d\n", ret);
}
ret = sensing_close_sensor(&lid_acc);
if (ret) {
LOG_ERR("sensing_close_sensor:%p error:%d", lid_acc, ret);
}
return 0;
}

View file

@ -157,7 +157,7 @@ static void hinge_reporter_on_data_event(sensing_sensor_handle_t handle,
.on_data_event = hinge_reporter_on_data_event, \
.context = &_CONCAT(hinge_ctx, _inst), \
}; \
SENSING_SENSOR_DT_INST_DEFINE(_inst, &hinge_reg, \
SENSING_SENSORS_DT_INST_DEFINE(_inst, &hinge_reg, \
&_CONCAT(hinge_cb, _inst), \
&hinge_init, NULL, \
&_CONCAT(hinge_ctx, _inst), NULL, \

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "zephyr/devicetree.h"
#define DT_DRV_COMPAT zephyr_sensing_phy_3d_sensor
#include <stdlib.h>
@ -250,9 +251,9 @@ static const struct sensing_sensor_register_info phy_3d_sensor_reg = {
.hw_dev = DEVICE_DT_GET( \
DT_PHANDLE(DT_DRV_INST(_inst), \
underlying_device)), \
.sensor_type = DT_PROP(DT_DRV_INST(_inst), sensor_type),\
.sensor_type = DT_PROP_BY_IDX(DT_DRV_INST(_inst), sensor_types, 0),\
}; \
SENSING_SENSOR_DT_INST_DEFINE(_inst, &phy_3d_sensor_reg, NULL, \
SENSING_SENSORS_DT_INST_DEFINE(_inst, &phy_3d_sensor_reg, NULL, \
&phy_3d_sensor_init, NULL, \
&_CONCAT(data, _inst), &_CONCAT(cfg, _inst), \
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \