/* * Copyright (c) 2022 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include "sensor_mgmt.h" LOG_MODULE_DECLARE(sensing, CONFIG_SENSING_LOG_LEVEL); /* check whether it is right time for client to consume this sample */ static inline bool sensor_test_consume_time(struct sensing_sensor *sensor, struct sensing_connection *conn, uint64_t cur_time) { LOG_DBG("sensor:%s next_consume_time:%lld cur_time:%lld", sensor->dev->name, conn->next_consume_time, cur_time); return conn->next_consume_time <= cur_time; } static void update_client_consume_time(struct sensing_sensor *sensor, struct sensing_connection *conn) { uint32_t interval = conn->interval; if (conn->next_consume_time == 0) { conn->next_consume_time = get_us(); } conn->next_consume_time += interval; } /* send data to clients based on interval and sensitivity */ static int send_data_to_clients(struct sensing_sensor *sensor, void *data) { struct sensing_sensor *client; struct sensing_connection *conn; for_each_client_conn(sensor, conn) { client = conn->sink; LOG_DBG("sensor:%s send data to client:%p", conn->source->dev->name, conn); if (!is_client_request_data(conn)) { continue; } /* sensor_test_consume_time(), check whether time is ready or not: * true: it's time for client consuming the data * false: client time not arrived yet, not consume the data */ if (!sensor_test_consume_time(sensor, conn, get_us())) { continue; } update_client_consume_time(sensor, conn); if (!conn->callback_list->on_data_event) { LOG_WRN("sensor:%s event callback not registered", conn->source->dev->name); continue; } conn->callback_list->on_data_event(conn, data, conn->callback_list->context); } return 0; } STRUCT_SECTION_START_EXTERN(sensing_sensor); STRUCT_SECTION_END_EXTERN(sensing_sensor); static void dispatch_task(void *a, void *b, void *c) { uint8_t *data = NULL; uint32_t data_len = 0; int rc; int get_data_rc; ARG_UNUSED(a); ARG_UNUSED(b); ARG_UNUSED(c); if (IS_ENABLED(CONFIG_USERSPACE) && !k_is_user_context()) { rtio_access_grant(&sensing_rtio_ctx, k_current_get()); k_thread_user_mode_enter(dispatch_task, a, b, c); } while (true) { struct rtio_cqe cqe; rc = rtio_cqe_copy_out(&sensing_rtio_ctx, &cqe, 1, K_FOREVER); if (rc < 1) { continue; } /* Cache the data from the CQE */ rc = cqe.result; /* Get the associated data */ get_data_rc = rtio_cqe_get_mempool_buffer(&sensing_rtio_ctx, &cqe, &data, &data_len); if (get_data_rc != 0 || data_len == 0) { continue; } if ((uintptr_t)cqe.userdata >= (uintptr_t)STRUCT_SECTION_START(sensing_sensor) && (uintptr_t)cqe.userdata < (uintptr_t)STRUCT_SECTION_END(sensing_sensor)) { struct sensing_sensor *sensor = cqe.userdata; send_data_to_clients(sensor, data); } rtio_release_buffer(&sensing_rtio_ctx, data, data_len); } } K_THREAD_DEFINE(sensing_dispatch, CONFIG_SENSING_DISPATCH_THREAD_STACK_SIZE, dispatch_task, NULL, NULL, NULL, CONFIG_SENSING_DISPATCH_THREAD_PRIORITY, 0, 0);