1 /*
2  * Copyright (c) 2022-2023 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_SENSING_SENSOR_H_
8 #define ZEPHYR_INCLUDE_SENSING_SENSOR_H_
9 
10 #include <stdbool.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/sensor.h>
13 #include <zephyr/sensing/sensing.h>
14 
15 /**
16  * @defgroup sensing_sensor Sensing Sensor API
17  * @ingroup sensing
18  * @defgroup sensing_sensor_callbacks Sensor Callbacks
19  * @ingroup sensing_sensor
20  */
21 
22 /**
23  * @brief Sensing Sensor API
24  * @addtogroup sensing_sensor
25  * @{
26  */
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /**
33  * @brief Sensor registration information
34  *
35  */
36 struct sensing_sensor_register_info {
37 	/**
38 	 * Sensor flags
39 	 */
40 	uint16_t flags;
41 
42 	/**
43 	 * Sample size in bytes for a single sample of the registered sensor.
44 	 * sensing runtime need this information for internal buffer allocation.
45 	 */
46 	uint16_t sample_size;
47 
48 	/**
49 	 * The number of sensor sensitivities
50 	 */
51 	uint8_t sensitivity_count;
52 
53 	/**
54 	 * Sensor version.
55 	 * Version can be used to identify different versions of sensor implementation.
56 	 */
57 	struct sensing_sensor_version version;
58 };
59 
60 /** @cond INTERNAL_HIDDEN */
61 
62 /**
63  * @brief Enumeration for sensing subsystem event.
64  *
65  * This enumeration defines the various events used by the sensing subsystem.
66  */
67 enum {
68 	EVENT_CONFIG_READY, /**< Configuration is ready. */
69 };
70 
71 /**
72  * @brief Enumeration for sensor flag bit.
73  *
74  * This enumeration defines the bit for sensor flag.
75  */
76 enum {
77 	SENSOR_LATER_CFG_BIT, /**< Indicates if there is a configuration request pending. */
78 };
79 
80 /**
81  * @brief Connection between a source and sink of sensor data
82  */
83 struct sensing_connection {
84 	sys_snode_t snode;             /**< Node in the singly-linked list of connections. */
85 	struct sensing_sensor *source; /**< Source sensor of the connection. */
86 	struct sensing_sensor *sink;   /**< Sink sensor of the connection. */
87 	uint32_t interval;             /**< Report interval in micro seconds. */
88 	/** Sensitivity of the connection. */
89 	int sensitivity[CONFIG_SENSING_MAX_SENSITIVITY_COUNT];
90 	void *data;                 /**< Pointer to sensor sample data of the connection. */
91 	/** Next consume time of the connection. Unit is micro seconds. */
92 	uint64_t next_consume_time;
93 	struct sensing_callback_list *callback_list; /**< Callback list of the connection. */
94 };
95 
96 /**
97  * @brief Internal sensor instance data structure.
98  *
99  * Each sensor instance will have its unique data structure for storing all
100  * it's related information.
101  *
102  * Sensor management will enumerate all these instance data structures,
103  * build report relationship model base on them, etc.
104  */
105 struct sensing_sensor {
106 	const struct device *dev;               /**< Device of the sensor instance. */
107 	const struct sensing_sensor_info *info; /**< Info of the sensor instance. */
108 	/** Register info of the sensor instance. */
109 	const struct sensing_sensor_register_info *register_info;
110 	const uint16_t reporter_num; /**< Reporter number of the sensor instance. */
111 	sys_slist_t client_list;     /**< List of the sensor clients. */
112 	uint32_t interval;           /**< Report interval of the sensor sample in micro seconds. */
113 	uint8_t sensitivity_count;   /**< Sensitivity count of the sensor instance. */
114 	/** Sensitivity array of the sensor instance. */
115 	int sensitivity[CONFIG_SENSING_MAX_SENSITIVITY_COUNT];
116 	enum sensing_sensor_state state;  /**< State of the sensor instance. */
117 	struct rtio_iodev *iodev;         /**< Pointer to RTIO device of the sensor instance. */
118 	struct k_timer timer;             /**< Timer for non streaming mode */
119 	struct rtio_sqe *stream_sqe;      /**< Sqe for streaming mode. */
120 	atomic_t flag;                    /**< Sensor flag of the sensor instance. */
121 	struct sensing_connection *conns; /**< Pointer to sensor connections. */
122 };
123 
124 /**
125  * @brief Macro to generate a name for a sensor info structure.
126  *
127  * This macro generates a name for a sensor info structure based on a node and an index.
128  *
129  * @param node The devicetree node identifier.
130  * @param idx Logical index into the sensor-types array.
131  */
132 #define SENSING_SENSOR_INFO_NAME(node, idx)					\
133 	_CONCAT(_CONCAT(__sensing_sensor_info_, idx), DEVICE_DT_NAME_GET(node))
134 
135 /**
136  * @brief Macro to define a sensor info structure.
137  *
138  * This macro defines a sensor info structure based on a node and an index.
139  * The structure includes the type, name, friendly name, vendor, model, and minimal interval of the
140  * sensor.
141  *
142  * @param node The devicetree node identifier.
143  * @param idx Logical index into the sensor-types array.
144  */
145 #define SENSING_SENSOR_INFO_DEFINE(node, idx)				\
146 	const static STRUCT_SECTION_ITERABLE(sensing_sensor_info,	\
147 			SENSING_SENSOR_INFO_NAME(node, idx)) = {	\
148 		.type = DT_PROP_BY_IDX(node, sensor_types, idx),	\
149 		.name = DT_NODE_FULL_NAME(node),			\
150 		.friendly_name = DT_PROP(node, friendly_name),		\
151 		.vendor = DT_NODE_VENDOR_OR(node, NULL),		\
152 		.model = DT_NODE_MODEL_OR(node, NULL),			\
153 		.minimal_interval = DT_PROP(node, minimal_interval),	\
154 	};
155 
156 /**
157  * @brief Macro to generate a name for a connections array.
158  *
159  * This macro generates a name for a connections array based on a node.
160  *
161  * @param node The devicetree node identifier.
162  */
163 #define SENSING_CONNECTIONS_NAME(node)					\
164 	_CONCAT(__sensing_connections_, DEVICE_DT_NAME_GET(node))
165 
166 /**
167  * @brief Macro to generate a name for a sensor source.
168  *
169  * This macro generates a name for a sensor source based on an index and a node.
170  *
171  * @param idx Logical index into the reporters array.
172  * @param node The devicetree node identifier.
173  */
174 #define SENSING_SENSOR_SOURCE_NAME(idx, node)				\
175 	SENSING_SENSOR_NAME(DT_PHANDLE_BY_IDX(node, reporters, idx),	\
176 		DT_PROP_BY_IDX(node, reporters_index, idx))
177 
178 /**
179  * @brief Macro to declare an external sensor source.
180  *
181  * This macro declares an external sensor source based on an index and a node.
182  *
183  * @param idx Logical index into the reporters array.
184  * @param node The devicetree node identifier.
185  */
186 #define SENSING_SENSOR_SOURCE_EXTERN(idx, node)				\
187 extern struct sensing_sensor SENSING_SENSOR_SOURCE_NAME(idx, node);
188 
189 /**
190  * @brief Macro to initialize a connection.
191  *
192  * This macro initializes a connection with a source name and a callback list pointer.
193  *
194  * @param source_name The name of struct sensing_sensor for source sensor.
195  * @param cb_list_ptr Pointer to sensing callback list.
196  */
197 #define SENSING_CONNECTION_INITIALIZER(source_name, cb_list_ptr)	\
198 {									\
199 	.callback_list = cb_list_ptr,					\
200 	.source = &source_name,						\
201 }
202 
203 /**
204  * @brief Macro to define a connection.
205  *
206  * This macro defines a connection based on an index, a node, and a callback list pointer.
207  *
208  * @param idx Logical index into the reporters array.
209  * @param node The devicetree node identifier.
210  * @param cb_list_ptr Pointer to sensing callback list.
211  */
212 #define SENSING_CONNECTION_DEFINE(idx, node, cb_list_ptr)		\
213 	SENSING_CONNECTION_INITIALIZER(SENSING_SENSOR_SOURCE_NAME(idx, node), \
214 				       cb_list_ptr)
215 
216 /**
217  * @brief Macro to define an array of connections.
218  *
219  * This macro defines an array of connections based on a node, a number, and a callback list
220  * pointer.
221  *
222  * @param node The devicetree node identifier.
223  * @param num The number of the connections.
224  * @param cb_list_ptr Pointer to sensing callback list.
225  */
226 #define SENSING_CONNECTIONS_DEFINE(node, num, cb_list_ptr)		\
227 	LISTIFY(num, SENSING_SENSOR_SOURCE_EXTERN,			\
228 				(), node)				\
229 	static struct sensing_connection				\
230 			SENSING_CONNECTIONS_NAME(node)[(num)] = {	\
231 		LISTIFY(num, SENSING_CONNECTION_DEFINE,			\
232 				(,), node, cb_list_ptr)			\
233 	};
234 
235 /**
236  * @brief Structure for sensor submit configuration.
237  *
238  * This structure represents a sensor submit configuration. It includes the channel, info index, and
239  * streaming flag.
240  */
241 struct sensing_submit_config {
242 	enum sensor_channel chan; /**< Channel of the sensor to submit. */
243 	const int info_index;     /**< Logical index into the sensor-types array. */
244 	const bool is_streaming;  /**< Working in streaming mode or not. */
245 };
246 
247 /**
248  * @brief External declaration for the sensing I/O device API.
249  *
250  * This external declaration represents the sensing I/O device API.
251  */
252 extern const struct rtio_iodev_api __sensing_iodev_api;
253 
254 /**
255  * @brief Macro to generate a name for a submit configuration.
256  *
257  * This macro generates a name for a submit configuration based on a node and an index.
258  *
259  * @param node The devicetree node identifier.
260  * @param idx Logical index into the sensor-types array.
261  */
262 #define SENSING_SUBMIT_CFG_NAME(node, idx)						\
263 	_CONCAT(_CONCAT(__sensing_submit_cfg_, idx), DEVICE_DT_NAME_GET(node))
264 
265 /**
266  * @brief Macro to generate a name for a sensor I/O device.
267  *
268  * This macro generates a name for a sensor I/O device based on a node and an index.
269  *
270  * @param node The devicetree node identifier.
271  * @param idx Logical index into the sensor-types array.
272  */
273 #define SENSING_SENSOR_IODEV_NAME(node, idx)						\
274 	_CONCAT(_CONCAT(__sensing_iodev_, idx), DEVICE_DT_NAME_GET(node))
275 
276 /**
277  * @brief Macro to define a sensor I/O device.
278  *
279  * This macro defines a sensor I/O device based on a node and an index.
280  * The device includes a submit configuration with a streaming flag and an info index.
281  *
282  * @param node The devicetree node identifier.
283  * @param idx Logical index into the sensor-types array.
284  */
285 #define SENSING_SENSOR_IODEV_DEFINE(node, idx)						\
286 	static struct sensing_submit_config SENSING_SUBMIT_CFG_NAME(node, idx) = {	\
287 		.is_streaming = DT_PROP(node, stream_mode),				\
288 		.info_index = idx,							\
289 	};										\
290 	RTIO_IODEV_DEFINE(SENSING_SENSOR_IODEV_NAME(node, idx),				\
291 			  &__sensing_iodev_api,						\
292 			  &SENSING_SUBMIT_CFG_NAME(node, idx));
293 
294 /**
295  * @brief Macro to generate a name for a sensor.
296  *
297  * This macro generates a name for a sensor based on a node and an index.
298  *
299  * @param node The devicetree node identifier.
300  * @param idx Logical index into the sensor-types array.
301  */
302 #define SENSING_SENSOR_NAME(node, idx)					\
303 	_CONCAT(_CONCAT(__sensing_sensor_, idx), DEVICE_DT_NAME_GET(node))
304 
305 /**
306  * @brief Macro to define a sensor.
307  *
308  * This macro defines a sensor based on a node, a property, an index, a register info pointer, and a
309  * callback list pointer. The sensor includes a device, info, register info, reporter number,
310  * connections, and an I/O device.
311  *
312  * @param node The devicetree node identifier.
313  * @param prop property name.
314  * @param idx Logical index into the sensor-types array.
315  * @param reg_ptr Pointer to the device's sensing_sensor_register_info.
316  * @param cb_list_ptr Pointer to sensing callback list.
317  */
318 #define SENSING_SENSOR_DEFINE(node, prop, idx, reg_ptr, cb_list_ptr)	\
319 	SENSING_SENSOR_INFO_DEFINE(node, idx)				\
320 	SENSING_SENSOR_IODEV_DEFINE(node, idx)				\
321 	STRUCT_SECTION_ITERABLE(sensing_sensor,				\
322 				SENSING_SENSOR_NAME(node, idx)) = {	\
323 		.dev = DEVICE_DT_GET(node),				\
324 		.info = &SENSING_SENSOR_INFO_NAME(node, idx),		\
325 		.register_info = reg_ptr,				\
326 		.reporter_num = DT_PROP_LEN_OR(node, reporters, 0),	\
327 		.conns = SENSING_CONNECTIONS_NAME(node),		\
328 		.iodev = &SENSING_SENSOR_IODEV_NAME(node, idx),		\
329 	};
330 
331 /**
332  * @brief Macro to define sensors.
333  *
334  * This macro defines sensors based on a node, a register info pointer, and a callback list pointer.
335  * It uses the DT_FOREACH_PROP_ELEM_VARGS macro to define each sensor.
336  *
337  * @param node The devicetree node identifier.
338  * @param reg_ptr Pointer to the device's sensing_sensor_register_info.
339  * @param cb_list_ptr Pointer to sensing callback list.
340  */
341 #define SENSING_SENSORS_DEFINE(node, reg_ptr, cb_list_ptr)		\
342 	DT_FOREACH_PROP_ELEM_VARGS(node, sensor_types,			\
343 			SENSING_SENSOR_DEFINE, reg_ptr, cb_list_ptr)
344 
345 /** @endcond */
346 
347 /**
348  * @brief Like SENSOR_DEVICE_DT_DEFINE() with sensing specifics.
349  *
350  * @details Defines a sensor which implements the sensor API. May define an
351  * element in the sensing sensor iterable section used to enumerate all sensing
352  * sensors.
353  *
354  * @param node The devicetree node identifier.
355  * @param reg_ptr Pointer to the device's sensing_sensor_register_info.
356  * @param cb_list_ptr Pointer to sensing callback list.
357  * @param init_fn Name of the init function of the driver.
358  * @param pm_device PM device resources reference (NULL if device does not use
359  * PM).
360  * @param data_ptr Pointer to the device's private data.
361  * @param cfg_ptr The address to the structure containing the configuration
362  * information for this instance of the driver.
363  * @param level The initialization level. See SYS_INIT() for details.
364  * @param prio Priority within the selected initialization level. See
365  * SYS_INIT() for details.
366  * @param api_ptr Provides an initial pointer to the API function struct used
367  * by the driver. Can be NULL.
368  */
369 #define SENSING_SENSORS_DT_DEFINE(node, reg_ptr, cb_list_ptr,	\
370 				init_fn, pm_device,			\
371 				data_ptr, cfg_ptr, level, prio,		\
372 				api_ptr, ...)				\
373 	SENSOR_DEVICE_DT_DEFINE(node, init_fn, pm_device,		\
374 				data_ptr, cfg_ptr, level, prio,		\
375 				api_ptr, __VA_ARGS__);			\
376 	SENSING_CONNECTIONS_DEFINE(node,				\
377 				   DT_PROP_LEN_OR(node, reporters, 0),	\
378 				   cb_list_ptr);			\
379 	SENSING_SENSORS_DEFINE(node, reg_ptr, cb_list_ptr);
380 
381 /**
382  * @brief Like SENSING_SENSORS_DT_DEFINE() for an instance of a DT_DRV_COMPAT
383  * compatible
384  *
385  * @param inst instance number. This is replaced by
386  * <tt>DT_DRV_COMPAT(inst)</tt> in the call to SENSING_SENSORS_DT_DEFINE().
387  * @param ... other parameters as expected by SENSING_SENSORS_DT_DEFINE().
388  */
389 #define SENSING_SENSORS_DT_INST_DEFINE(inst, ...)	\
390 	SENSING_SENSORS_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
391 
392 /**
393  * @brief Get reporter handles	of a given sensor instance by sensor type.
394  *
395  * @param dev The sensor instance device structure.
396  * @param type The given type, \ref SENSING_SENSOR_TYPE_ALL to get reporters
397  * with all types.
398  * @param max_handles The max count of the \p reporter_handles array input. Can
399  * get real count number via \ref sensing_sensor_get_reporters_count
400  * @param reporter_handles Input handles array for receiving found reporter
401  * sensor instances
402  * @return number of reporters found, 0 returned if not found.
403  */
404 int sensing_sensor_get_reporters(
405 		const struct device *dev, int type,
406 		sensing_sensor_handle_t *reporter_handles, int max_handles);
407 
408 /**
409  * @brief Get reporters count of a given sensor instance by sensor type.
410  *
411  * @param dev The sensor instance device structure.
412  * @param type The sensor type for checking, \ref SENSING_SENSOR_TYPE_ALL
413  * @return Count of reporters by \p type, 0 returned if no reporters by \p type.
414  */
415 int sensing_sensor_get_reporters_count(
416 		const struct device *dev, int type);
417 
418 /**
419  * @brief Get this sensor's state
420  *
421  * @param dev The sensor instance device structure.
422  * @param state Returned sensor state value
423  * @return 0 on success or negative error value on failure.
424  */
425 int sensing_sensor_get_state(
426 		const struct device *dev,
427 		enum sensing_sensor_state *state);
428 
429 /**
430  * @}
431  */
432 
433 #ifdef __cplusplus
434 }
435 #endif
436 
437 #endif /*ZEPHYR_INCLUDE_SENSING_SENSOR_H_*/
438