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