1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "oslo_config_test"
18 
19 #include <errno.h>
20 #include <getopt.h>
21 #include <inttypes.h>
22 #include <limits.h>
23 #include <log/log.h>
24 #include <math.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/ioctl.h>
30 #include <time.h>
31 #include <unistd.h>
32 
33 #include "oslo_iaxxx_sensor_control.h"
34 #include "oslo_sound_model_control.h"
35 
36 #define GETOPT_HELP_CHAR (CHAR_MIN - 2)
37 
38 #define BGT60TR24C_NUM_REGISTERS        0x60
39 
40 /* Oslo Calibration */
41 #define CAL_FILE "/mnt/vendor/persist/oslo/oslo.cal"
42 #define CAL_MODES_MAX 10
43 #define CAL_INVALID_MODE -1
44 #define CAL_MODE_IS_VALID(x) (x >= 0 && x < CAL_MODES_MAX)
45 #define CAL_VERSION_DEFAULT 1.0f
46 
47 /* Transmit power */
48 #define TX_CAL_FILE "/mnt/vendor/persist/oslo/tx_power.cal"
49 
50 typedef enum {
51     INJECT_MODE_OFF = 0,
52     INJECT_MODE_PRESENCE,
53     INJECT_MODE_REACH,
54     INJECT_MODE_NUM,
55 } oslo_inject_mode_t;
56 
57 typedef struct {
58     int setting_id;
59     char *setting_name;
60 } oslo_settings_t;
61 
62 /* map oslo driver setting name to param id */
63 static const oslo_settings_t oslo_driver_settings[] =
64 {
65     {SENSOR_PARAM_FRAMES_PROCESSED,                         "frames_processed"},
66     {SENSOR_PARAM_PRESET_RADAR_CONFIG,                      "preset_radar_config"},
67     {OSLO_CONFIG_DEFAULT,                                   "config_default"},
68     {OSLO_CONFIG_PRESENCE,                                  "config_presence"},
69     {OSLO_CONFIG_CONTINUOUS,                                "config_continuous"},
70     {OSLO_CONFIG_PRESENCE_SLOW,                             "config_presence_slow"},
71     {OSLO_CONFIG_FACTORY_PRESENCE,                          "config_factory_presence"},
72     {OSLO_CONFIG_FACTORY_REACH,                             "config_factory_reach"},
73     {OSLO_CONFIG_CW_MODE,                                   "config_cw_mode"},
74     {OSLO_CONFIG_FACTORY_PRESENCE_V1,                       "config_factory_presence_v1"},
75     {OSLO_CONFIG_FACTORY_REACH_V1,                          "config_factory_reach_v1"},
76     {OSLO_CONFIG_REACH,                                     "config_reach"},
77     {OSLO_CONFIG_PRESENCE_V1,                               "config_presence_v1"},
78     {OSLO_CONFIG_REACH_V1,                                  "config_reach_v1"},
79     {OSLO_CONFIG_OFF,                                       "config_off"},
80     {OSLO_CONTROL_RESTART,                                  "oslo_control_restart"},
81     {OSLO_CONTROL_STRIP_HEADERS,                            "oslo_control_strip_headers"},
82     {OSLO_CONTROL_SLPI_INT,                                 "oslo_control_slpi_interrupt"},
83     {OSLO_CONTROL_STOP,                                     "oslo_control_stop"},
84     {OSLO_CONTROL_SIMULATE_RADAR_DATA,                      "oslo_control_simulate_radar_data"},
85     {OSLO_CONTROL_ASSERT_RESET,                             "oslo_control_assert_reset"},
86     {OSLO_PARAM_REQUEST_RATE,                               "param_request_rate"},
87     {OSLO_PARAM_REQUEST_ANTENNA_MASK,                       "param_request_antenna_mask"},
88     {OSLO_PARAM_TX_POWER,                                   "param_tx_power"},
89     {OSLO_PARAM_LOWER_FREQ,                                 "param_lower_freq"},
90     {OSLO_PARAM_UPPER_FREQ,                                 "param_upper_freq"},
91     {OSLO_PARAM_SAMPLES_PER_CHIRP,                          "param_samples_per_chirp"},
92     {OSLO_PARAM_VGA_GAIN_CH1,                               "param_vga_gain_ch1"},
93     {OSLO_PARAM_VGA_GAIN_CH2,                               "param_vga_gain_ch2"},
94     {OSLO_PARAM_VGA_GAIN_CH3,                               "param_vga_gain_ch3"},
95     {OSLO_PARAM_VGA_GAIN_CH4,                               "param_vga_gain_ch4"},
96     {OSLO_PARAM_BURST_CHIRP_COUNT,                          "param_burst_chirp_count"},
97     {OSLO_PARAM_BURST_CHIRP_RATE,                           "param_burst_chirp_rate"},
98     {OSLO_PARAM_BURST_POWER_MODE,                           "param_burst_power_mode"},
99     {OSLO_PARAM_BURST_INTERCHIRP_POWER_MODE,                "param_burst_interchirp_power_mode"},
100     {OSLO_PARAM_STARTUP_TIMING_WAKE_UP_TIME_100NS,          "param_startup_timing_wake_up_time_100ns"},
101     {OSLO_PARAM_STARTUP_TIMING_PLL_SETTLE_TIME_COARSE_100NS,"param_startup_timing_pll_settle_time_coarse_100ns"},
102     {OSLO_PARAM_STARTUP_TIMING_PLL_SETTLE_TIME_FINE_100NS,  "param_startup_timing_pll_settle_time_fine_100ns"},
103     {OSLO_PARAM_STARTUP_TIMING_OSCILLATOR_USEC,             "param_startup_timing_oscillator_usec"},
104     {OSLO_PARAM_PRE_CHIRP_DELAY_100NS,                      "param_pre_chirp_delay_100ns"},
105     {OSLO_PARAM_POST_CHIRP_DELAY_100NS,                     "param_post_chirp_delay_100ns"},
106     {OSLO_PARAM_CHIRP_PA_DELAY_100NS,                       "param_chirp_pa_delay_100ns"},
107     {OSLO_PARAM_CHIRP_ADC_DELAY_100NS,                      "param_chirp_adc_delay_100ns"},
108     {OSLO_PARAM_VISUALIZER_DATA_TYPE,                       "param_visualizer_data_type"},
109     {OSLO_PARAM_OSCILLATOR_MODE,                            "param_oscillator_mode"},
110     {OSLO_PARAM_HP_GAIN_CH1,                                "param_hp_gain_ch1"},
111     {OSLO_PARAM_HP_GAIN_CH2,                                "param_hp_gain_ch2"},
112     {OSLO_PARAM_HP_GAIN_CH3,                                "param_hp_gain_ch3"},
113     {OSLO_PARAM_HP_GAIN_CH4,                                "param_hp_gain_ch4"},
114     {OSLO_PARAM_BASEBAND_RESET_PERIOD_1NS,                  "param_baseband_reset_period_1ns"},
115     {OSLO_PARAM_HP_CUTOFF_CH1,                              "param_hp_cutoff_ch1"},
116     {OSLO_PARAM_HP_CUTOFF_CH2,                              "param_hp_cutoff_ch2"},
117     {OSLO_PARAM_HP_CUTOFF_CH3,                              "param_hp_cutoff_ch3"},
118     {OSLO_PARAM_HP_CUTOFF_CH4,                              "param_hp_cutoff_ch4"},
119     {OSLO_PARAM_PHASE_CONFIG,                               "param_phase_config"},
120     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_PLL,                   "param_idle_settings_enable_pll"},
121     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_VCO,                   "param_idle_settings_enable_vco"},
122     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_FDIV,                  "param_idle_settings_enable_fdiv"},
123     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_BASEBAND,              "param_idle_settings_enable_baseband"},
124     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_RF,                    "param_idle_settings_enable_rf"},
125     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_MADC,                  "param_idle_settings_enable_madc"},
126     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_MADC_BANDGAP,          "param_idle_settings_enable_madc_bandgap"},
127     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_SADC,                  "param_idle_settings_enable_sadc"},
128     {OSLO_PARAM_IDLE_SETTINGS_ENABLE_SADC_BANDGAP,          "param_idle_settings_enable_sadc_bandgap"},
129     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_PLL,             "param_deep_sleep_settings_enable_pll"},
130     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_VCO,             "param_deep_sleep_settings_enable_vco"},
131     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_FDIV,            "param_deep_sleep_settings_enable_fdiv"},
132     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_BASEBAND,        "param_deep_sleep_settings_enable_baseband"},
133     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_RF,              "param_deep_sleep_settings_enable_rf"},
134     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_MADC,            "param_deep_sleep_settings_enable_madc"},
135     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_MADC_BANDGAP,    "param_deep_sleep_settings_enable_madc_bandgap"},
136     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_SADC,            "param_deep_sleep_settings_enable_sadc"},
137     {OSLO_PARAM_DEEP_SLEEP_SETTINGS_ENABLE_SADC_BANDGAP,    "param_deep_sleep_settings_enable_sadc_bandgap"},
138     {OSLO_PARAM_CHIRP_DIRECTION,                            "param_chirp_direction"},
139     {OSLO_PARAM_ADC_SAMPLE_RATE,                            "param_adc_sample_rate"},
140     {OSLO_PARAM_CHARGE_PUMP,                                "param_charge_pump"},
141 };
142 
143 /* map oslo plugin setting name to param id */
144 static const oslo_settings_t oslo_plugin_settings[] =
145 {
146     {OSLO_SENSOR_PARAM_MODE,                                "plugin_mode"},
147     {OSLO_SENSOR_PARAM_SLPY_STATE,                          "plugin_slpy_state"},
148     {OSLO_SENSOR_PARAM_ENABLE_SLPY_RAW,                     "plugin_slpy_raw"},
149     {OSLO_SENSOR_PARAM_HOST,                                "plugin_set_host"},
150     {OSLO_SENSOR_STATE,                                     "plugin_oslo_state"},
151     {OSLO_SENSOR_CONFIG_RECOVERY_COUNTER,                   "plugin_config_retries"},
152     {OSLO_SENSOR_PARAM_ENABLE_PRESENCE,                     "plugin_enable_presence"},
153     {OSLO_SENSOR_PARAM_ENABLE_REACH,                        "plugin_enable_reach"},
154     {OSLO_SENSOR_PARAM_ENABLE_FLICK,                        "plugin_enable_flick"},
155     {OSLO_SENSOR_PARAM_ENABLE_SWIPE,                        "plugin_enable_swipe"},
156     {OSLO_SENSOR_PARAM_ENABLE_TAP,                          "plugin_enable_tap"},
157     {OSLO_SENSOR_PARAM_ENABLE_AUDIO_FILTER,                 "plugin_enable_audio_filter"},
158     {OSLO_SENSOR_PARAM_ENABLE_WLC_FILTER,                   "plugin_enable_wlc_filter"},
159     {OSLO_SENSOR_PARAM_CPS,                                 "plugin_cps"},
160     {OSLO_SENSOR_MAX_POWER_MODE,                            "plugin_max_power_mode"},
161     {OSLO_SENSOR_PARAM_SLPY_TEST_MODE,                      "plugin_slpy_test_mode"},
162 };
163 
164 /* map oslo plugin test mode name to param id */
165 static const oslo_settings_t oslo_plugin_test_mode[] =
166 {
167     {OSLO_TESTMODE_RESET,                                   "reset"},
168     {OSLO_TESTMODE_PRESENCE_ON,                             "presence_on"},
169     {OSLO_TESTMODE_PRESENCE_OFF,                            "presence_off"},
170     {OSLO_TESTMODE_SWIPE,                                   "swipe"},
171     {OSLO_TESTMODE_FLICK,                                   "flick"},
172     {OSLO_TESTMODE_REACH_IN,                                "reach_in"},
173     {OSLO_TESTMODE_REACH_OUT,                               "reach_out"},
174     {OSLO_TESTMODE_REACH_SWIPE,                             "reach+swipe"},
175     {OSLO_TESTMODE_REACH_FLICK,                             "reach+flick"},
176     {OSLO_TESTMODE_REACH_SWIPE_FLICK,                       "reach+swipe+flick"},
177 };
178 #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
179 #define OSLO_DRIVER_SETTINGS_SIZE COUNT_OF(oslo_driver_settings)
180 #define OSLO_PLUGIN_SETTINGS_SIZE COUNT_OF(oslo_plugin_settings)
181 #define OSLO_PLUGIN_TESTMODE_SIZE COUNT_OF(oslo_plugin_test_mode)
182 
183 struct cal_coefficient {
184     float version;
185     int mode;
186     float ch1_i_val;
187     float ch1_q_val;
188     float ch2_i_val;
189     float ch2_q_val;
190     float ch3_i_val;
191     float ch3_q_val;
192 };
193 static struct cal_coefficient cal_table[CAL_MODES_MAX];
194 static uint32_t tx_power_cal;
195 
196 static struct option const long_options[] =
197 {
198  {"setparamid", required_argument, NULL, 's'},
199  {"value", required_argument, NULL, 'v'},
200  {"getparamid", required_argument, NULL, 'g'},
201  {"ping", required_argument, NULL, 'p'},
202  {"route", required_argument, NULL, 'r'},
203  {"readregister", required_argument, NULL, 'd'},
204  {"writeregister", required_argument, NULL, 'w'},
205  {"calibration", required_argument, NULL, 'c'},
206  {"tx power cal", required_argument, NULL, 'e'},
207  {"injection", required_argument, NULL, 'i'},
208  {"help", no_argument, NULL, GETOPT_HELP_CHAR},
209  {NULL, 0, NULL, 0}
210 };
211 
usage()212 void usage() {
213     fputs("\
214     USAGE -\n\
215     -------\n\
216     1) oslo_config_test -s <param_name> -v <param_val>\n\
217     2) oslo_config_test -g <param_name>\n\
218     \n\
219     In the first form, set a parameter with a value.\n\
220     In the second form, get a value of a parameter\n\
221     \n\
222     3) oslo_config_test -p <timeout>\n\
223     4) oslo_config_test -r <1/0>\n\
224     5) oslo_config_test -d <reg_addr>\n\
225     6) oslo_config_test -w <reg_addr> -v <reg_val>\n\
226     7) oslo_config_test -c 'V:<ver> M:<mode> <ch1 I_val> <ch1 Q_val> <ch2 I_val> <ch2 Q_val> <ch3 I_val> <ch3 Q_val>' \n\
227     8) oslo_config_test -t <test_mode> -v <elapsed time>\n\
228     9) oslo_config_test -i <0/1/2>      # 0:off 1:entrance 2:interactive \n\
229     10) oslo_config_test -e '<tx_val>'\n\
230     ", stdout);
231 
232     fputs("\n\
233     OPTIONS - \n\
234     ---------\n\
235     -s          Set a parameter using its <param_name>.\n\
236     -v          Set this value for the parameter ID that was passed with\n\
237                 the option '-s'. Using this option alone is invalid.\n\
238     -g          Get the value of a parameter using its <param_name>.\n\
239     -p          Ping oslo sensor.\n\
240     -r          Set sensor route.\n\
241     -d          Read register.\n\
242     -w          Write register.\n\
243     -c          Store Calibration coefficients to persist file.\n\
244     -t          Set the system into a test mode with optional gesture detection spoofing.\n\
245     -i          Set the system into data injection mode.\n\
246     -e          Store Tx power calibration to persist file.\n\
247     ", stdout);
248 
249     fputs("\n\
250     List of all <param_name>\n\
251     ---------\
252     ", stdout);
253     fputs("\n", stdout);
254 
255     unsigned int i;
256     for (i = 0; i < OSLO_DRIVER_SETTINGS_SIZE; i++) {
257         fprintf(stdout, "    %s\n", oslo_driver_settings[i].setting_name, stdout);
258     }
259     for (i = 0; i < OSLO_PLUGIN_SETTINGS_SIZE; i++) {
260         fprintf(stdout, "    %s\n", oslo_plugin_settings[i].setting_name, stdout);
261     }
262 
263     fputs("\n\
264     List of all <test_mode>\n\
265     ---------\
266     ", stdout);
267     fputs("\n", stdout);
268 
269     for (i = 0; i < OSLO_PLUGIN_TESTMODE_SIZE; i++) {
270         fprintf(stdout, "    %s\n", oslo_plugin_test_mode[i].setting_name, stdout);
271     }
272 
273     exit(EXIT_FAILURE);
274 }
275 
oslo_driver_setting_lookup(char * in)276 int oslo_driver_setting_lookup(char *in)
277 {
278     unsigned int i;
279     int ret = -1;
280 
281     for (i = 0; i < OSLO_DRIVER_SETTINGS_SIZE; i++)
282     {
283         if (strcmp(in, oslo_driver_settings[i].setting_name) == 0)
284         {
285             ret = oslo_driver_settings[i].setting_id;
286             break;
287         }
288     }
289 
290     return ret;
291 }
292 
oslo_plugin_setting_lookup(char * in)293 int oslo_plugin_setting_lookup(char *in)
294 {
295     unsigned int i;
296     int ret = -1;
297 
298     for (i = 0; i < OSLO_PLUGIN_SETTINGS_SIZE; i++)
299     {
300         if (strcmp(in, oslo_plugin_settings[i].setting_name) == 0)
301         {
302             ret = oslo_plugin_settings[i].setting_id;
303             break;
304         }
305     }
306 
307     return ret;
308 }
309 
oslo_plugin_test_mode_lookup(char * in)310 int oslo_plugin_test_mode_lookup(char *in)
311 {
312     unsigned int i;
313     int ret = -1;
314 
315     for (i = 0; i < OSLO_PLUGIN_TESTMODE_SIZE; i++)
316     {
317         if (strcmp(in, oslo_plugin_test_mode[i].setting_name) == 0)
318         {
319             ret = oslo_plugin_test_mode[i].setting_id;
320             break;
321         }
322     }
323 
324     return ret;
325 }
326 
oslo_enable(struct ia_sensor_mgr * smd,bool enable)327 void oslo_enable(struct ia_sensor_mgr *smd, bool enable) {
328     if (enable) {
329         osloSoundModelEnable(true);
330         oslo_driver_set_param(smd, OSLO_CONTROL_RESTART, 1);
331     }
332     else {
333         oslo_driver_set_param(smd, OSLO_CONTROL_STOP, 0);
334         sleep(1);
335         osloSoundModelEnable(false);
336     }
337 }
338 
ping_test(struct ia_sensor_mgr * smd,uint32_t ping_timeout_sec)339 bool ping_test(struct ia_sensor_mgr *smd, uint32_t ping_timeout_sec) {
340     bool ret = false;
341     uint32_t radar_frames_initial;
342     time_t start_time;
343 
344     oslo_enable(smd, true);
345 
346     start_time = time(NULL);
347     radar_frames_initial = oslo_driver_get_param(smd, SENSOR_PARAM_FRAMES_PROCESSED);
348 
349     do {
350         uint32_t radar_frames = oslo_driver_get_param(smd, SENSOR_PARAM_FRAMES_PROCESSED);
351         if (radar_frames > radar_frames_initial) {
352             ALOGD("%s: frame number increased (%d, %d)",
353                   __func__, radar_frames_initial, radar_frames);
354             ret = true;
355             break;
356         }
357         else
358             usleep(50 * 1000); // 50ms
359     } while (difftime(time(NULL), start_time) <= ping_timeout_sec);
360 
361     oslo_enable(smd, false);
362 
363     ALOGD("%s: %s", __func__, (ret ? "PASS" : "FAIL"));
364     fprintf(stdout, "%s: %s\n", __func__, (ret ? "PASS" : "FAIL"));
365 
366     return ret;
367 }
368 
read_register(struct ia_sensor_mgr * smd,uint32_t reg_addr)369 void read_register(struct ia_sensor_mgr *smd, uint32_t reg_addr) {
370     uint32_t reg_val;
371 
372     if (reg_addr >= BGT60TR24C_NUM_REGISTERS) {
373         fprintf(stdout, "Invalid reg addr:0x%02x\n", reg_addr);
374         return;
375     }
376 
377     reg_val = oslo_driver_get_param(smd, OSLO_REGISTER_MIN + reg_addr);
378 
379     ALOGD("reg[0x%02x]: 0x%06x\n", reg_addr, reg_val);
380     fprintf(stdout, "reg[0x%02x]: 0x%06x\n", reg_addr, reg_val);
381 }
382 
write_register(struct ia_sensor_mgr * smd,uint32_t reg_addr,uint32_t reg_val)383 void write_register(struct ia_sensor_mgr *smd, uint32_t reg_addr, uint32_t reg_val) {
384     if (reg_addr >= BGT60TR24C_NUM_REGISTERS) {
385         fprintf(stdout, "Invalid reg addr:0x%02x\n", reg_addr);
386         return;
387     }
388 
389     oslo_driver_set_param(smd, OSLO_REGISTER_MIN + reg_addr, reg_val);
390 
391     ALOGD("Write reg[0x%02x] val:0x%06x\n", reg_addr, reg_val);
392     fprintf(stdout, "Write reg[0x%02x] val:0x%06x\n", reg_addr, reg_val);
393 }
394 
cal_read_persist(void)395 int cal_read_persist(void) {
396     FILE *fid;
397     struct cal_coefficient coef;
398 
399     fid = fopen(CAL_FILE, "r");
400     if (fid == NULL) {
401         ALOGD("%s: Cannot open '%s'\n", __func__, CAL_FILE);
402         return -errno;
403     }
404 
405     while (!feof(fid)) {
406         int num;
407 
408         memset(&coef, 0, sizeof(coef));
409         coef.mode = CAL_INVALID_MODE;
410 
411         num = fscanf(fid, "Version: %f\n", &coef.version);
412         if (num != 1) {
413             ALOGE("%s: Parse Version failed, num:%d\n", __func__, num);
414             coef.version = CAL_VERSION_DEFAULT;
415         }
416 
417         num = fscanf(fid, "Mode: %d\n", &coef.mode);
418         if (num != 1) {
419             ALOGE("%s: Parse Mode failed, num:%d\n", __func__, num);
420             break;
421         }
422 
423         num = fscanf(fid, "ch1: %f %f\n", &coef.ch1_i_val, &coef.ch1_q_val);
424         if (num != 2) {
425             ALOGE("%s: Parse ch1 failed, num:%d\n", __func__, num);
426             break;
427         }
428 
429         num = fscanf(fid, "ch2: %f %f\n", &coef.ch2_i_val, &coef.ch2_q_val);
430         if (num != 2) {
431             ALOGE("%s: Parse ch2 failed, num:%d\n", __func__, num);
432             break;
433         }
434 
435         num = fscanf(fid, "ch3: %f %f\n", &coef.ch3_i_val, &coef.ch3_q_val);
436         if (num != 2) {
437             ALOGE("%s: Parse ch3 failed, num:%d\n", __func__, num);
438             break;
439         }
440 
441         if (CAL_MODE_IS_VALID(coef.mode)) {
442             memcpy(&cal_table[coef.mode], &coef, sizeof(coef));
443             ALOGD("%s: %.1f %d  %f %f %f %f %f %f\n", __func__,
444                   coef.version,
445                   coef.mode,
446                   coef.ch1_i_val, coef.ch1_q_val,
447                   coef.ch2_i_val, coef.ch2_q_val,
448                   coef.ch3_i_val, coef.ch3_q_val);
449         } else {
450             ALOGE("%s: Invalid mode:%d\n", __func__, coef.mode);
451         }
452     }
453 
454     fclose(fid);
455 
456     return 0;
457 }
458 
cal_write_persist(const struct cal_coefficient * coef)459 int cal_write_persist(const struct cal_coefficient* coef) {
460     FILE *fid;
461 
462     if (!coef) {
463         ALOGE("%s: Invalid coef", __func__);
464         fprintf(stdout, "%s: Invalid coef\n", __func__);
465         return -EINVAL;
466     }
467 
468     if (!CAL_MODE_IS_VALID(coef->mode)) {
469         ALOGE("%s: Invalid mode:%d", __func__, coef->mode);
470         fprintf(stdout, "%s: Invalid mode:%d\n", __func__, coef->mode);
471         return -EINVAL;
472     }
473 
474     fid = fopen(CAL_FILE, "w");
475     if (fid == NULL) {
476         ALOGE("Cannot open '%s' (%s)\n", CAL_FILE, strerror(errno));
477         fprintf(stdout, "Cannot open '%s' (%s)\n", CAL_FILE, strerror(errno));
478         return -errno;
479     }
480 
481     memcpy(&cal_table[coef->mode], coef, sizeof(struct cal_coefficient));
482     for (int i = 0; i < CAL_MODES_MAX; i++) {
483         if (CAL_MODE_IS_VALID(cal_table[i].mode)) {
484             fprintf(fid, "Version: %.1f\n", cal_table[i].version);
485             fprintf(fid, "Mode: %u\n", cal_table[i].mode);
486             fprintf(fid, "ch1: %f %f\n",
487                          cal_table[i].ch1_i_val,
488                          cal_table[i].ch1_q_val);
489             fprintf(fid, "ch2: %f %f\n",
490                          cal_table[i].ch2_i_val,
491                          cal_table[i].ch2_q_val);
492             fprintf(fid, "ch3: %f %f\n",
493                          cal_table[i].ch3_i_val,
494                          cal_table[i].ch3_q_val);
495             ALOGD("%s: %.1f %d %f %f %f %f %f %f\n", __func__,
496                   cal_table[i].version,
497                   cal_table[i].mode,
498                   cal_table[i].ch1_i_val, cal_table[i].ch1_q_val,
499                   cal_table[i].ch2_i_val, cal_table[i].ch2_q_val,
500                   cal_table[i].ch3_i_val, cal_table[i].ch3_q_val);
501         }
502     }
503 
504     fclose(fid);
505 
506     return 0;
507 }
508 
read_tx_power_from_persist(void)509 static int read_tx_power_from_persist(void) {
510     FILE *fid;
511     uint32_t tx_power = 0;
512 
513     fid = fopen(TX_CAL_FILE, "r");
514     if (fid == NULL) {
515         ALOGD("%s: Cannot open '%s'\n", __func__, TX_CAL_FILE);
516         return -errno;
517     }
518 
519     while (!feof(fid)) {
520         int num;
521         num = fscanf(fid, "tx_power: %d\n", &tx_power);
522         if (num != 1) {
523             ALOGE("%s: Parse tx power failed, num:%d\n", __func__, num);
524             break;
525         }
526 
527         memcpy(&tx_power_cal, &tx_power, sizeof(tx_power));
528         ALOGD("%s: tx_power: %d\n", __func__, tx_power);
529     }
530 
531     fclose(fid);
532     return 0;
533 }
534 
write_tx_power_to_persist(const uint32_t * tx_power)535 static int write_tx_power_to_persist(const uint32_t* tx_power) {
536     FILE *fid;
537 
538     if (!tx_power) {
539         ALOGE("%s: Invalid tx power", __func__);
540         fprintf(stdout, "%s: Invalid tx power\n", __func__);
541         return -EINVAL;
542     }
543 
544     fid = fopen(TX_CAL_FILE, "w");
545     if (fid == NULL) {
546         ALOGE("Cannot open '%s' (%s)\n", TX_CAL_FILE, strerror(errno));
547         fprintf(stdout, "Cannot open '%s' (%s)\n", TX_CAL_FILE, strerror(errno));
548         return -errno;
549     }
550 
551     memcpy(&tx_power_cal, tx_power, sizeof(tx_power_cal));
552     fprintf(fid, "tx_power: %u\n", tx_power_cal);
553     ALOGD("%s: %d\n", __func__, tx_power_cal);
554     fclose(fid);
555     return 0;
556 }
557 
main(int argc,char * argv[])558 int main(int argc, char *argv[]) {
559     struct ia_sensor_mgr * smd;
560     char use_case;
561     int driver_param_id = -1;
562     int plugin_param_id = -1;
563     int c;
564     float param_val = 0.0;
565     uint32_t ping_timeout_sec;
566     bool route_enable;
567     uint32_t reg_addr;
568     uint32_t reg_val;
569     bool reg_val_set = false;
570     struct cal_coefficient cal_coef = { .mode = CAL_INVALID_MODE };
571     uint32_t tx_power = 0;
572     int test_mode_param_id = -1;
573     oslo_inject_mode_t inject_mode = INJECT_MODE_OFF;
574 
575     if (argc <= 1) {
576         usage();
577     }
578 
579     while ((c = getopt_long (argc, argv, "s:v:g:p:r:d:w:c:t:i:e:", long_options, NULL)) != -1) {
580         switch (c) {
581         case 's':
582             if (NULL == optarg) {
583                 fprintf(stderr, "Incorrect usage, s option requires an argument");
584                 usage();
585             } else {
586                 driver_param_id = oslo_driver_setting_lookup(optarg);
587                 plugin_param_id = oslo_plugin_setting_lookup(optarg);
588                 if (driver_param_id == -1 && plugin_param_id == -1) {
589                     fprintf(stderr, "Invalid setting %s", optarg);
590                     usage();
591                 } else {
592                     use_case = 's';
593                 }
594             }
595         break;
596         case 'v':
597             if (NULL == optarg) {
598                 fprintf(stderr, "Incorrect usage, v option requires an argument");
599                 usage();
600             } else {
601                 if ('s' == use_case) {
602                     param_val = strtof(optarg, NULL);
603                     use_case = 'v';
604                 } else if ('w' == use_case) {
605                     reg_val = strtoul(optarg, NULL, 0);
606                     reg_val_set = true;
607                 } else if ('t' == use_case) {
608                     param_val = strtof(optarg, NULL);
609                     use_case = 'v';
610                 } else {
611                     fprintf(stderr, "Incorrect usage, v option should be the second option");
612                     usage();
613                 }
614             }
615         break;
616         case 'g':
617             if (NULL == optarg) {
618                 fprintf(stderr, "Incorrect usage, g option requires an argument");
619                 usage();
620             } else {
621                 driver_param_id = oslo_driver_setting_lookup(optarg);
622                 plugin_param_id = oslo_plugin_setting_lookup(optarg);
623                 if (driver_param_id == -1 && plugin_param_id == -1) {
624                     fprintf(stderr, "Invalid setting %s", optarg);
625                     usage();
626                 } else {
627                     use_case = 'g';
628                 }
629             }
630         break;
631         case 'p':
632             if (NULL == optarg) {
633                 fprintf(stderr, "Incorrect usage, p option requires an argument");
634                 usage();
635             } else {
636                 ping_timeout_sec = strtoul(optarg, NULL, 0);
637                 use_case = 'p';
638             }
639         break;
640         case 'r':
641             if (NULL == optarg) {
642                 fprintf(stderr, "Incorrect usage, r option requires an argument");
643                 usage();
644             } else {
645                 route_enable = (strtoul(optarg, NULL, 0) != 0) ? true : false;
646                 use_case = 'r';
647             }
648         break;
649         case 'd':
650             if (NULL == optarg) {
651                 fprintf(stderr, "Incorrect usage, d option requires an argument");
652                 usage();
653             } else {
654                 reg_addr = strtoul(optarg, NULL, 0);
655                 use_case = 'd';
656             }
657         break;
658         case 'w':
659             if (NULL == optarg) {
660                 fprintf(stderr, "Incorrect usage, w option requires an argument");
661                 usage();
662             } else {
663                 reg_addr = strtoul(optarg, NULL, 0);
664                 use_case = 'w';
665             }
666         break;
667         case 'c':
668             if (NULL == optarg) {
669                 fprintf(stderr, "Incorrect usage, c option requires an argument");
670                 usage();
671             } else {
672                 int num_matched;
673                 num_matched = sscanf(optarg, "V:%f M:%d %f %f %f %f %f %f",
674                                      &cal_coef.version,
675                                      &cal_coef.mode,
676                                      &cal_coef.ch1_i_val, &cal_coef.ch1_q_val,
677                                      &cal_coef.ch2_i_val, &cal_coef.ch2_q_val,
678                                      &cal_coef.ch3_i_val, &cal_coef.ch3_q_val);
679                 if (num_matched == 8) {
680                     use_case = 'c';
681                 } else {
682                     fprintf(stderr, "Incorrect -c arguments %s\n", optarg);
683                     usage();
684                 }
685             }
686         break;
687         case 'e':
688             if (NULL == optarg) {
689                 fprintf(stderr, "Incorrect usage, e option requires an argument");
690                 usage();
691             } else {
692                 int num_matched;
693                 num_matched = sscanf(optarg, "%d", &tx_power);
694                 if (num_matched == 1) {
695                     use_case = 'e';
696                 } else {
697                     fprintf(stderr, "Incorrect -e arguments %s \n", optarg);
698                     usage();
699                 }
700             }
701         break;
702         case 't':
703             if (NULL == optarg) {
704                 fprintf(stderr, "Incorrect usage, t option requires an argument");
705                 usage();
706             } else {
707                 test_mode_param_id = oslo_plugin_test_mode_lookup(optarg);
708                 if (test_mode_param_id == -1) {
709                     fprintf(stderr, "Invalid setting %s", optarg);
710                     usage();
711                 } else {
712                     use_case = 't';
713                     fprintf(stderr, "Executing test mode %s\n", optarg);
714                 }
715             }
716         break;
717         case 'i':
718             if (NULL == optarg) {
719                 fprintf(stderr, "Incorrect usage, i option requires an argument");
720                 usage();
721             } else {
722                 inject_mode = strtoul(optarg, NULL, 0);
723                 if (inject_mode >= INJECT_MODE_NUM) {
724                     fprintf(stderr, "Invalid setting %s", optarg);
725                     usage();
726                 } else {
727                     use_case = 'i';
728                 }
729             }
730         break;
731         case GETOPT_HELP_CHAR:
732         default:
733             usage();
734         break;
735         }
736 
737         smd = iaxxx_sensor_mgr_init();
738         if (NULL == smd) {
739             ALOGE("%s: ERROR Failed to init ia_sensor_mgr", __func__);
740             return -EINVAL;
741         }
742 
743         if ('v' == use_case) {
744             if (driver_param_id != -1) {
745                 oslo_driver_set_param(smd, driver_param_id, param_val);
746             } else if (plugin_param_id != -1) {
747                 oslo_plugin_set_param(plugin_param_id, param_val);
748             } else if (test_mode_param_id != -1) {
749                 uint32_t integer_param = (uint32_t)lrintf(param_val);
750                 if (param_val < 0) {
751                     ALOGD("%s: Test mode: %d with no event", __func__, test_mode_param_id);
752                     integer_param = UINT32_MAX;
753                 } else if (param_val > 0) {
754                     ALOGD("%s: Test mode: %d with duration: %" PRIu32, __func__, test_mode_param_id, integer_param);
755                 } else {
756                     ALOGD("%s: Test mode: %d with no duration", __func__, test_mode_param_id);
757                 }
758                 oslo_plugin_set_param(test_mode_param_id, integer_param);
759             }
760         } else if ('g' == use_case) {
761             if (driver_param_id != -1) {
762                 oslo_driver_get_param(smd, driver_param_id);
763             } else if (plugin_param_id != -1) {
764                 oslo_plugin_get_param(plugin_param_id);
765             }
766         } else if ('p' == use_case) {
767             ping_test(smd, ping_timeout_sec);
768         } else if ('r' == use_case) {
769             route_enable ? osloSoundModelEnable(true) : oslo_enable(smd, false);
770         } else if ('d' == use_case) {
771             read_register(smd, reg_addr);
772         } else if ('w' == use_case) {
773             if (reg_val_set)
774                 write_register(smd, reg_addr, reg_val);
775         } else if ('c' == use_case) {
776             for (int i = 0; i < CAL_MODES_MAX; i++) {
777                 cal_table[i].mode = CAL_INVALID_MODE;
778             }
779             cal_read_persist();
780             cal_write_persist(&cal_coef);
781         } else if ('e' == use_case) {
782             read_tx_power_from_persist();
783             write_tx_power_to_persist(&tx_power);
784         } else if ('i' == use_case) {
785             oslo_plugin_set_param(OSLO_SENSOR_PARAM_SLPY_STATE, 0);
786             oslo_driver_set_param(smd, OSLO_CONTROL_INJECT_RADAR_DATA, inject_mode);
787             oslo_plugin_set_param(OSLO_SENSOR_PARAM_SLPY_STATE, inject_mode);
788         }
789 
790         iaxxx_sensor_mgr_deinit(smd);
791     }
792 
793     return 0;
794 }
795