Repository navigation
Expand file tree
/
Copy pathparams.c
More file actions
467 lines (419 loc) · 13.4 KB
/
Copy pathparams.c
File metadata and controls
467 lines (419 loc) · 13.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
/*
* Copyright 2023 Morse Micro
* SPDX-License-Identifier: GPL-2.0-or-later OR LicenseRef-MorseMicroCommercial
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include "portable_endian.h"
#include "command.h"
#include "utilities.h"
struct param_entry;
/**
* @brief Callback to process user input for setting a parameter entry.
*
* @param entry The parameter entry to set.
* @param value The value provided by the user on the CLI.
* @param req On success of parsing, the value field of the req struct will be filled.
*
* @return 0 on success, else specific error code.
*/
typedef int (*param_process_t)(const struct param_entry* entry,
const char* value, struct morse_cmd_req_get_set_generic_param* req);
/**
* @brief Callback that formats the response of a get operation, printing to stdout.
*
* @param entry The parameter entry to format.
* @param resp Pointer to the response to format.
*
* @return 0 on success, else specific error code.
*/
typedef int (*param_format_t)(const struct param_entry* entry,
struct morse_cmd_resp_get_set_generic_param* resp);
struct param_entry {
/** ID of the parameter */
enum morse_cmd_param_id id;
/** Name of the parameter (used to match on user CLI input) */
const char *name;
/** The help message to display for the parameter */
const char *help;
/** Minimum allowed value of the parameter (can be of a different int type,
* but cast to uint32) */
uint32_t min_val;
/** Maximum allowed value of the parameter (can be of a different int type,
* but cast to uint32) */
uint32_t max_val;
/** Function that processes user input for the set command */
param_process_t set_fn;
/** Function that formats response of the get command to stdout */
param_format_t get_fn;
};
static int param_set_uint32(const struct param_entry* entry, const char* value,
struct morse_cmd_req_get_set_generic_param* req)
{
int ret;
uint32_t val;
ret = str_to_uint32_range(value, &val, entry->min_val, entry->max_val);
if (ret)
{
mctrl_err("Failed to parse value for '%s' [min:%u, max:%u]\n",
entry->name, entry->min_val, entry->max_val);
return ret;
}
req->value = htole32(val);
return 0;
}
static int param_get_uint32(const struct param_entry* entry,
struct morse_cmd_resp_get_set_generic_param* resp)
{
mctrl_print("%u\n", le32toh(resp->value));
return 0;
}
static int param_set_int32(const struct param_entry* entry, const char* value,
struct morse_cmd_req_get_set_generic_param* req)
{
int ret;
int32_t val;
ret = str_to_int32_range(value, &val, (int32_t)(entry->min_val), (int32_t)(entry->max_val));
if (ret)
{
mctrl_err("Failed to parse value for '%s' [min:%d, max:%d]\n",
entry->name, entry->min_val, entry->max_val);
return ret;
}
req->value = htole32((uint32_t)val);
return 0;
}
static int param_get_int32(const struct param_entry* entry,
struct morse_cmd_resp_get_set_generic_param* resp)
{
mctrl_print("%d\n", le32toh(resp->value));
return 0;
}
static struct {
struct arg_str *param;
struct arg_str *value;
} args;
int get_init(struct morsectrl *mors, struct mm_argtable *mm_args)
{
MM_INIT_ARGTABLE(mm_args, "Get a chip parameter",
args.param = arg_str1(NULL, NULL, "<param>", "Parameter name"));
return 0;
}
int set_init(struct morsectrl *mors, struct mm_argtable *mm_args)
{
MM_INIT_ARGTABLE(mm_args, "Set a chip parameter",
args.param = arg_str1(NULL, NULL, "<param>", "Parameter name"),
args.value = arg_str1(NULL, NULL, "<value>", "Value"));
return 0;
}
/* Help strings for parameters should not have line control characters (e.g. '\n') embedded
* within.
*/
struct param_entry params[] = {
{
.id = MORSE_CMD_PARAM_ID_MAX_TRAFFIC_DELIVERY_WAIT_US,
.name = "traffic_delivery_wait",
.help = "Time to wait for traffic delivery from the AP after the TIM "
"is set in a busy BSS (usecs).",
.min_val = 0,
.max_val = UINT32_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_EXTRA_ACK_TIMEOUT_ADJUST_US,
.name = "ack_timeout_adjust",
.help = "Extra time to wait for 802.11 control response frames to be "
"delivered (usecs).",
.min_val = 0,
.max_val = UINT32_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_WAKE_ACTION_GPIO,
.name = "wake_action_gpio",
.help = "Specify GPIO to pulse on reception of a Morse Micro "
"wake action frame (-1 to disable).",
.min_val = (uint32_t) -1,
.max_val = INT32_MAX,
.set_fn = param_set_int32,
.get_fn = param_get_int32,
},
{
.id = MORSE_CMD_PARAM_ID_WAKE_ACTION_GPIO_PULSE_MS,
.name = "wake_action_gpio_pulse",
.help = "Time to hold wake action GPIO high after reception of "
"a Morse Micro wake action frame (msecs).",
.min_val = 50,
.max_val = UINT32_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_CONNECTION_MONITOR_GPIO,
.name = "connection_monitor_gpio",
.help = "Specify GPIO that monitors and reflects device's "
"802.11 connection status (-1 to disable).",
.min_val = (uint32_t) -1,
.max_val = INT32_MAX,
.set_fn = param_set_int32,
.get_fn = param_get_int32,
},
{
.id = MORSE_CMD_PARAM_ID_INPUT_TRIGGER_GPIO,
.name = "input_trigger_gpio",
.help = "Specify GPIO that listens for an input signal to "
"wake an external host (-1 to disable).",
.min_val = (uint32_t) -1,
.max_val = INT32_MAX,
.set_fn = param_set_int32,
.get_fn = param_get_int32,
},
{
.id = MORSE_CMD_PARAM_ID_INPUT_TRIGGER_MODE,
.name = "input_trigger_mode",
.help = "Specify the active mode (high or low) for the trigger GPIO",
.min_val = (uint32_t) -1,
.max_val = INT32_MAX,
.set_fn = param_set_int32,
.get_fn = param_get_int32,
},
{
.id = MORSE_CMD_PARAM_ID_NON_TIM_MODE,
.name = "non_tim_mode",
.help = "Enable non-TIM mode (must be run before association)",
.min_val = 0,
.max_val = 1,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_DYNAMIC_PS_TIMEOUT_MS,
.name = "dynamic_ps_timeout_ms",
.help = "Dynamic powersave timeout (in ms) after network activity",
.min_val = 0,
.max_val = UINT32_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_DEFAULT_ACTIVE_SCAN_DWELL_MS,
.name = "active_scan_dwell_ms",
.help = "Default time to dwell on each channel in a scan list during active scans (ms)",
.min_val = 30,
.max_val = UINT32_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_HOME_CHANNEL_DWELL_MS,
.name = "home_channel_dwell_ms",
.help = "Time to dwell on home channel during scans while associated (ms)",
.min_val = 0,
.max_val = UINT32_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_BEACON_LOSS_COUNT,
.name = "beacon_loss_count",
.help = "Number of lost beacons before a beacon loss event is triggered",
.min_val = 1,
.max_val = UINT8_MAX,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_AP_POWER_SAVE,
.name = "ap_power_save",
.help = "Enable power save on an AP interface",
.min_val = 0,
.max_val = 1,
.set_fn = param_set_uint32,
.get_fn = param_get_uint32,
},
{
.id = MORSE_CMD_PARAM_ID_CHANNELIZATION,
.name = "channelization",
.help = "Query channelization scheme - for internal use by hostapd/wpa_supplicant",
.min_val = 0,
.max_val = 256,
.set_fn = NULL,
.get_fn = param_get_uint32,
},
};
static int get_line(const char **start, const char *end)
{
const int max_len = 60; /* Max line length after leading tabs */
int len = 0;
int last_space = max_len + 1;
const char *p;
char *eol = MIN((char *)end, (char *)(*start) + max_len);
/* Find first char to print on this line */
while ((*start < eol) && ((**start == ' ') || (**start == '\n')))
{
(*start)++;
}
p = *start;
/* Search up to the max characters that can be printed for a line
* termination or end-of-text.
* Keep track of the last space found, so the text is not split in the
* middle of a word.
*/
while (p <= eol)
{
if (*p == '\0' || *p == '\n')
{
return len;
}
if (*p == ' ')
{
last_space = len;
}
len++;
p++;
}
return MIN(last_space, len);
}
static void print_param_help(const struct param_entry* param)
{
const char *prefix = " ";
const char *start = param->help;
const char *end = start + strlen(param->help);
int len = 0;
len = get_line(&start, end);
while (start < end)
{
mctrl_print("%s%.*s\n", prefix, len, start);
start += len;
len = get_line(&start, end);
}
}
int set_help(void)
{
mctrl_print(" Available parameters:\n");
for (unsigned int entry = 0; entry < MORSE_ARRAY_SIZE(params); entry++)
{
const struct param_entry* param = ¶ms[entry];
if (param->set_fn == NULL)
{
continue;
}
mctrl_print(" %s\n", param->name);
print_param_help(param);
}
return 0;
}
int get_help(void)
{
mctrl_print(" Available parameters:\n");
for (unsigned int entry = 0; entry < MORSE_ARRAY_SIZE(params); entry++)
{
const struct param_entry* param = ¶ms[entry];
if (param->get_fn == NULL)
{
continue;
}
mctrl_print(" %s\n", param->name);
print_param_help(param);
}
return 0;
}
static const struct param_entry* match_str_to_param(const char *str,
enum morse_cmd_param_action action)
{
for (unsigned int entry = 0; entry < MORSE_ARRAY_SIZE(params); entry++)
{
const struct param_entry* param = ¶ms[entry];
if (strncmp(str, param->name, strlen(str)) == 0)
{
if ((action == MORSE_CMD_PARAM_ACTION_SET) && (param->set_fn == NULL))
{
break;
}
if ((action == MORSE_CMD_PARAM_ACTION_GET) && (param->get_fn == NULL))
{
break;
}
return param;
}
}
return NULL;
}
static void param_help(struct morsectrl *mors, enum morse_cmd_param_action action)
{
if (action == MORSE_CMD_PARAM_ACTION_SET)
{
set_help();
}
else if (action == MORSE_CMD_PARAM_ACTION_GET)
{
get_help();
}
}
static int param_get_set(struct morsectrl *mors,
enum morse_cmd_param_action action, int argc, char *argv[])
{
int ret = MORSE_ARG_ERR;
const struct param_entry *param;
struct morse_cmd_req_get_set_generic_param *req;
struct morse_cmd_resp_get_set_generic_param *rsp;
struct morsectrl_transport_buff *req_tbuff;
struct morsectrl_transport_buff *rsp_tbuff;
param = match_str_to_param(args.param->sval[0], action);
if (param == NULL)
{
mctrl_err("Invalid parameter: '%s'\n", args.param->sval[0]);
param_help(mors, action);
return ret;
}
req_tbuff = morsectrl_transport_cmd_alloc(mors->transport, sizeof(*req));
rsp_tbuff = morsectrl_transport_resp_alloc(mors->transport, sizeof(*rsp));
if (!req_tbuff || !rsp_tbuff)
goto exit;
req = TBUFF_TO_REQ(req_tbuff, struct morse_cmd_req_get_set_generic_param);
rsp = TBUFF_TO_RSP(rsp_tbuff, struct morse_cmd_resp_get_set_generic_param);
req->param_id = htole32(param->id);
req->action = htole32(action);
req->flags = 0;
if (action == MORSE_CMD_PARAM_ACTION_SET)
{
ret = param->set_fn(param, args.value->sval[0], req);
if (ret < 0)
{
goto exit;
}
}
ret = morsectrl_send_command(mors->transport,
MORSE_CMD_ID_GET_SET_GENERIC_PARAM, req_tbuff, rsp_tbuff);
exit:
if (ret == 0)
{
if (action == MORSE_CMD_PARAM_ACTION_GET)
{
param->get_fn(param, rsp);
}
}
else
{
ret = -MORSE_CMD_ERR;
}
morsectrl_transport_buff_free(req_tbuff);
morsectrl_transport_buff_free(rsp_tbuff);
return ret;
}
int get(struct morsectrl *mors, int argc, char *argv[])
{
return param_get_set(mors, MORSE_CMD_PARAM_ACTION_GET, argc, argv);
}
int set(struct morsectrl *mors, int argc, char *argv[])
{
return param_get_set(mors, MORSE_CMD_PARAM_ACTION_SET, argc, argv);
}
MM_CLI_HANDLER_CUSTOM_HELP(get, MM_INTF_REQUIRED, MM_DIRECT_CHIP_SUPPORTED);
MM_CLI_HANDLER_CUSTOM_HELP(set, MM_INTF_REQUIRED, MM_DIRECT_CHIP_SUPPORTED);