|
@@ -50,6 +50,10 @@ static struct pdb_config tmpcfg = {
|
50
|
50
|
.status = PDB_CONFIG_STATUS_VALID
|
51
|
51
|
};
|
52
|
52
|
|
|
53
|
+/*
|
|
54
|
+ * Command functions
|
|
55
|
+ */
|
|
56
|
+
|
53
|
57
|
static void cmd_license(BaseSequentialStream *chp, int argc, char *argv[])
|
54
|
58
|
{
|
55
|
59
|
(void) argv;
|
|
@@ -237,6 +241,9 @@ static void cmd_identify(BaseSequentialStream *chp, int argc, char *argv[])
|
237
|
241
|
chEvtSignal(pdb_led_thread, PDB_EVT_LED_IDENTIFY);
|
238
|
242
|
}
|
239
|
243
|
|
|
244
|
+/*
|
|
245
|
+ * List of shell commands
|
|
246
|
+ */
|
240
|
247
|
static const struct pdb_shell_cmd commands[] = {
|
241
|
248
|
{"license", cmd_license, "Show copyright and license information"},
|
242
|
249
|
{"erase", cmd_erase, "Erase all stored configuration"},
|
|
@@ -254,6 +261,9 @@ static const struct pdb_shell_cmd commands[] = {
|
254
|
261
|
{NULL, NULL, NULL}
|
255
|
262
|
};
|
256
|
263
|
|
|
264
|
+/*
|
|
265
|
+ * The shell's configuration
|
|
266
|
+ */
|
257
|
267
|
const struct pdb_shell_cfg shell_cfg = {
|
258
|
268
|
(BaseSequentialStream *)&SDU1,
|
259
|
269
|
commands
|
|
@@ -302,9 +312,7 @@ static bool cmdexec(const struct pdb_shell_cmd *scp, BaseSequentialStream *chp,
|
302
|
312
|
}
|
303
|
313
|
|
304
|
314
|
/*
|
305
|
|
- * PD Buddy configuration shell
|
306
|
|
- *
|
307
|
|
- * p: The configuration for the shell itself
|
|
315
|
+ * PD Buddy Sink configuration shell
|
308
|
316
|
*/
|
309
|
317
|
void pdb_shell(void)
|
310
|
318
|
{
|
|
@@ -315,15 +323,22 @@ void pdb_shell(void)
|
315
|
323
|
char *args[PDB_SHELL_MAX_ARGUMENTS + 1];
|
316
|
324
|
|
317
|
325
|
while (true) {
|
|
326
|
+ /* Print the prompt */
|
318
|
327
|
chprintf(chp, "PDBS) ");
|
|
328
|
+
|
|
329
|
+ /* Read a line of input */
|
319
|
330
|
if (shellGetLine(chp, line, sizeof(line))) {
|
|
331
|
+ /* If a command was not entered, prompt again */
|
320
|
332
|
chprintf(chp, "\r\n");
|
321
|
333
|
continue;
|
322
|
334
|
}
|
|
335
|
+
|
|
336
|
+ /* Tokenize the line */
|
323
|
337
|
lp = _strtok(line, " \t", &tokp);
|
324
|
338
|
cmd = lp;
|
325
|
339
|
n = 0;
|
326
|
340
|
while ((lp = _strtok(NULL, " \t", &tokp)) != NULL) {
|
|
341
|
+ /* If we have too many tokens, abort */
|
327
|
342
|
if (n >= PDB_SHELL_MAX_ARGUMENTS) {
|
328
|
343
|
chprintf(chp, "too many arguments\r\n");
|
329
|
344
|
cmd = NULL;
|
|
@@ -332,7 +347,10 @@ void pdb_shell(void)
|
332
|
347
|
args[n++] = lp;
|
333
|
348
|
}
|
334
|
349
|
args[n] = NULL;
|
|
350
|
+
|
|
351
|
+ /* If there's a command to run, run it */
|
335
|
352
|
if (cmd != NULL) {
|
|
353
|
+ /* Handle "help" in a special way */
|
336
|
354
|
if (strcmp(cmd, "help") == 0) {
|
337
|
355
|
if (n > 0) {
|
338
|
356
|
chprintf(chp, "Usage: help\r\n");
|
|
@@ -344,6 +362,8 @@ void pdb_shell(void)
|
344
|
362
|
if (scp != NULL)
|
345
|
363
|
list_commands(chp, scp);
|
346
|
364
|
}
|
|
365
|
+ /* Run a command, giving a generic error message if there is no
|
|
366
|
+ * such command */
|
347
|
367
|
else if ((scp == NULL) || cmdexec(scp, chp, cmd, n, args)) {
|
348
|
368
|
chprintf(chp, "%s", cmd);
|
349
|
369
|
chprintf(chp, " ?\r\n");
|
|
@@ -372,13 +392,16 @@ bool shellGetLine(BaseSequentialStream *chp, char *line, unsigned size)
|
372
|
392
|
while (true) {
|
373
|
393
|
char c;
|
374
|
394
|
|
|
395
|
+ /* Read a character */
|
375
|
396
|
if (chSequentialStreamRead(chp, (uint8_t *)&c, 1) == 0)
|
376
|
397
|
return true;
|
377
|
|
- if (c == 4) {
|
|
398
|
+ /* Abort if ^D is received */
|
|
399
|
+ if (c == '\x04') {
|
378
|
400
|
chprintf(chp, "^D");
|
379
|
401
|
return true;
|
380
|
402
|
}
|
381
|
|
- if ((c == 8) || (c == 127)) {
|
|
403
|
+ /* Delete a character if ASCII backspace or delete is received */
|
|
404
|
+ if ((c == '\b') || (c == '\x7F')) {
|
382
|
405
|
if (p != line) {
|
383
|
406
|
chSequentialStreamPut(chp, 0x08);
|
384
|
407
|
chSequentialStreamPut(chp, 0x20);
|
|
@@ -387,13 +410,16 @@ bool shellGetLine(BaseSequentialStream *chp, char *line, unsigned size)
|
387
|
410
|
}
|
388
|
411
|
continue;
|
389
|
412
|
}
|
|
413
|
+ /* Finish reading input if Enter is pressed */
|
390
|
414
|
if (c == '\r') {
|
391
|
415
|
chprintf(chp, "\r\n");
|
392
|
416
|
*p = 0;
|
393
|
417
|
return false;
|
394
|
418
|
}
|
395
|
|
- if (c < 0x20)
|
|
419
|
+ /* Ignore other non-printing characters */
|
|
420
|
+ if (c < ' ')
|
396
|
421
|
continue;
|
|
422
|
+ /* If there's room in the line buffer, append the new character */
|
397
|
423
|
if (p < line + size - 1) {
|
398
|
424
|
chSequentialStreamPut(chp, c);
|
399
|
425
|
*p++ = (char)c;
|