1 /*
2  * Copyright (c) 2023 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/kernel.h>
12 
13 #include "sensor_shell.h"
14 
15 /* Create a single common config for streaming */
16 static struct sensor_stream_trigger iodev_sensor_shell_trigger;
17 static struct sensor_read_config iodev_sensor_shell_stream_config = {
18 	.sensor = NULL,
19 	.is_streaming = true,
20 	.triggers = &iodev_sensor_shell_trigger,
21 	.count = 0,
22 	.max = 1,
23 };
24 RTIO_IODEV_DEFINE(iodev_sensor_shell_stream, &__sensor_iodev_api,
25 		  &iodev_sensor_shell_stream_config);
26 
sensor_shell_processing_entry_point(void * a,void * b,void * c)27 static void sensor_shell_processing_entry_point(void *a, void *b, void *c)
28 {
29 	ARG_UNUSED(a);
30 	ARG_UNUSED(b);
31 	ARG_UNUSED(c);
32 
33 	while (true) {
34 		sensor_processing_with_callback(&sensor_read_rtio,
35 						sensor_shell_processing_callback);
36 	}
37 }
38 K_THREAD_DEFINE(sensor_shell_processing_tid, CONFIG_SENSOR_SHELL_THREAD_STACK_SIZE,
39 		sensor_shell_processing_entry_point, NULL, NULL, NULL, 0, 0, 0);
40 
cmd_sensor_stream(const struct shell * shell_ptr,size_t argc,char * argv[])41 int cmd_sensor_stream(const struct shell *shell_ptr, size_t argc, char *argv[])
42 {
43 	static struct rtio_sqe *current_streaming_handle;
44 	static struct sensor_shell_processing_context ctx;
45 	const struct device *dev = device_get_binding(argv[1]);
46 
47 	if (argc != 5 && argc != 3) {
48 		shell_error(shell_ptr, "Wrong number of arguments (%zu)", argc);
49 		return -EINVAL;
50 	}
51 
52 	if (dev == NULL) {
53 		shell_error(shell_ptr, "Device unknown (%s)", argv[1]);
54 		return -ENODEV;
55 	}
56 
57 	if (current_streaming_handle != NULL) {
58 		shell_info(shell_ptr, "Disabling existing stream");
59 		rtio_sqe_cancel(current_streaming_handle);
60 	}
61 
62 	if (strcmp("off", argv[2]) == 0) {
63 		return 0;
64 	}
65 
66 	if (strcmp("on", argv[2]) != 0) {
67 		shell_error(shell_ptr, "Unknown streaming operation (%s)", argv[2]);
68 		return -EINVAL;
69 	}
70 
71 	if (strcmp("double_tap", argv[3]) == 0) {
72 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_DOUBLE_TAP;
73 	} else if (strcmp("data_ready", argv[3]) == 0) {
74 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_DATA_READY;
75 	} else if (strcmp("delta", argv[3]) == 0) {
76 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_DELTA;
77 	} else if (strcmp("freefall", argv[3]) == 0) {
78 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_FREEFALL;
79 	} else if (strcmp("motion", argv[3]) == 0) {
80 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_MOTION;
81 	} else if (strcmp("near_far", argv[3]) == 0) {
82 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_NEAR_FAR;
83 	} else if (strcmp("stationary", argv[3]) == 0) {
84 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_STATIONARY;
85 	} else if (strcmp("threshold", argv[3]) == 0) {
86 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_THRESHOLD;
87 	} else if (strcmp("fifo_wm", argv[3]) == 0) {
88 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_FIFO_WATERMARK;
89 	} else if (strcmp("fifo_full", argv[3]) == 0) {
90 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_FIFO_FULL;
91 	} else if (strcmp("tap", argv[3]) == 0) {
92 		iodev_sensor_shell_trigger.trigger = SENSOR_TRIG_TAP;
93 	} else {
94 		shell_error(shell_ptr, "Invalid trigger (%s)", argv[3]);
95 		return -EINVAL;
96 	}
97 
98 	if (strcmp("incl", argv[4]) == 0) {
99 		iodev_sensor_shell_trigger.opt = SENSOR_STREAM_DATA_INCLUDE;
100 	} else if (strcmp("drop", argv[4]) == 0) {
101 		iodev_sensor_shell_trigger.opt = SENSOR_STREAM_DATA_DROP;
102 	} else if (strcmp("nop", argv[4]) == 0) {
103 		iodev_sensor_shell_trigger.opt = SENSOR_STREAM_DATA_NOP;
104 	} else {
105 		shell_error(shell_ptr, "Unknown trigger op (%s)", argv[4]);
106 		return -EINVAL;
107 	}
108 
109 	shell_print(shell_ptr, "Enabling stream...");
110 	iodev_sensor_shell_stream_config.sensor = dev;
111 
112 	iodev_sensor_shell_stream_config.count = 1;
113 
114 	ctx.dev = dev;
115 	ctx.sh = shell_ptr;
116 
117 	int rc = sensor_stream(&iodev_sensor_shell_stream, &sensor_read_rtio, &ctx,
118 			       &current_streaming_handle);
119 
120 	if (rc != 0) {
121 		shell_error(shell_ptr, "Failed to start stream");
122 	}
123 	return rc;
124 }
125