1 /*
2  * Copyright (c) 2023 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/sys/__assert.h>
7 #include <zephyr/devicetree.h>
8 #include <zephyr/drivers/sensor.h>
9 #include <zephyr/init.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/rtio/rtio.h>
12 #include <zephyr/sensing/sensing.h>
13 #include <zephyr/sensing/sensing_sensor.h>
14 #include <zephyr/logging/log.h>
15 #include <stdlib.h>
16 #include "sensor_mgmt.h"
17 
18 #define DT_DRV_COMPAT zephyr_sensing
19 
20 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
21 	     "only one 'zephyr_sensing' compatible node may be present");
22 
23 LOG_MODULE_REGISTER(sensing, CONFIG_SENSING_LOG_LEVEL);
24 
25 static struct sensing_context sensing_ctx = {
26 };
27 RTIO_DEFINE_WITH_MEMPOOL(sensing_rtio_ctx, CONFIG_SENSING_RTIO_SQE_NUM,
28 		CONFIG_SENSING_RTIO_CQE_NUM,
29 		CONFIG_SENSING_RTIO_BLOCK_COUNT,
30 		CONFIG_SENSING_RTIO_BLOCK_SIZE, 4);
31 
sensing_sensor_type_to_chan(const int32_t type)32 static enum sensor_channel sensing_sensor_type_to_chan(const int32_t type)
33 {
34 	switch (type) {
35 	case SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D:
36 		return SENSOR_CHAN_ACCEL_XYZ;
37 	case SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D:
38 		return SENSOR_CHAN_GYRO_XYZ;
39 	default:
40 		break;
41 	}
42 
43 	return SENSOR_CHAN_PRIV_START;
44 }
45 
46 /* sensor_later_config including arbitrate/set interval/sensitivity
47  */
arbitrate_interval(struct sensing_sensor * sensor)48 static uint32_t arbitrate_interval(struct sensing_sensor *sensor)
49 {
50 	struct sensing_connection *conn;
51 	uint32_t min_interval = UINT32_MAX;
52 	uint32_t interval;
53 
54 	/* search from all clients, arbitrate the interval */
55 	for_each_client_conn(sensor, conn) {
56 		LOG_INF("arbitrate interval, sensor:%s for each conn:%p, interval:%d(us)",
57 			sensor->dev->name, conn, conn->interval);
58 		if (!is_client_request_data(conn)) {
59 			continue;
60 		}
61 		if (conn->interval < min_interval) {
62 			min_interval = conn->interval;
63 		}
64 	}
65 	/* min_interval == UINT32_MAX means sensor is not opened by any clients,
66 	 * then interval should be 0
67 	 */
68 	interval = (min_interval == UINT32_MAX ? 0 : min_interval);
69 
70 	LOG_DBG("arbitrate interval, sensor:%s, interval:%d(us)",
71 			sensor->dev->name, interval);
72 
73 	return interval;
74 }
75 
set_arbitrate_interval(struct sensing_sensor * sensor,uint32_t interval)76 static int set_arbitrate_interval(struct sensing_sensor *sensor, uint32_t interval)
77 {
78 	struct sensing_submit_config *config = sensor->iodev->data;
79 	struct sensor_value odr = {0};
80 	int ret;
81 
82 	__ASSERT(sensor && sensor->dev, "set arbitrate interval, sensor or sensor device is NULL");
83 
84 	LOG_INF("set arbitrate interval:%d, sensor:%s, is_streaming:%d",
85 			interval, sensor->dev->name, config->is_streaming);
86 
87 	if (interval) {
88 		odr.val1 = USEC_PER_SEC / interval;
89 		odr.val2 = (uint64_t)USEC_PER_SEC * 1000000 / interval % 1000000;
90 	}
91 
92 	ret = sensor_attr_set(sensor->dev, config->chan,
93 			SENSOR_ATTR_SAMPLING_FREQUENCY, &odr);
94 	if (ret) {
95 		LOG_ERR("%s set attr freq failed:%d", sensor->dev->name, ret);
96 		return ret;
97 	}
98 
99 	if (sensor->interval) {
100 		if (config->is_streaming) {
101 			rtio_sqe_cancel(sensor->stream_sqe);
102 		} else {
103 			k_timer_stop(&sensor->timer);
104 		}
105 	}
106 
107 	if (interval) {
108 		if (config->is_streaming) {
109 			ret = sensor_stream(sensor->iodev, &sensing_rtio_ctx,
110 					sensor, &sensor->stream_sqe);
111 		} else {
112 			k_timer_start(&sensor->timer, K_USEC(interval),
113 					K_USEC(interval));
114 		}
115 	}
116 
117 	sensor->interval = interval;
118 
119 	return ret;
120 }
121 
config_interval(struct sensing_sensor * sensor)122 static int config_interval(struct sensing_sensor *sensor)
123 {
124 	uint32_t interval = arbitrate_interval(sensor);
125 
126 	LOG_INF("config interval, sensor:%s, interval:%d", sensor->dev->name, interval);
127 
128 	return set_arbitrate_interval(sensor, interval);
129 }
130 
arbitrate_sensitivity(struct sensing_sensor * sensor,int index)131 static uint32_t arbitrate_sensitivity(struct sensing_sensor *sensor, int index)
132 {
133 	struct sensing_connection *conn;
134 	uint32_t min_sensitivity = UINT32_MAX;
135 
136 	/* search from all clients, arbitrate the sensitivity */
137 	for_each_client_conn(sensor, conn) {
138 		LOG_DBG("arbitrate sensitivity, sensor:%s for each conn:%p, idx:%d, sens:%d",
139 				sensor->dev->name, conn, index,
140 				conn->sensitivity[index]);
141 		if (!is_client_request_data(conn)) {
142 			continue;
143 		}
144 		if (conn->sensitivity[index] < min_sensitivity) {
145 			min_sensitivity = conn->sensitivity[index];
146 		}
147 	}
148 	LOG_DBG("arbitrate sensitivity, sensor:%s, min_sensitivity:%d",
149 		sensor->dev->name, min_sensitivity);
150 
151 	/* min_sensitivity == UINT32_MAX means no client is requesting to open sensor,
152 	 * by any client, in this case, return sensitivity 0
153 	 */
154 	return (min_sensitivity == UINT32_MAX ? 0 : min_sensitivity);
155 }
156 
set_arbitrate_sensitivity(struct sensing_sensor * sensor,int index,uint32_t sensitivity)157 static int set_arbitrate_sensitivity(struct sensing_sensor *sensor, int index, uint32_t sensitivity)
158 {
159 	struct sensing_submit_config *config = (struct sensing_submit_config *)sensor->iodev->data;
160 	struct sensor_value threshold = {.val1 = sensitivity};
161 	int i;
162 
163 	/* update sensor sensitivity */
164 	sensor->sensitivity[index] = sensitivity;
165 
166 	for (i = 0; i < sensor->sensitivity_count; i++) {
167 		threshold.val1 = MIN(sensor->sensitivity[i], threshold.val1);
168 	}
169 
170 	return sensor_attr_set(sensor->dev, config->chan,
171 			SENSOR_ATTR_HYSTERESIS, &threshold);
172 }
173 
config_sensitivity(struct sensing_sensor * sensor,int index)174 static int config_sensitivity(struct sensing_sensor *sensor, int index)
175 {
176 	uint32_t sensitivity = arbitrate_sensitivity(sensor, index);
177 
178 	LOG_INF("config sensitivity, sensor:%s, index:%d, sensitivity:%d",
179 		sensor->dev->name, index, sensitivity);
180 
181 	return set_arbitrate_sensitivity(sensor, index, sensitivity);
182 }
183 
config_sensor(struct sensing_sensor * sensor)184 static int config_sensor(struct sensing_sensor *sensor)
185 {
186 	int ret;
187 	int i = 0;
188 
189 	ret = config_interval(sensor);
190 	if (ret) {
191 		LOG_WRN("sensor:%s config interval error", sensor->dev->name);
192 	}
193 
194 	for (i = 0; i < sensor->sensitivity_count; i++) {
195 		ret = config_sensitivity(sensor, i);
196 		if (ret) {
197 			LOG_WRN("sensor:%s config sensitivity index:%d error:%d",
198 					sensor->dev->name, i, ret);
199 		}
200 	}
201 
202 	return ret;
203 }
204 
sensor_later_config(void)205 static void sensor_later_config(void)
206 {
207 	LOG_INF("sensor later config begin...");
208 
209 	for_each_sensor_reverse(sensor) {
210 		if (atomic_test_and_clear_bit(&sensor->flag, SENSOR_LATER_CFG_BIT)) {
211 			LOG_INF("sensor later config, sensor:%s",
212 				sensor->dev->name);
213 			config_sensor(sensor);
214 		}
215 	}
216 }
217 
sensing_runtime_thread(void * p1,void * p2,void * p3)218 static void sensing_runtime_thread(void *p1, void *p2, void *p3)
219 {
220 	struct sensing_context *ctx = p1;
221 	int ret;
222 
223 	LOG_INF("sensing runtime thread start...");
224 
225 	do {
226 		ret = k_sem_take(&ctx->event_sem, K_FOREVER);
227 		if (!ret) {
228 			if (atomic_test_and_clear_bit(&ctx->event_flag, EVENT_CONFIG_READY)) {
229 				LOG_INF("runtime thread triggered by EVENT_CONFIG_READY");
230 				sensor_later_config();
231 			}
232 		}
233 	} while (1);
234 }
235 
save_config_and_notify(struct sensing_sensor * sensor)236 static void save_config_and_notify(struct sensing_sensor *sensor)
237 {
238 	struct sensing_context *ctx = &sensing_ctx;
239 
240 	__ASSERT(sensor, "save config and notify, sensing_sensor not be NULL");
241 
242 	LOG_INF("save config and notify, sensor:%s", sensor->dev->name);
243 
244 	/* remember sensor_later_config bit to sensor */
245 	atomic_set_bit(&sensor->flag, SENSOR_LATER_CFG_BIT);
246 
247 	/*remember event config ready and notify sensing_runtime_thread */
248 	atomic_set_bit(&ctx->event_flag, EVENT_CONFIG_READY);
249 
250 	k_sem_give(&ctx->event_sem);
251 }
252 
set_sensor_state(struct sensing_sensor * sensor,enum sensing_sensor_state state)253 static int set_sensor_state(struct sensing_sensor *sensor, enum sensing_sensor_state state)
254 {
255 	__ASSERT(sensor, "set sensor state, sensing_sensor is NULL");
256 
257 	sensor->state = state;
258 
259 	return 0;
260 }
261 
init_connection(struct sensing_connection * conn,struct sensing_sensor * source,struct sensing_sensor * sink)262 static void init_connection(struct sensing_connection *conn,
263 			    struct sensing_sensor *source,
264 			    struct sensing_sensor *sink)
265 {
266 	__ASSERT(conn, "init each connection, invalid connection");
267 
268 	if (source) {
269 		conn->source = source;
270 	}
271 
272 	if (sink) {
273 		conn->sink = sink;
274 	}
275 
276 	conn->interval = 0;
277 	memset(conn->sensitivity, 0x00, sizeof(conn->sensitivity));
278 	/* link connection to its reporter's client_list */
279 	sys_slist_append(&conn->source->client_list, &conn->snode);
280 }
281 
sensing_sensor_polling_timer(struct k_timer * timer_id)282 static void sensing_sensor_polling_timer(struct k_timer *timer_id)
283 {
284 	struct sensing_sensor *sensor = CONTAINER_OF(timer_id,
285 			struct sensing_sensor, timer);
286 
287 	/* TODO: move it into sensing_runtime_thread */
288 	sensor_read(sensor->iodev, &sensing_rtio_ctx, sensor);
289 }
290 
init_sensor(struct sensing_sensor * sensor)291 static int init_sensor(struct sensing_sensor *sensor)
292 {
293 	struct sensing_submit_config *config;
294 	struct sensing_connection *conn;
295 	int i;
296 
297 	__ASSERT(sensor && sensor->dev, "init sensor, sensor or sensor device is NULL");
298 
299 	k_timer_init(&sensor->timer, sensing_sensor_polling_timer, NULL);
300 	sys_slist_init(&sensor->client_list);
301 
302 	for (i = 0; i < sensor->reporter_num; i++) {
303 		conn = &sensor->conns[i];
304 
305 		/* source sensor has been assigned in compile time */
306 		init_connection(conn, NULL, sensor);
307 
308 		LOG_INF("init sensor, reporter:%s, client:%s, connection:%d(%p)",
309 			conn->source->dev->name, sensor->dev->name, i, conn);
310 	}
311 
312 	config = sensor->iodev->data;
313 	config->chan = sensing_sensor_type_to_chan(sensor->info->type);
314 
315 	return 0;
316 }
317 
sensing_init(const struct device * dev)318 static int sensing_init(const struct device *dev)
319 {
320 	struct sensing_context *ctx = dev->data;
321 	enum sensing_sensor_state state;
322 	int ret = 0;
323 
324 	LOG_INF("sensing init begin...");
325 
326 	for_each_sensor(sensor) {
327 		ret = init_sensor(sensor);
328 		if (ret) {
329 			LOG_ERR("sensor:%s initial error", sensor->dev->name);
330 		}
331 		state = (ret ? SENSING_SENSOR_STATE_OFFLINE : SENSING_SENSOR_STATE_READY);
332 		ret = set_sensor_state(sensor, state);
333 		if (ret) {
334 			LOG_ERR("set sensor:%s state:%d error", sensor->dev->name, state);
335 		}
336 		LOG_INF("sensing init, sensor:%s, state:%d", sensor->dev->name, sensor->state);
337 	}
338 
339 	k_sem_init(&ctx->event_sem, 0, 1);
340 
341 	LOG_INF("create sensing runtime thread ok");
342 	ctx->sensing_initialized = true;
343 
344 	return ret;
345 }
346 
open_sensor(struct sensing_sensor * sensor,struct sensing_connection ** conn)347 int open_sensor(struct sensing_sensor *sensor, struct sensing_connection **conn)
348 {
349 	struct sensing_connection *tmp_conn;
350 
351 	if (sensor->state != SENSING_SENSOR_STATE_READY) {
352 		return -EINVAL;
353 	}
354 
355 	/* create connection from sensor to application(client = NULL) */
356 	tmp_conn = malloc(sizeof(*tmp_conn));
357 	if (!tmp_conn) {
358 		return -ENOMEM;
359 	}
360 
361 	init_connection(tmp_conn, sensor, NULL);
362 
363 	*conn = tmp_conn;
364 
365 	return 0;
366 }
367 
close_sensor(struct sensing_connection ** conn)368 int close_sensor(struct sensing_connection **conn)
369 {
370 	struct sensing_connection *tmp_conn = *conn;
371 
372 	if (tmp_conn == NULL) {
373 		LOG_ERR("connection should not be NULL");
374 		return -EINVAL;
375 	}
376 
377 	__ASSERT(!tmp_conn->sink, "sensor derived from device tree cannot be closed");
378 
379 	__ASSERT(tmp_conn->source, "reporter should not be NULL");
380 
381 	sys_slist_find_and_remove(&tmp_conn->source->client_list, &tmp_conn->snode);
382 
383 	save_config_and_notify(tmp_conn->source);
384 
385 	free(*conn);
386 	*conn = NULL;
387 
388 	return 0;
389 }
390 
sensing_register_callback(struct sensing_connection * conn,struct sensing_callback_list * cb_list)391 int sensing_register_callback(struct sensing_connection *conn,
392 			      struct sensing_callback_list *cb_list)
393 {
394 	if (conn == NULL) {
395 		LOG_ERR("register sensing callback list, connection not be NULL");
396 		return -ENODEV;
397 	}
398 
399 	__ASSERT(!conn->sink, "only connection to application could register sensing callback");
400 
401 	if (cb_list == NULL) {
402 		LOG_ERR("callback should not be NULL");
403 		return -ENODEV;
404 	}
405 	conn->callback_list = cb_list;
406 
407 	return 0;
408 }
409 
set_interval(struct sensing_connection * conn,uint32_t interval)410 int set_interval(struct sensing_connection *conn, uint32_t interval)
411 {
412 	LOG_INF("set interval, sensor:%s, interval:%u(us)", conn->source->dev->name, interval);
413 
414 	__ASSERT(conn && conn->source, "set interval, connection or reporter not be NULL");
415 
416 	if (interval > 0 && interval < conn->source->info->minimal_interval) {
417 		LOG_ERR("interval:%d(us) should no less than min interval:%d(us)",
418 					interval, conn->source->info->minimal_interval);
419 		return -EINVAL;
420 	}
421 
422 	conn->interval = interval;
423 	conn->next_consume_time = EXEC_TIME_INIT;
424 
425 	LOG_INF("set interval, sensor:%s, conn:%p, interval:%d",
426 		conn->source->dev->name, conn, interval);
427 
428 	save_config_and_notify(conn->source);
429 
430 	return 0;
431 }
432 
get_interval(struct sensing_connection * conn,uint32_t * interval)433 int get_interval(struct sensing_connection *conn, uint32_t *interval)
434 {
435 	__ASSERT(conn, "get interval, connection not be NULL");
436 	*interval = conn->interval;
437 
438 	LOG_INF("get interval, sensor:%s, interval:%u(us)", conn->source->dev->name, *interval);
439 
440 	return 0;
441 }
442 
set_sensitivity(struct sensing_connection * conn,int8_t index,uint32_t sensitivity)443 int set_sensitivity(struct sensing_connection *conn, int8_t index, uint32_t sensitivity)
444 {
445 	int i;
446 
447 	__ASSERT(conn && conn->source, "set sensitivity, connection or reporter not be NULL");
448 
449 	LOG_INF("set sensitivity, sensor:%s, index:%d, sensitivity:%d, count:%d",
450 		conn->source->dev->name, index,
451 		sensitivity, conn->source->sensitivity_count);
452 
453 	if (index < SENSING_SENSITIVITY_INDEX_ALL || index >= conn->source->sensitivity_count) {
454 		LOG_ERR("sensor:%s sensitivity index:%d invalid", conn->source->dev->name, index);
455 		return -EINVAL;
456 	}
457 
458 	if (index == SENSING_SENSITIVITY_INDEX_ALL) {
459 		for (i = 0; i < conn->source->sensitivity_count; i++) {
460 			conn->sensitivity[i] = sensitivity;
461 		}
462 	} else {
463 		conn->sensitivity[index] = sensitivity;
464 	}
465 
466 	return 0;
467 }
468 
get_sensitivity(struct sensing_connection * conn,int8_t index,uint32_t * sensitivity)469 int get_sensitivity(struct sensing_connection *conn, int8_t index, uint32_t *sensitivity)
470 {
471 	int i = 0;
472 
473 	__ASSERT(conn && conn->source, "get sensitivity, connection or reporter not be NULL");
474 
475 	*sensitivity = UINT32_MAX;
476 
477 	if (index < SENSING_SENSITIVITY_INDEX_ALL || index >= conn->source->sensitivity_count) {
478 		LOG_ERR("sensor:%s sensitivity index:%d invalid", conn->source->dev->name, index);
479 		return -EINVAL;
480 	}
481 
482 	if (index == SENSING_SENSITIVITY_INDEX_ALL) {
483 		/* each sensitivity index value should be same for global sensitivity */
484 		for (i = 1; i < conn->source->sensitivity_count; i++) {
485 			if (conn->sensitivity[i] != conn->sensitivity[0]) {
486 				LOG_ERR("sensitivity[%d]:%d should be same as sensitivity:%d",
487 					i, conn->sensitivity[i], conn->sensitivity[0]);
488 				return -EINVAL;
489 			}
490 		}
491 		*sensitivity = conn->sensitivity[0];
492 	} else {
493 		*sensitivity = conn->sensitivity[index];
494 	}
495 
496 	LOG_INF("get_sensitivity, sensor:%s, index:%d, sensitivity:%d, count:%d",
497 		conn->source->dev->name, index,
498 		*sensitivity, conn->source->sensitivity_count);
499 
500 	return 0;
501 }
502 
sensing_get_sensors(int * sensor_nums,const struct sensing_sensor_info ** info)503 int sensing_get_sensors(int *sensor_nums, const struct sensing_sensor_info **info)
504 {
505 	if (info == NULL) {
506 		LOG_ERR("sensing_sensor_info should not be NULL");
507 		return -ENODEV;
508 	}
509 
510 	STRUCT_SECTION_COUNT(sensing_sensor_info, sensor_nums);
511 
512 	STRUCT_SECTION_GET(sensing_sensor_info, 0, info);
513 
514 	return 0;
515 }
516 
517 K_THREAD_DEFINE(sensing_runtime, CONFIG_SENSING_RUNTIME_THREAD_STACK_SIZE, sensing_runtime_thread,
518 		&sensing_ctx, NULL, NULL, CONFIG_SENSING_RUNTIME_THREAD_PRIORITY, 0, 0);
519 
520 DEVICE_DT_INST_DEFINE(0, sensing_init, NULL, &sensing_ctx, NULL, POST_KERNEL,
521 		      CONFIG_SENSOR_INIT_PRIORITY, NULL);
522