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