1 /*
2 * Copyright 2023 Google LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdlib.h>
8 #include <zephyr/device.h>
9 #include <zephyr/input/input_analog_axis.h>
10 #include <zephyr/input/input_analog_axis_settings.h>
11 #include <zephyr/logging/log.h>
12 #include <zephyr/settings/settings.h>
13 #include <zephyr/sys/printk.h>
14
15 LOG_MODULE_REGISTER(analog_axis_settings, CONFIG_INPUT_LOG_LEVEL);
16
17 #define ANALOG_AXIS_SETTINGS_PATH_MAX 32
18
19 #define MAX_AXES CONFIG_INPUT_ANALOG_AXIS_SETTINGS_MAX_AXES
20
analog_axis_calibration_log(const struct device * dev)21 static void analog_axis_calibration_log(const struct device *dev)
22 {
23 struct analog_axis_calibration cal;
24 int i;
25
26 for (i = 0; i < analog_axis_num_axes(dev); i++) {
27 analog_axis_calibration_get(dev, i, &cal);
28
29 LOG_INF("%s: ch: %d min: %d max: %d deadzone: %d",
30 dev->name, i, cal.in_min, cal.in_max, cal.out_deadzone);
31 }
32 }
33
analog_axis_calibration_load(const char * key,size_t len_rd,settings_read_cb read_cb,void * cb_arg)34 static int analog_axis_calibration_load(const char *key, size_t len_rd,
35 settings_read_cb read_cb, void *cb_arg)
36 {
37 const struct device *dev;
38 struct analog_axis_calibration cal[MAX_AXES];
39 int axes;
40 char dev_name[ANALOG_AXIS_SETTINGS_PATH_MAX];
41 const char *next;
42 int nlen;
43 ssize_t len;
44
45 nlen = settings_name_next(key, &next);
46 if (nlen + 1 > sizeof(dev_name)) {
47 LOG_ERR("Setting name too long: %d", nlen);
48 return -EINVAL;
49 }
50
51 memcpy(dev_name, key, nlen);
52 dev_name[nlen] = '\0';
53
54 dev = device_get_binding(dev_name);
55 if (dev == NULL) {
56 LOG_ERR("Cannot restore: device %s not available", dev_name);
57 return -ENODEV;
58 }
59
60 len = read_cb(cb_arg, cal, sizeof(cal));
61 if (len < 0) {
62 LOG_ERR("Data restore error: %d", len);
63 }
64
65 axes = analog_axis_num_axes(dev);
66 if (len != sizeof(struct analog_axis_calibration) * axes) {
67 LOG_ERR("Invalid settings data length: %d, expected %d",
68 len, sizeof(struct analog_axis_calibration) * axes);
69 return -EIO;
70 }
71
72 for (int i = 0; i < axes; i++) {
73 analog_axis_calibration_set(dev, i, &cal[i]);
74 }
75
76 analog_axis_calibration_log(dev);
77
78 return 0;
79 }
80
81 SETTINGS_STATIC_HANDLER_DEFINE(analog_axis, "aa-cal", NULL,
82 analog_axis_calibration_load, NULL, NULL);
83
analog_axis_calibration_save(const struct device * dev)84 int analog_axis_calibration_save(const struct device *dev)
85 {
86 struct analog_axis_calibration cal[MAX_AXES];
87 int axes;
88 char path[ANALOG_AXIS_SETTINGS_PATH_MAX];
89 int ret;
90
91 analog_axis_calibration_log(dev);
92
93 ret = snprintk(path, sizeof(path), "aa-cal/%s", dev->name);
94 if (ret < 0) {
95 return -EINVAL;
96 }
97
98 axes = analog_axis_num_axes(dev);
99 for (int i = 0; i < axes; i++) {
100 analog_axis_calibration_get(dev, i, &cal[i]);
101 }
102
103 ret = settings_save_one(path, &cal[0],
104 sizeof(struct analog_axis_calibration) * axes);
105 if (ret < 0) {
106 LOG_ERR("Settings save errord: %d", ret);
107 return ret;
108 }
109
110 return 0;
111 }
112