1 /*
2  * Copyright (c) 2018 Diego Sueiro
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/sensor.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/rtio/rtio.h>
15 #include <zephyr/shell/shell.h>
16 #include <zephyr/sys/iterable_sections.h>
17 #include <zephyr/sys/util.h>
18 
19 #include "sensor_shell.h"
20 
21 LOG_MODULE_REGISTER(sensor_shell, CONFIG_SENSOR_LOG_LEVEL);
22 
23 #define SENSOR_GET_HELP                                                                            \
24 	"Get sensor data. Channel names are optional. All channels are read "                      \
25 	"when no channels are provided. Syntax:\n"                                                 \
26 	"<device_name> <channel name 0> .. <channel name N>"
27 
28 #define SENSOR_STREAM_HELP                                                                         \
29 	"Start/stop streaming sensor data. Data ready trigger will be used if no triggers "        \
30 	"are provided. Syntax:\n"                                                                  \
31 	"<device_name> on|off <trigger name> incl|drop|nop"
32 
33 #define SENSOR_ATTR_GET_HELP                                                                       \
34 	"Get the sensor's channel attribute. Syntax:\n"                                            \
35 	"<device_name> [<channel_name 0> <attribute_name 0> .. "                                   \
36 	"<channel_name N> <attribute_name N>]"
37 
38 #define SENSOR_ATTR_SET_HELP                                                                       \
39 	"Set the sensor's channel attribute.\n"                                                    \
40 	"<device_name> <channel_name> <attribute_name> <value>"
41 
42 #define SENSOR_INFO_HELP "Get sensor info, such as vendor and model name, for all sensors."
43 
44 #define SENSOR_TRIG_HELP                                                                           \
45 	"Get or set the trigger type on a sensor. Currently only supports `data_ready`.\n"         \
46 	"<device_name> <on/off> <trigger_name>"
47 
48 static const char *sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = {
49 	[SENSOR_CHAN_ACCEL_X] = "accel_x",
50 	[SENSOR_CHAN_ACCEL_Y] = "accel_y",
51 	[SENSOR_CHAN_ACCEL_Z] = "accel_z",
52 	[SENSOR_CHAN_ACCEL_XYZ] = "accel_xyz",
53 	[SENSOR_CHAN_GYRO_X] = "gyro_x",
54 	[SENSOR_CHAN_GYRO_Y] = "gyro_y",
55 	[SENSOR_CHAN_GYRO_Z] = "gyro_z",
56 	[SENSOR_CHAN_GYRO_XYZ] = "gyro_xyz",
57 	[SENSOR_CHAN_MAGN_X] = "magn_x",
58 	[SENSOR_CHAN_MAGN_Y] = "magn_y",
59 	[SENSOR_CHAN_MAGN_Z] = "magn_z",
60 	[SENSOR_CHAN_MAGN_XYZ] = "magn_xyz",
61 	[SENSOR_CHAN_DIE_TEMP] = "die_temp",
62 	[SENSOR_CHAN_AMBIENT_TEMP] = "ambient_temp",
63 	[SENSOR_CHAN_PRESS] = "press",
64 	[SENSOR_CHAN_PROX] = "prox",
65 	[SENSOR_CHAN_HUMIDITY] = "humidity",
66 	[SENSOR_CHAN_LIGHT] = "light",
67 	[SENSOR_CHAN_IR] = "ir",
68 	[SENSOR_CHAN_RED] = "red",
69 	[SENSOR_CHAN_GREEN] = "green",
70 	[SENSOR_CHAN_BLUE] = "blue",
71 	[SENSOR_CHAN_ALTITUDE] = "altitude",
72 	[SENSOR_CHAN_PM_1_0] = "pm_1_0",
73 	[SENSOR_CHAN_PM_2_5] = "pm_2_5",
74 	[SENSOR_CHAN_PM_10] = "pm_10",
75 	[SENSOR_CHAN_DISTANCE] = "distance",
76 	[SENSOR_CHAN_CO2] = "co2",
77 	[SENSOR_CHAN_O2] = "o2",
78 	[SENSOR_CHAN_VOC] = "voc",
79 	[SENSOR_CHAN_GAS_RES] = "gas_resistance",
80 	[SENSOR_CHAN_VOLTAGE] = "voltage",
81 	[SENSOR_CHAN_VSHUNT] = "vshunt",
82 	[SENSOR_CHAN_CURRENT] = "current",
83 	[SENSOR_CHAN_POWER] = "power",
84 	[SENSOR_CHAN_RESISTANCE] = "resistance",
85 	[SENSOR_CHAN_ROTATION] = "rotation",
86 	[SENSOR_CHAN_POS_DX] = "pos_dx",
87 	[SENSOR_CHAN_POS_DY] = "pos_dy",
88 	[SENSOR_CHAN_POS_DZ] = "pos_dz",
89 	[SENSOR_CHAN_POS_DXYZ] = "pos_dxyz",
90 	[SENSOR_CHAN_RPM] = "rpm",
91 	[SENSOR_CHAN_GAUGE_VOLTAGE] = "gauge_voltage",
92 	[SENSOR_CHAN_GAUGE_AVG_CURRENT] = "gauge_avg_current",
93 	[SENSOR_CHAN_GAUGE_STDBY_CURRENT] = "gauge_stdby_current",
94 	[SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT] = "gauge_max_load_current",
95 	[SENSOR_CHAN_GAUGE_TEMP] = "gauge_temp",
96 	[SENSOR_CHAN_GAUGE_STATE_OF_CHARGE] = "gauge_state_of_charge",
97 	[SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY] = "gauge_full_cap",
98 	[SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY] = "gauge_remaining_cap",
99 	[SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY] = "gauge_nominal_cap",
100 	[SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY] = "gauge_full_avail_cap",
101 	[SENSOR_CHAN_GAUGE_AVG_POWER] = "gauge_avg_power",
102 	[SENSOR_CHAN_GAUGE_STATE_OF_HEALTH] = "gauge_state_of_health",
103 	[SENSOR_CHAN_GAUGE_TIME_TO_EMPTY] = "gauge_time_to_empty",
104 	[SENSOR_CHAN_GAUGE_TIME_TO_FULL] = "gauge_time_to_full",
105 	[SENSOR_CHAN_GAUGE_CYCLE_COUNT] = "gauge_cycle_count",
106 	[SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE] = "gauge_design_voltage",
107 	[SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE] = "gauge_desired_voltage",
108 	[SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT] = "gauge_desired_charging_current",
109 	[SENSOR_CHAN_ALL] = "all",
110 };
111 
112 static const char *sensor_attribute_name[SENSOR_ATTR_COMMON_COUNT] = {
113 	[SENSOR_ATTR_SAMPLING_FREQUENCY] = "sampling_frequency",
114 	[SENSOR_ATTR_LOWER_THRESH] = "lower_thresh",
115 	[SENSOR_ATTR_UPPER_THRESH] = "upper_thresh",
116 	[SENSOR_ATTR_SLOPE_TH] = "slope_th",
117 	[SENSOR_ATTR_SLOPE_DUR] = "slope_dur",
118 	[SENSOR_ATTR_HYSTERESIS] = "hysteresis",
119 	[SENSOR_ATTR_OVERSAMPLING] = "oversampling",
120 	[SENSOR_ATTR_FULL_SCALE] = "full_scale",
121 	[SENSOR_ATTR_OFFSET] = "offset",
122 	[SENSOR_ATTR_CALIB_TARGET] = "calib_target",
123 	[SENSOR_ATTR_CONFIGURATION] = "configuration",
124 	[SENSOR_ATTR_CALIBRATION] = "calibration",
125 	[SENSOR_ATTR_FEATURE_MASK] = "feature_mask",
126 	[SENSOR_ATTR_ALERT] = "alert",
127 	[SENSOR_ATTR_FF_DUR] = "ff_dur",
128 	[SENSOR_ATTR_BATCH_DURATION] = "batch_dur",
129 };
130 
131 enum sample_stats_state {
132 	SAMPLE_STATS_STATE_UNINITIALIZED = 0,
133 	SAMPLE_STATS_STATE_ENABLED,
134 	SAMPLE_STATS_STATE_DISABLED,
135 };
136 
137 struct sample_stats {
138 	int64_t accumulator;
139 	uint64_t sample_window_start;
140 	uint32_t count;
141 	enum sample_stats_state state;
142 };
143 
144 static struct sample_stats sensor_stats[CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES][SENSOR_CHAN_ALL];
145 
146 static const struct device *sensor_trigger_devices[CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES];
147 
device_is_sensor(const struct device * dev)148 static bool device_is_sensor(const struct device *dev)
149 {
150 #ifdef CONFIG_SENSOR_INFO
151 	STRUCT_SECTION_FOREACH(sensor_info, sensor) {
152 		if (sensor->dev == dev) {
153 			return true;
154 		}
155 	}
156 	return false;
157 #else
158 	return true;
159 #endif /* CONFIG_SENSOR_INFO */
160 }
161 
find_sensor_trigger_device(const struct device * sensor)162 static int find_sensor_trigger_device(const struct device *sensor)
163 {
164 	for (int i = 0; i < CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES; i++) {
165 		if (sensor_trigger_devices[i] == sensor) {
166 			return i;
167 		}
168 	}
169 	return -1;
170 }
171 
172 /* Forward declaration */
173 static void data_ready_trigger_handler(const struct device *sensor,
174 				       const struct sensor_trigger *trigger);
175 
176 #define TRIGGER_DATA_ENTRY(trig_enum, str_name, handler_func)                                      \
177 	[(trig_enum)] = {.name = #str_name,                                                        \
178 			 .handler = (handler_func),                                                \
179 			 .trigger = {.chan = SENSOR_CHAN_ALL, .type = (trig_enum)}}
180 
181 /**
182  * @brief This table stores a mapping of string trigger names along with the sensor_trigger struct
183  * that gets passed to the driver to enable that trigger, plus a function pointer to a handler. If
184  * that pointer is NULL, this indicates there is not currently support for that trigger type in the
185  * sensor shell.
186  */
187 static const struct {
188 	const char *name;
189 	sensor_trigger_handler_t handler;
190 	struct sensor_trigger trigger;
191 } sensor_trigger_table[SENSOR_TRIG_COMMON_COUNT] = {
192 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_TIMER, timer, NULL),
193 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_DATA_READY, data_ready, data_ready_trigger_handler),
194 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_DELTA, delta, NULL),
195 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_NEAR_FAR, near_far, NULL),
196 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_THRESHOLD, threshold, NULL),
197 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_TAP, tap, NULL),
198 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_DOUBLE_TAP, double_tap, NULL),
199 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_FREEFALL, freefall, NULL),
200 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_MOTION, motion, NULL),
201 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_STATIONARY, stationary, NULL),
202 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_FIFO_WATERMARK, fifo_wm, NULL),
203 	TRIGGER_DATA_ENTRY(SENSOR_TRIG_FIFO_FULL, fifo_full, NULL),
204 };
205 
206 /**
207  * Lookup the sensor trigger data by name
208  *
209  * @param name The name of the trigger
210  * @return < 0 on error
211  * @return >= 0 if found
212  */
sensor_trigger_name_lookup(const char * name)213 static int sensor_trigger_name_lookup(const char *name)
214 {
215 	for (int i = 0; i < ARRAY_SIZE(sensor_trigger_table); ++i) {
216 		if (strcmp(name, sensor_trigger_table[i].name) == 0) {
217 			return i;
218 		}
219 	}
220 	return -1;
221 }
222 
223 enum dynamic_command_context {
224 	NONE,
225 	CTX_GET,
226 	CTX_ATTR_GET_SET,
227 	CTX_STREAM_ON_OFF,
228 };
229 
230 static enum dynamic_command_context current_cmd_ctx = NONE;
231 
232 /* Mutex for accessing shared RTIO/IODEV data structures */
233 K_MUTEX_DEFINE(cmd_get_mutex);
234 
235 /* Crate a single common config for one-shot reading */
236 static struct sensor_chan_spec iodev_sensor_shell_channels[SENSOR_CHAN_ALL];
237 static struct sensor_read_config iodev_sensor_shell_read_config = {
238 	.sensor = NULL,
239 	.is_streaming = false,
240 	.channels = iodev_sensor_shell_channels,
241 	.count = 0,
242 	.max = ARRAY_SIZE(iodev_sensor_shell_channels),
243 };
244 RTIO_IODEV_DEFINE(iodev_sensor_shell_read, &__sensor_iodev_api, &iodev_sensor_shell_read_config);
245 
246 /* Create the RTIO context to service the reading */
247 RTIO_DEFINE_WITH_MEMPOOL(sensor_read_rtio, 8, 8, 32, 64, 4);
248 
parse_named_int(const char * name,const char * heystack[],size_t count)249 static int parse_named_int(const char *name, const char *heystack[], size_t count)
250 {
251 	char *endptr;
252 	int i;
253 
254 	/* Attempt to parse channel name as a number first */
255 	i = strtoul(name, &endptr, 0);
256 
257 	if (*endptr == '\0') {
258 		return i;
259 	}
260 
261 	/* Channel name is not a number, look it up */
262 	for (i = 0; i < count; i++) {
263 		if (strcmp(name, heystack[i]) == 0) {
264 			return i;
265 		}
266 	}
267 
268 	return -ENOTSUP;
269 }
270 
parse_sensor_value(const char * val_str,struct sensor_value * out)271 static int parse_sensor_value(const char *val_str, struct sensor_value *out)
272 {
273 	const bool is_negative = val_str[0] == '-';
274 	const char *decimal_pos = strchr(val_str, '.');
275 	long value;
276 	char *endptr;
277 
278 	/* Parse int portion */
279 	value = strtol(val_str, &endptr, 0);
280 
281 	if (*endptr != '\0' && *endptr != '.') {
282 		return -EINVAL;
283 	}
284 	if (value > INT32_MAX || value < INT32_MIN) {
285 		return -EINVAL;
286 	}
287 	out->val1 = (int32_t)value;
288 
289 	if (decimal_pos == NULL) {
290 		return 0;
291 	}
292 
293 	/* Parse the decimal portion */
294 	value = strtoul(decimal_pos + 1, &endptr, 0);
295 	if (*endptr != '\0') {
296 		return -EINVAL;
297 	}
298 	while (value < 100000) {
299 		value *= 10;
300 	}
301 	if (value > INT32_C(999999)) {
302 		return -EINVAL;
303 	}
304 	out->val2 = (int32_t)value;
305 	if (is_negative) {
306 		out->val2 *= -1;
307 	}
308 	return 0;
309 }
310 
sensor_shell_processing_callback(int result,uint8_t * buf,uint32_t buf_len,void * userdata)311 void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len, void *userdata)
312 {
313 	struct sensor_shell_processing_context *ctx = userdata;
314 	const struct sensor_decoder_api *decoder;
315 	uint8_t decoded_buffer[128];
316 	struct {
317 		uint64_t base_timestamp_ns;
318 		int count;
319 		uint64_t timestamp_delta;
320 		int64_t values[3];
321 		int8_t shift;
322 	} accumulator_buffer;
323 	int rc;
324 
325 	ARG_UNUSED(buf_len);
326 
327 	if (result < 0) {
328 		shell_error(ctx->sh, "Read failed");
329 		return;
330 	}
331 
332 	rc = sensor_get_decoder(ctx->dev, &decoder);
333 	if (rc != 0) {
334 		shell_error(ctx->sh, "Failed to get decoder for '%s'", ctx->dev->name);
335 		return;
336 	}
337 
338 	for (int trigger = 0; decoder->has_trigger != NULL && trigger < SENSOR_TRIG_COMMON_COUNT;
339 	     ++trigger) {
340 		if (!decoder->has_trigger(buf, trigger)) {
341 			continue;
342 		}
343 		shell_info(ctx->sh, "Trigger (%d / %s) detected", trigger,
344 			   (sensor_trigger_table[trigger].name == NULL
345 				    ? "UNKNOWN"
346 				    : sensor_trigger_table[trigger].name));
347 	}
348 
349 
350 
351 	for (struct sensor_chan_spec ch = {0, 0}; ch.chan_type < SENSOR_CHAN_ALL; ch.chan_type++) {
352 		uint32_t fit = 0;
353 		size_t base_size;
354 		size_t frame_size;
355 		uint16_t frame_count;
356 
357 		/* Channels with multi-axis equivalents are skipped */
358 		switch (ch.chan_type) {
359 		case SENSOR_CHAN_ACCEL_X:
360 		case SENSOR_CHAN_ACCEL_Y:
361 		case SENSOR_CHAN_ACCEL_Z:
362 		case SENSOR_CHAN_GYRO_X:
363 		case SENSOR_CHAN_GYRO_Y:
364 		case SENSOR_CHAN_GYRO_Z:
365 		case SENSOR_CHAN_MAGN_X:
366 		case SENSOR_CHAN_MAGN_Y:
367 		case SENSOR_CHAN_MAGN_Z:
368 		case SENSOR_CHAN_POS_DX:
369 		case SENSOR_CHAN_POS_DY:
370 		case SENSOR_CHAN_POS_DZ:
371 			continue;
372 		}
373 
374 		rc = decoder->get_size_info(ch, &base_size, &frame_size);
375 		if (rc != 0) {
376 			LOG_DBG("skipping unsupported channel %s:%d",
377 				 sensor_channel_name[ch.chan_type], ch.chan_idx);
378 			/* Channel not supported, skipping */
379 			continue;
380 		}
381 
382 		if (base_size > ARRAY_SIZE(decoded_buffer)) {
383 			shell_error(ctx->sh,
384 				    "Channel (type %d, idx %d) requires %zu bytes to decode, but "
385 				    "only %zu are available",
386 				    ch.chan_type, ch.chan_idx, base_size,
387 				    ARRAY_SIZE(decoded_buffer));
388 			continue;
389 		}
390 
391 		while (decoder->get_frame_count(buf, ch, &frame_count) == 0) {
392 			LOG_DBG("decoding %d frames from channel %s:%d",
393 				frame_count, sensor_channel_name[ch.chan_type], ch.chan_idx);
394 			fit = 0;
395 			memset(&accumulator_buffer, 0, sizeof(accumulator_buffer));
396 			while (decoder->decode(buf, ch, &fit, 1, decoded_buffer) > 0) {
397 				switch (ch.chan_type) {
398 				case SENSOR_CHAN_ACCEL_XYZ:
399 				case SENSOR_CHAN_GYRO_XYZ:
400 				case SENSOR_CHAN_MAGN_XYZ:
401 				case SENSOR_CHAN_POS_DXYZ: {
402 					struct sensor_three_axis_data *data =
403 						(struct sensor_three_axis_data *)decoded_buffer;
404 
405 					if (accumulator_buffer.count == 0) {
406 						accumulator_buffer.base_timestamp_ns =
407 							data->header.base_timestamp_ns;
408 					}
409 					accumulator_buffer.count++;
410 					accumulator_buffer.shift = data->shift;
411 					accumulator_buffer.timestamp_delta +=
412 						data->readings[0].timestamp_delta;
413 					accumulator_buffer.values[0] += data->readings[0].values[0];
414 					accumulator_buffer.values[1] += data->readings[0].values[1];
415 					accumulator_buffer.values[2] += data->readings[0].values[2];
416 					break;
417 				}
418 				case SENSOR_CHAN_PROX: {
419 					struct sensor_byte_data *data =
420 						(struct sensor_byte_data *)decoded_buffer;
421 
422 					if (accumulator_buffer.count == 0) {
423 						accumulator_buffer.base_timestamp_ns =
424 							data->header.base_timestamp_ns;
425 					}
426 					accumulator_buffer.count++;
427 					accumulator_buffer.timestamp_delta +=
428 						data->readings[0].timestamp_delta;
429 					accumulator_buffer.values[0] += data->readings[0].is_near;
430 					break;
431 				}
432 				default: {
433 					struct sensor_q31_data *data =
434 						(struct sensor_q31_data *)decoded_buffer;
435 
436 					if (accumulator_buffer.count == 0) {
437 						accumulator_buffer.base_timestamp_ns =
438 							data->header.base_timestamp_ns;
439 					}
440 					accumulator_buffer.count++;
441 					accumulator_buffer.shift = data->shift;
442 					accumulator_buffer.timestamp_delta +=
443 						data->readings[0].timestamp_delta;
444 					accumulator_buffer.values[0] += data->readings[0].value;
445 					break;
446 				}
447 				}
448 			}
449 
450 			/* Print the accumulated value average */
451 			switch (ch.chan_type) {
452 			case SENSOR_CHAN_ACCEL_XYZ:
453 			case SENSOR_CHAN_GYRO_XYZ:
454 			case SENSOR_CHAN_MAGN_XYZ:
455 			case SENSOR_CHAN_POS_DXYZ: {
456 				struct sensor_three_axis_data *data =
457 					(struct sensor_three_axis_data *)decoded_buffer;
458 
459 				data->header.base_timestamp_ns =
460 					accumulator_buffer.base_timestamp_ns;
461 				data->header.reading_count = 1;
462 				data->shift = accumulator_buffer.shift;
463 				data->readings[0].timestamp_delta =
464 					(uint32_t)(accumulator_buffer.timestamp_delta /
465 						   accumulator_buffer.count);
466 				data->readings[0].values[0] = (q31_t)(accumulator_buffer.values[0] /
467 								      accumulator_buffer.count);
468 				data->readings[0].values[1] = (q31_t)(accumulator_buffer.values[1] /
469 								      accumulator_buffer.count);
470 				data->readings[0].values[2] = (q31_t)(accumulator_buffer.values[2] /
471 								      accumulator_buffer.count);
472 				shell_info(ctx->sh,
473 					   "channel type=%d(%s) index=%d shift=%d num_samples=%d "
474 					   "value=%" PRIsensor_three_axis_data,
475 					   ch.chan_type, sensor_channel_name[ch.chan_type],
476 					   ch.chan_idx, data->shift, accumulator_buffer.count,
477 					   PRIsensor_three_axis_data_arg(*data, 0));
478 				break;
479 			}
480 			case SENSOR_CHAN_PROX: {
481 				struct sensor_byte_data *data =
482 					(struct sensor_byte_data *)decoded_buffer;
483 
484 				data->header.base_timestamp_ns =
485 					accumulator_buffer.base_timestamp_ns;
486 				data->header.reading_count = 1;
487 				data->readings[0].timestamp_delta =
488 					(uint32_t)(accumulator_buffer.timestamp_delta /
489 						   accumulator_buffer.count);
490 				data->readings[0].is_near =
491 					accumulator_buffer.values[0] / accumulator_buffer.count;
492 
493 				shell_info(ctx->sh,
494 					   "channel type=%d(%s) index=%d num_samples=%d "
495 					   "value=%" PRIsensor_byte_data(is_near),
496 					   ch.chan_type, sensor_channel_name[ch.chan_type],
497 					   ch.chan_idx, accumulator_buffer.count,
498 					   PRIsensor_byte_data_arg(*data, 0, is_near));
499 				break;
500 			}
501 			default: {
502 				struct sensor_q31_data *data =
503 					(struct sensor_q31_data *)decoded_buffer;
504 
505 				data->header.base_timestamp_ns =
506 					accumulator_buffer.base_timestamp_ns;
507 				data->header.reading_count = 1;
508 				data->shift = accumulator_buffer.shift;
509 				data->readings[0].timestamp_delta =
510 					(uint32_t)(accumulator_buffer.timestamp_delta /
511 						   accumulator_buffer.count);
512 				data->readings[0].value = (q31_t)(accumulator_buffer.values[0] /
513 								  accumulator_buffer.count);
514 
515 				shell_info(ctx->sh,
516 					   "channel type=%d(%s) index=%d shift=%d num_samples=%d "
517 					   "value=%" PRIsensor_q31_data,
518 					   ch.chan_type,
519 					   (ch.chan_type >= ARRAY_SIZE(sensor_channel_name))
520 						   ? ""
521 						   : sensor_channel_name[ch.chan_type],
522 					   ch.chan_idx,
523 					   data->shift, accumulator_buffer.count,
524 					   PRIsensor_q31_data_arg(*data, 0));
525 				}
526 			}
527 			++ch.chan_idx;
528 		}
529 		ch.chan_idx = 0;
530 	}
531 }
532 
cmd_get_sensor(const struct shell * sh,size_t argc,char * argv[])533 static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[])
534 {
535 	static struct sensor_shell_processing_context ctx;
536 	const struct device *dev;
537 	int count = 0;
538 	int err;
539 
540 	err = k_mutex_lock(&cmd_get_mutex, K_NO_WAIT);
541 	if (err < 0) {
542 		shell_error(sh, "Another sensor reading in progress");
543 		return err;
544 	}
545 
546 	dev = device_get_binding(argv[1]);
547 	if (dev == NULL) {
548 		shell_error(sh, "Device unknown (%s)", argv[1]);
549 		k_mutex_unlock(&cmd_get_mutex);
550 		return -ENODEV;
551 	}
552 
553 	if (!device_is_sensor(dev)) {
554 		shell_error(sh, "Device is not a sensor (%s)", argv[1]);
555 		k_mutex_unlock(&cmd_get_mutex);
556 		return -ENODEV;
557 	}
558 
559 	if (argc == 2) {
560 		/* read all channel types */
561 		for (int i = 0; i < ARRAY_SIZE(iodev_sensor_shell_channels); ++i) {
562 			if (SENSOR_CHANNEL_3_AXIS(i)) {
563 				continue;
564 			}
565 			iodev_sensor_shell_channels[count++] = (struct sensor_chan_spec){i, 0};
566 		}
567 	} else {
568 		/* read specific channels */
569 		for (int i = 2; i < argc; ++i) {
570 			int chan = parse_named_int(argv[i], sensor_channel_name,
571 						   ARRAY_SIZE(sensor_channel_name));
572 
573 			if (chan < 0) {
574 				shell_error(sh, "Failed to read channel (%s)", argv[i]);
575 				continue;
576 			}
577 			iodev_sensor_shell_channels[count++] =
578 				(struct sensor_chan_spec){chan, 0};
579 		}
580 	}
581 
582 	if (count == 0) {
583 		shell_error(sh, "No channels to read, bailing");
584 		k_mutex_unlock(&cmd_get_mutex);
585 		return -EINVAL;
586 	}
587 	iodev_sensor_shell_read_config.sensor = dev;
588 	iodev_sensor_shell_read_config.count = count;
589 
590 	ctx.dev = dev;
591 	ctx.sh = sh;
592 	err = sensor_read_async_mempool(&iodev_sensor_shell_read, &sensor_read_rtio, &ctx);
593 	if (err < 0) {
594 		shell_error(sh, "Failed to read sensor: %d", err);
595 	}
596 	if (!IS_ENABLED(CONFIG_SENSOR_SHELL_STREAM)) {
597 		/*
598 		 * Streaming enables a thread that polls the RTIO context, so if it's enabled, we
599 		 * don't need a blocking read here.
600 		 */
601 		sensor_processing_with_callback(&sensor_read_rtio,
602 						sensor_shell_processing_callback);
603 	}
604 
605 	k_mutex_unlock(&cmd_get_mutex);
606 
607 	return 0;
608 }
609 
cmd_sensor_attr_set(const struct shell * shell_ptr,size_t argc,char * argv[])610 static int cmd_sensor_attr_set(const struct shell *shell_ptr, size_t argc, char *argv[])
611 {
612 	const struct device *dev;
613 	int rc;
614 
615 	dev = device_get_binding(argv[1]);
616 	if (dev == NULL) {
617 		shell_error(shell_ptr, "Device unknown (%s)", argv[1]);
618 		return -ENODEV;
619 	}
620 
621 	if (!device_is_sensor(dev)) {
622 		shell_error(shell_ptr, "Device is not a sensor (%s)", argv[1]);
623 		k_mutex_unlock(&cmd_get_mutex);
624 		return -ENODEV;
625 	}
626 
627 	for (size_t i = 2; i < argc; i += 3) {
628 		int channel = parse_named_int(argv[i], sensor_channel_name,
629 					      ARRAY_SIZE(sensor_channel_name));
630 		int attr = parse_named_int(argv[i + 1], sensor_attribute_name,
631 					   ARRAY_SIZE(sensor_attribute_name));
632 		struct sensor_value value = {0};
633 
634 		if (channel < 0) {
635 			shell_error(shell_ptr, "Channel '%s' unknown", argv[i]);
636 			return -EINVAL;
637 		}
638 		if (attr < 0) {
639 			shell_error(shell_ptr, "Attribute '%s' unknown", argv[i + 1]);
640 			return -EINVAL;
641 		}
642 		if (parse_sensor_value(argv[i + 2], &value)) {
643 			shell_error(shell_ptr, "Sensor value '%s' invalid", argv[i + 2]);
644 			return -EINVAL;
645 		}
646 
647 		rc = sensor_attr_set(dev, channel, attr, &value);
648 		if (rc) {
649 			shell_error(shell_ptr, "Failed to set channel(%s) attribute(%s): %d",
650 				    sensor_channel_name[channel], sensor_attribute_name[attr], rc);
651 			continue;
652 		}
653 		shell_info(shell_ptr, "%s channel=%s, attr=%s set to value=%s", dev->name,
654 			   sensor_channel_name[channel], sensor_attribute_name[attr], argv[i + 2]);
655 	}
656 	return 0;
657 }
658 
cmd_sensor_attr_get_handler(const struct shell * shell_ptr,const struct device * dev,const char * channel_name,const char * attr_name,bool print_missing_attribute)659 static void cmd_sensor_attr_get_handler(const struct shell *shell_ptr, const struct device *dev,
660 					const char *channel_name, const char *attr_name,
661 					bool print_missing_attribute)
662 {
663 	int channel =
664 		parse_named_int(channel_name, sensor_channel_name, ARRAY_SIZE(sensor_channel_name));
665 	int attr = parse_named_int(attr_name, sensor_attribute_name,
666 				   ARRAY_SIZE(sensor_attribute_name));
667 	struct sensor_value value = {0};
668 	int rc;
669 
670 	if (channel < 0) {
671 		shell_error(shell_ptr, "Channel '%s' unknown", channel_name);
672 		return;
673 	}
674 	if (attr < 0) {
675 		shell_error(shell_ptr, "Attribute '%s' unknown", attr_name);
676 		return;
677 	}
678 
679 	rc = sensor_attr_get(dev, channel, attr, &value);
680 
681 	if (rc != 0) {
682 		if (rc == -EINVAL && !print_missing_attribute) {
683 			return;
684 		}
685 		shell_error(shell_ptr, "Failed to get channel(%s) attribute(%s): %d",
686 			    sensor_channel_name[channel], sensor_attribute_name[attr], rc);
687 		return;
688 	}
689 
690 	shell_info(shell_ptr, "%s(channel=%s, attr=%s) value=%.6f", dev->name,
691 		   sensor_channel_name[channel], sensor_attribute_name[attr],
692 		   sensor_value_to_double(&value));
693 }
694 
cmd_sensor_attr_get(const struct shell * shell_ptr,size_t argc,char * argv[])695 static int cmd_sensor_attr_get(const struct shell *shell_ptr, size_t argc, char *argv[])
696 {
697 	const struct device *dev;
698 
699 	dev = device_get_binding(argv[1]);
700 	if (dev == NULL) {
701 		shell_error(shell_ptr, "Device unknown (%s)", argv[1]);
702 		return -ENODEV;
703 	}
704 
705 	if (!device_is_sensor(dev)) {
706 		shell_error(shell_ptr, "Device is not a sensor (%s)", argv[1]);
707 		k_mutex_unlock(&cmd_get_mutex);
708 		return -ENODEV;
709 	}
710 
711 	if (argc > 2) {
712 		for (size_t i = 2; i < argc; i += 2) {
713 			cmd_sensor_attr_get_handler(shell_ptr, dev, argv[i], argv[i + 1],
714 						    /*print_missing_attribute=*/true);
715 		}
716 	} else {
717 		for (size_t channel_idx = 0; channel_idx < ARRAY_SIZE(sensor_channel_name);
718 		     ++channel_idx) {
719 			for (size_t attr_idx = 0; attr_idx < ARRAY_SIZE(sensor_attribute_name);
720 			     ++attr_idx) {
721 				cmd_sensor_attr_get_handler(shell_ptr, dev,
722 							    sensor_channel_name[channel_idx],
723 							    sensor_attribute_name[attr_idx],
724 							    /*print_missing_attribute=*/false);
725 			}
726 		}
727 	}
728 	return 0;
729 }
730 
731 static void channel_name_get(size_t idx, struct shell_static_entry *entry);
732 SHELL_DYNAMIC_CMD_CREATE(dsub_channel_name, channel_name_get);
733 
734 static void attribute_name_get(size_t idx, struct shell_static_entry *entry);
735 SHELL_DYNAMIC_CMD_CREATE(dsub_attribute_name, attribute_name_get);
736 
channel_name_get(size_t idx,struct shell_static_entry * entry)737 static void channel_name_get(size_t idx, struct shell_static_entry *entry)
738 {
739 	int cnt = 0;
740 
741 	entry->syntax = NULL;
742 	entry->handler = NULL;
743 	entry->help = NULL;
744 	if (current_cmd_ctx == CTX_GET) {
745 		entry->subcmd = &dsub_channel_name;
746 	} else if (current_cmd_ctx == CTX_ATTR_GET_SET) {
747 		entry->subcmd = &dsub_attribute_name;
748 	} else {
749 		entry->subcmd = NULL;
750 	}
751 
752 	for (int i = 0; i < ARRAY_SIZE(sensor_channel_name); i++) {
753 		if (sensor_channel_name[i] != NULL) {
754 			if (cnt == idx) {
755 				entry->syntax = sensor_channel_name[i];
756 				break;
757 			}
758 			cnt++;
759 		}
760 	}
761 }
762 
attribute_name_get(size_t idx,struct shell_static_entry * entry)763 static void attribute_name_get(size_t idx, struct shell_static_entry *entry)
764 {
765 	int cnt = 0;
766 
767 	entry->syntax = NULL;
768 	entry->handler = NULL;
769 	entry->help = NULL;
770 	entry->subcmd = &dsub_channel_name;
771 
772 	for (int i = 0; i < ARRAY_SIZE(sensor_attribute_name); i++) {
773 		if (sensor_attribute_name[i] != NULL) {
774 			if (cnt == idx) {
775 				entry->syntax = sensor_attribute_name[i];
776 				break;
777 			}
778 			cnt++;
779 		}
780 	}
781 }
782 
783 static void trigger_opt_get_for_stream(size_t idx, struct shell_static_entry *entry);
784 SHELL_DYNAMIC_CMD_CREATE(dsub_trigger_opt_get_for_stream, trigger_opt_get_for_stream);
785 
trigger_opt_get_for_stream(size_t idx,struct shell_static_entry * entry)786 static void trigger_opt_get_for_stream(size_t idx, struct shell_static_entry *entry)
787 {
788 	entry->syntax = NULL;
789 	entry->handler = NULL;
790 	entry->help = NULL;
791 	entry->subcmd = NULL;
792 
793 	switch (idx) {
794 	case SENSOR_STREAM_DATA_INCLUDE:
795 		entry->syntax = "incl";
796 		break;
797 	case SENSOR_STREAM_DATA_DROP:
798 		entry->syntax = "drop";
799 		break;
800 	case SENSOR_STREAM_DATA_NOP:
801 		entry->syntax = "nop";
802 		break;
803 	}
804 }
805 
806 static void trigger_name_get_for_stream(size_t idx, struct shell_static_entry *entry);
807 SHELL_DYNAMIC_CMD_CREATE(dsub_trigger_name_for_stream, trigger_name_get_for_stream);
808 
trigger_name_get_for_stream(size_t idx,struct shell_static_entry * entry)809 static void trigger_name_get_for_stream(size_t idx, struct shell_static_entry *entry)
810 {
811 	int cnt = 0;
812 
813 	entry->syntax = NULL;
814 	entry->handler = NULL;
815 	entry->help = NULL;
816 	entry->subcmd = &dsub_trigger_opt_get_for_stream;
817 
818 	for (int i = 0; i < ARRAY_SIZE(sensor_trigger_table); i++) {
819 		if (sensor_trigger_table[i].name != NULL) {
820 			if (cnt == idx) {
821 				entry->syntax = sensor_trigger_table[i].name;
822 				break;
823 			}
824 			cnt++;
825 		}
826 	}
827 }
828 
stream_on_off(size_t idx,struct shell_static_entry * entry)829 static void stream_on_off(size_t idx, struct shell_static_entry *entry)
830 {
831 	entry->syntax = NULL;
832 	entry->handler = NULL;
833 	entry->help = NULL;
834 
835 	if (idx == 0) {
836 		entry->syntax = "on";
837 		entry->subcmd = &dsub_trigger_name_for_stream;
838 	} else if (idx == 1) {
839 		entry->syntax = "off";
840 		entry->subcmd = NULL;
841 	}
842 }
843 SHELL_DYNAMIC_CMD_CREATE(dsub_stream_on_off, stream_on_off);
844 
845 static void device_name_get(size_t idx, struct shell_static_entry *entry);
846 
847 SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get);
848 
device_name_get(size_t idx,struct shell_static_entry * entry)849 static void device_name_get(size_t idx, struct shell_static_entry *entry)
850 {
851 	const struct device *dev = shell_device_lookup(idx, NULL);
852 
853 	current_cmd_ctx = CTX_GET;
854 	entry->syntax = (dev != NULL) ? dev->name : NULL;
855 	entry->handler = NULL;
856 	entry->help = NULL;
857 	entry->subcmd = &dsub_channel_name;
858 }
859 
device_name_get_for_attr(size_t idx,struct shell_static_entry * entry)860 static void device_name_get_for_attr(size_t idx, struct shell_static_entry *entry)
861 {
862 	const struct device *dev = shell_device_lookup(idx, NULL);
863 
864 	current_cmd_ctx = CTX_ATTR_GET_SET;
865 	entry->syntax = (dev != NULL) ? dev->name : NULL;
866 	entry->handler = NULL;
867 	entry->help = NULL;
868 	entry->subcmd = &dsub_channel_name;
869 }
870 SHELL_DYNAMIC_CMD_CREATE(dsub_device_name_for_attr, device_name_get_for_attr);
871 
trigger_name_get(size_t idx,struct shell_static_entry * entry)872 static void trigger_name_get(size_t idx, struct shell_static_entry *entry)
873 {
874 	int cnt = 0;
875 
876 	entry->syntax = NULL;
877 	entry->handler = NULL;
878 	entry->help = NULL;
879 	entry->subcmd = NULL;
880 
881 	for (int i = 0; i < ARRAY_SIZE(sensor_trigger_table); i++) {
882 		if (sensor_trigger_table[i].name != NULL) {
883 			if (cnt == idx) {
884 				entry->syntax = sensor_trigger_table[i].name;
885 				break;
886 			}
887 			cnt++;
888 		}
889 	}
890 }
891 
892 SHELL_DYNAMIC_CMD_CREATE(dsub_trigger_name, trigger_name_get);
893 
trigger_on_off_get(size_t idx,struct shell_static_entry * entry)894 static void trigger_on_off_get(size_t idx, struct shell_static_entry *entry)
895 {
896 	entry->handler = NULL;
897 	entry->help = NULL;
898 	entry->subcmd = &dsub_trigger_name;
899 
900 	switch (idx) {
901 	case 0:
902 		entry->syntax = "on";
903 		break;
904 	case 1:
905 		entry->syntax = "off";
906 		break;
907 	default:
908 		entry->syntax = NULL;
909 		break;
910 	}
911 }
912 
913 SHELL_DYNAMIC_CMD_CREATE(dsub_trigger_onoff, trigger_on_off_get);
914 
device_name_get_for_trigger(size_t idx,struct shell_static_entry * entry)915 static void device_name_get_for_trigger(size_t idx, struct shell_static_entry *entry)
916 {
917 	const struct device *dev = shell_device_lookup(idx, NULL);
918 
919 	entry->syntax = (dev != NULL) ? dev->name : NULL;
920 	entry->handler = NULL;
921 	entry->help = NULL;
922 	entry->subcmd = &dsub_trigger_onoff;
923 }
924 
925 SHELL_DYNAMIC_CMD_CREATE(dsub_trigger, device_name_get_for_trigger);
926 
device_name_get_for_stream(size_t idx,struct shell_static_entry * entry)927 static void device_name_get_for_stream(size_t idx, struct shell_static_entry *entry)
928 {
929 	const struct device *dev = shell_device_lookup(idx, NULL);
930 
931 	current_cmd_ctx = CTX_STREAM_ON_OFF;
932 	entry->syntax = (dev != NULL) ? dev->name : NULL;
933 	entry->handler = NULL;
934 	entry->help = NULL;
935 	entry->subcmd = &dsub_stream_on_off;
936 }
937 SHELL_DYNAMIC_CMD_CREATE(dsub_device_name_for_stream, device_name_get_for_stream);
938 
cmd_get_sensor_info(const struct shell * sh,size_t argc,char ** argv)939 static int cmd_get_sensor_info(const struct shell *sh, size_t argc, char **argv)
940 {
941 	ARG_UNUSED(argc);
942 	ARG_UNUSED(argv);
943 
944 #ifdef CONFIG_SENSOR_INFO
945 	const char *null_str = "(null)";
946 
947 	STRUCT_SECTION_FOREACH(sensor_info, sensor) {
948 		shell_print(sh,
949 			    "device name: %s, vendor: %s, model: %s, "
950 			    "friendly name: %s",
951 			    sensor->dev->name, sensor->vendor ? sensor->vendor : null_str,
952 			    sensor->model ? sensor->model : null_str,
953 			    sensor->friendly_name ? sensor->friendly_name : null_str);
954 	}
955 	return 0;
956 #else
957 	return -EINVAL;
958 #endif
959 }
960 
data_ready_trigger_handler(const struct device * sensor,const struct sensor_trigger * trigger)961 static void data_ready_trigger_handler(const struct device *sensor,
962 				       const struct sensor_trigger *trigger)
963 {
964 	const int64_t now = k_uptime_get();
965 	struct sensor_value value;
966 	int sensor_idx = find_sensor_trigger_device(sensor);
967 	struct sample_stats *stats;
968 	int sensor_name_len_before_at;
969 	const char *sensor_name;
970 
971 	if (sensor_idx < 0) {
972 		LOG_ERR("Unable to find sensor trigger device");
973 		return;
974 	}
975 	stats = sensor_stats[sensor_idx];
976 	sensor_name = sensor_trigger_devices[sensor_idx]->name;
977 	if (sensor_name) {
978 		sensor_name_len_before_at = strchr(sensor_name, '@') - sensor_name;
979 	} else {
980 		sensor_name_len_before_at = 0;
981 	}
982 
983 	if (sensor_sample_fetch(sensor)) {
984 		LOG_ERR("Failed to fetch samples on data ready handler");
985 	}
986 	for (int i = 0; i < SENSOR_CHAN_ALL; ++i) {
987 		int rc;
988 
989 		/* Skip disabled channels */
990 		if (stats[i].state == SAMPLE_STATS_STATE_DISABLED) {
991 			continue;
992 		}
993 		/* Skip 3 axis channels */
994 		if (SENSOR_CHANNEL_3_AXIS(i)) {
995 			continue;
996 		}
997 
998 		rc = sensor_channel_get(sensor, i, &value);
999 		if (stats[i].state == SAMPLE_STATS_STATE_UNINITIALIZED) {
1000 			if (rc == -ENOTSUP) {
1001 				/*
1002 				 * Stop reading this channel if the driver told us
1003 				 * it's not supported.
1004 				 */
1005 				stats[i].state = SAMPLE_STATS_STATE_DISABLED;
1006 			} else if (rc == 0) {
1007 				stats[i].state = SAMPLE_STATS_STATE_ENABLED;
1008 			}
1009 		}
1010 		if (rc != 0) {
1011 			/* Skip on any error. */
1012 			continue;
1013 		}
1014 		/* Do something with the data */
1015 		stats[i].accumulator += value.val1 * INT64_C(1000000) + value.val2;
1016 		if (stats[i].count++ == 0) {
1017 			stats[i].sample_window_start = now;
1018 		} else if (now > stats[i].sample_window_start +
1019 					 CONFIG_SENSOR_SHELL_TRIG_PRINT_TIMEOUT_MS) {
1020 			int64_t micro_value = stats[i].accumulator / stats[i].count;
1021 
1022 			value.val1 = micro_value / 1000000;
1023 			value.val2 = (int32_t)llabs(micro_value - (value.val1 * 1000000));
1024 			LOG_INF("sensor=%.*s, chan=%s, num_samples=%u, data=%d.%06d",
1025 				sensor_name_len_before_at, sensor_name,
1026 				sensor_channel_name[i],
1027 				stats[i].count,
1028 				value.val1, value.val2);
1029 
1030 			stats[i].accumulator = 0;
1031 			stats[i].count = 0;
1032 		}
1033 	}
1034 }
1035 
cmd_trig_sensor(const struct shell * sh,size_t argc,char ** argv)1036 static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv)
1037 {
1038 	const struct device *dev;
1039 	int trigger;
1040 	bool trigger_enabled = false;
1041 	int err;
1042 
1043 	if (argc < 4) {
1044 		shell_error(sh, "Wrong number of args");
1045 		return -EINVAL;
1046 	}
1047 
1048 	/* Parse device name */
1049 	dev = device_get_binding(argv[1]);
1050 	if (dev == NULL) {
1051 		shell_error(sh, "Device unknown (%s)", argv[1]);
1052 		return -ENODEV;
1053 	}
1054 
1055 	/* Map the trigger string to an enum value */
1056 	trigger = sensor_trigger_name_lookup(argv[3]);
1057 	if (trigger < 0 || sensor_trigger_table[trigger].handler == NULL) {
1058 		shell_error(sh, "Unsupported trigger type (%s)", argv[3]);
1059 		return -ENOTSUP;
1060 	}
1061 
1062 	/* Parse on/off */
1063 	if (strcmp(argv[2], "on") == 0) {
1064 		/* find a free entry in sensor_trigger_devices[] */
1065 		int sensor_idx = find_sensor_trigger_device(NULL);
1066 
1067 		if (sensor_idx < 0) {
1068 			shell_error(sh, "Unable to support more simultaneous sensor trigger"
1069 				    " devices");
1070 			err = -ENOTSUP;
1071 		} else {
1072 			struct sample_stats *stats = sensor_stats[sensor_idx];
1073 
1074 			sensor_trigger_devices[sensor_idx] = dev;
1075 			/* reset stats state to UNINITIALIZED */
1076 			for (unsigned int ch = 0; ch < SENSOR_CHAN_ALL; ch++) {
1077 				stats[ch].state = SAMPLE_STATS_STATE_UNINITIALIZED;
1078 			}
1079 			err = sensor_trigger_set(dev, &sensor_trigger_table[trigger].trigger,
1080 						 sensor_trigger_table[trigger].handler);
1081 			trigger_enabled = true;
1082 		}
1083 	} else if (strcmp(argv[2], "off") == 0) {
1084 		/* Clear the handler for the given trigger on this device */
1085 		err = sensor_trigger_set(dev, &sensor_trigger_table[trigger].trigger, NULL);
1086 		if (!err) {
1087 			/* find entry in sensor_trigger_devices[] and free it */
1088 			int sensor_idx = find_sensor_trigger_device(dev);
1089 
1090 			if (sensor_idx < 0) {
1091 				shell_error(sh, "Unable to find sensor device in trigger array");
1092 			} else {
1093 				sensor_trigger_devices[sensor_idx] = NULL;
1094 			}
1095 		}
1096 	} else {
1097 		shell_error(sh, "Pass 'on' or 'off' to enable/disable trigger");
1098 		return -EINVAL;
1099 	}
1100 
1101 	if (err) {
1102 		shell_error(sh, "Error while setting trigger %d on device %s (%d)", trigger,
1103 			    argv[1], err);
1104 	} else {
1105 		shell_info(sh, "%s trigger idx=%d %s on device %s",
1106 			   trigger_enabled ? "Enabled" : "Disabled", trigger,
1107 			   sensor_trigger_table[trigger].name, argv[1]);
1108 	}
1109 
1110 	return err;
1111 }
1112 
1113 /* clang-format off */
1114 SHELL_STATIC_SUBCMD_SET_CREATE(sub_sensor,
1115 	SHELL_CMD_ARG(get, &dsub_device_name, SENSOR_GET_HELP, cmd_get_sensor,
1116 			2, 255),
1117 	SHELL_CMD_ARG(attr_set, &dsub_device_name_for_attr, SENSOR_ATTR_SET_HELP,
1118 			cmd_sensor_attr_set, 2, 255),
1119 	SHELL_CMD_ARG(attr_get, &dsub_device_name_for_attr, SENSOR_ATTR_GET_HELP,
1120 			cmd_sensor_attr_get, 2, 255),
1121 	SHELL_COND_CMD(CONFIG_SENSOR_SHELL_STREAM, stream, &dsub_device_name_for_stream,
1122 			SENSOR_STREAM_HELP, cmd_sensor_stream),
1123 	SHELL_COND_CMD(CONFIG_SENSOR_INFO, info, NULL, SENSOR_INFO_HELP,
1124 			cmd_get_sensor_info),
1125 	SHELL_CMD_ARG(trig, &dsub_trigger, SENSOR_TRIG_HELP, cmd_trig_sensor,
1126 			2, 255),
1127 	SHELL_SUBCMD_SET_END
1128 	);
1129 /* clang-format on */
1130 
1131 SHELL_CMD_REGISTER(sensor, &sub_sensor, "Sensor commands", NULL);
1132