Subversion Repositories svn.mios32

Rev

Rev 1264 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1260 tk 1
// $Id: terminal.c 1260 2011-07-16 23:09:53Z tk $
2
/*
3
 * The command/configuration Terminal
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2010 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
19
#include <string.h>
20
 
21
#include "app.h"
22
#include "midio_patch.h"
23
#include "terminal.h"
24
#include "midimon.h"
25
#include "uip.h"
26
#include "uip_task.h"
27
#include "tasks.h"
28
#include "osc_server.h"
29
#include "midio_file.h"
30
#include "midio_file_p.h"
31
 
32
/////////////////////////////////////////////////////////////////////////////
33
// Local defines
34
/////////////////////////////////////////////////////////////////////////////
35
 
36
#define STRING_MAX 80
37
 
38
 
39
/////////////////////////////////////////////////////////////////////////////
40
// Local variables
41
/////////////////////////////////////////////////////////////////////////////
42
 
43
static char line_buffer[STRING_MAX];
44
static u16 line_ix;
45
 
46
 
47
/////////////////////////////////////////////////////////////////////////////
48
// Local prototypes
49
/////////////////////////////////////////////////////////////////////////////
50
 
51
static s32 TERMINAL_PrintSystem(void *_output_function);
52
static s32 TERMINAL_PrintIPs(void *_output_function);
53
 
54
 
55
/////////////////////////////////////////////////////////////////////////////
56
// Initialisation
57
/////////////////////////////////////////////////////////////////////////////
58
s32 TERMINAL_Init(u32 mode)
59
{
60
  // install the callback function which is called on incoming characters
61
  // from MIOS Terminal
62
  MIOS32_MIDI_DebugCommandCallback_Init(TERMINAL_Parse);
63
 
64
  // clear line buffer
65
  line_buffer[0] = 0;
66
  line_ix = 0;
67
 
68
  return 0; // no error
69
}
70
 
71
 
72
/////////////////////////////////////////////////////////////////////////////
73
// help function which parses a decimal or hex value
74
// returns >= 0 if value is valid
75
// returns -1 if value is invalid
76
/////////////////////////////////////////////////////////////////////////////
77
static s32 get_dec(char *word)
78
{
79
  if( word == NULL )
80
    return -1;
81
 
82
  char *next;
83
  long l = strtol(word, &next, 0);
84
 
85
  if( word == next )
86
    return -1;
87
 
88
  return l; // value is valid
89
}
90
 
91
 
92
/////////////////////////////////////////////////////////////////////////////
93
// help function which parses for on or off
94
// returns 0 if 'off', 1 if 'on', -1 if invalid
95
/////////////////////////////////////////////////////////////////////////////
96
static s32 get_on_off(char *word)
97
{
98
  if( strcmp(word, "on") == 0 )
99
    return 1;
100
 
101
  if( strcmp(word, "off") == 0 )
102
    return 0;
103
 
104
  return -1;
105
}
106
 
107
 
108
/////////////////////////////////////////////////////////////////////////////
109
// help function which parses an IP value
110
// returns > 0 if value is valid
111
// returns 0 if value is invalid
112
/////////////////////////////////////////////////////////////////////////////
113
static u32 get_ip(char *word)
114
{
115
  char *brkt;
116
  u8 ip[4];
117
 
118
  int i;
119
  for(i=0; i<4; ++i) {
120
    if( (word = strtok_r((i == 0) ? word : NULL, ".", &brkt)) ) {
121
      s32 value = get_dec(word);
122
      if( value >= 0 && value <= 255 )
123
    ip[i] = value;
124
      else
125
    return 0;
126
    }
127
  }
128
 
129
  if( i == 4 )
130
    return (ip[0]<<24)|(ip[1]<<16)|(ip[2]<<8)|(ip[3]<<0);
131
  else
132
    return 0; // invalid IP
133
}
134
 
135
 
136
/////////////////////////////////////////////////////////////////////////////
137
// Parser
138
/////////////////////////////////////////////////////////////////////////////
139
s32 TERMINAL_Parse(mios32_midi_port_t port, u8 byte)
140
{
141
  // temporary change debug port (will be restored at the end of this function)
142
  mios32_midi_port_t prev_debug_port = MIOS32_MIDI_DebugPortGet();
143
  MIOS32_MIDI_DebugPortSet(port);
144
 
145
  if( byte == '\r' ) {
146
    // ignore
147
  } else if( byte == '\n' ) {
148
    MUTEX_MIDIOUT_TAKE;
149
    TERMINAL_ParseLine(line_buffer, MIOS32_MIDI_SendDebugMessage);
150
    MUTEX_MIDIOUT_GIVE;
151
    line_ix = 0;
152
    line_buffer[line_ix] = 0;
153
  } else if( line_ix < (STRING_MAX-1) ) {
154
    line_buffer[line_ix++] = byte;
155
    line_buffer[line_ix] = 0;
156
  }
157
 
158
  // restore debug port
159
  MIOS32_MIDI_DebugPortSet(prev_debug_port);
160
 
161
  return 0; // no error
162
}
163
 
164
 
165
/////////////////////////////////////////////////////////////////////////////
166
// Parser for a complete line - also used by shell.c for telnet
167
/////////////////////////////////////////////////////////////////////////////
168
s32 TERMINAL_ParseLine(char *input, void *_output_function)
169
{
170
  void (*out)(char *format, ...) = _output_function;
171
  char *separators = " \t";
172
  char *brkt;
173
  char *parameter;
174
 
175
  if( (parameter = strtok_r(input, separators, &brkt)) ) {
176
    if( strcmp(parameter, "help") == 0 ) {
177
      out("Welcome to " MIOS32_LCD_BOOT_MSG_LINE1 "!");
178
      out("Following commands are available:");
179
      out("  system:                           print system info");
180
      out("  set dhcp <on|off>:                enables/disables DHCP");
181
      out("  set ip <address>:                 changes IP address");
182
      out("  set netmask <mask>:               changes netmask");
183
      out("  set gateway <address>:            changes gateway address");
184
      out("  set osc_remote <con> <address>:   changes OSC Remote Address");
185
      out("  set osc_remote_port <con> <port>: changes OSC Remote Port (1024..65535)");
186
      out("  set osc_local_port <con> <port>:  changes OSC Local Port (1024..65535)");
187
      out("  set udpmon <0..4>:                enables UDP monitor to check OSC packets (current: %d)\n", UIP_TASK_UDP_MonitorLevelGet());
188
      out("  set midimon <on|off>:             enables/disables the MIDI monitor");
189
      out("  set midimon_filter <on|off>:      enables/disables MIDI monitor filters");
190
      out("  set midimon_tempo <on|off>:       enables/disables the tempo display");
191
      out("  set dout <pin> <0|1>:             directly sets the DOUT pin (all or 0..%d) to the given level (1 or 0)", MIOS32_SRIO_NUM_SR*8 - 1);
192
      out("  store:                            stores current config on SD Card");
193
      out("  restore:                          restores config from SD Card");
194
      out("  show:                             shows the current configuration file");
195
      out("  reset:                            resets the MIDIbox (!)\n");
196
      out("  help:                             this page");
197
      out("  exit:                             (telnet only) exits the terminal");
198
    } else if( strcmp(parameter, "system") == 0 ) {
199
      TERMINAL_PrintSystem(_output_function);
200
    } else if( strcmp(parameter, "store") == 0 ) {
201
      s32 status = MIDIO_PATCH_Store(0, 0);
202
      if( status >= 0 ) {
203
    out("Presets stored on SD Card!");
204
      } else {
205
    out("ERROR: failed to store presets on SD Card (status %d)!", status);
206
      }
207
    } else if( strcmp(parameter, "restore") == 0 ) {
208
      s32 status = MIDIO_PATCH_Load(0, 0);
209
      if( status >= 0 ) {
210
    out("Presets restored from SD Card!");
211
      } else {
212
    out("ERROR: failed to restore presets from SD Card (status %d)!", status);
213
      }
214
    } else if( strcmp(parameter, "show") == 0 ) {
215
      MIDIO_FILE_P_Debug();
216
    } else if( strcmp(parameter, "reset") == 0 ) {
217
      MIOS32_SYS_Reset();
218
    } else if( strcmp(parameter, "set") == 0 ) {
219
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
220
    if( strcmp(parameter, "dhcp") == 0 ) {
221
      s32 on_off = -1;
222
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
223
        on_off = get_on_off(parameter);
224
 
225
      if( on_off < 0 ) {
226
        out("Expecting 'on' or 'off'!");
227
      } else {
228
        UIP_TASK_DHCP_EnableSet(on_off);
229
        if( UIP_TASK_DHCP_EnableGet() ) {
230
          out("DHCP enabled - waiting for IP address from server!\n");
231
        } else {
232
          out("DHCP disabled - using predefined values:");
233
          TERMINAL_PrintIPs(_output_function);
234
        }
235
      }
236
    } else if( strcmp(parameter, "ip") == 0 ) {
237
      if( UIP_TASK_DHCP_EnableGet() ) {
238
        out("ERROR: DHCP enabled - please disable it first via 'set dhcp off'");
239
      } else {
240
        u32 ip = 0;
241
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
242
          ip = get_ip(parameter);
243
        if( !ip ) {
244
          out("Expecting IP address in format a.b.c.d!");
245
        } else {
246
          uip_ipaddr_t ipaddr;
247
          UIP_TASK_IP_AddressSet(ip);
248
          uip_gethostaddr(&ipaddr);
249
          out("Set IP address to %d.%d.%d.%d",
250
          uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
251
          uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
252
        }
253
      }
254
    } else if( strcmp(parameter, "netmask") == 0 ) {
255
      if( UIP_TASK_DHCP_EnableGet() ) {
256
        out("ERROR: DHCP enabled - please disable it first via 'set dhcp off'");
257
      } else {
258
        u32 ip = 0;
259
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
260
          ip = get_ip(parameter);
261
        if( !ip ) {
262
          out("Expecting netmask in format a.b.c.d!");
263
        } else {
264
          uip_ipaddr_t ipaddr;
265
          UIP_TASK_NetmaskSet(ip);
266
          uip_getnetmask(&ipaddr);
267
          out("Set netmask to %d.%d.%d.%d",
268
          uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
269
          uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
270
        }
271
      }
272
    } else if( strcmp(parameter, "gateway") == 0 ) {
273
      if( UIP_TASK_DHCP_EnableGet() ) {
274
        out("ERROR: DHCP enabled - please disable it first via 'set dhcp off'");
275
      } else {
276
        u32 ip = 0;
277
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
278
          ip = get_ip(parameter);
279
        if( !ip ) {
280
          out("Expecting gateway address in format a.b.c.d!");
281
        } else {
282
          uip_ipaddr_t ipaddr;
283
          UIP_TASK_GatewaySet(ip);
284
          uip_getdraddr(&ipaddr);
285
          out("Set gateway to %d.%d.%d.%d",
286
          uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
287
          uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
288
        }
289
      }
290
    } else if( strcmp(parameter, "osc_remote") == 0 ) {
291
      if( !UIP_TASK_ServicesRunning() ) {
292
        out("ERROR: Ethernet services not running yet!");
293
      } else {
294
        s32 con = -1;
295
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
296
          con = get_dec(parameter);
297
        if( con < 1 || con >= OSC_SERVER_NUM_CONNECTIONS) {
298
          out("Invalid OSC connection specified as first parameter (expecting 1..%d)!", OSC_SERVER_NUM_CONNECTIONS);
299
        } else {
300
          con+=1; // the user counts from 1
301
 
302
          u32 ip = 0;
303
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
304
        ip = get_ip(parameter);
305
          if( !ip ) {
306
        out("Expecting OSC connection <1..%d> and remote address in format a.b.c.d!", OSC_SERVER_NUM_CONNECTIONS);
307
          } else {
308
        if( OSC_SERVER_RemoteIP_Set(con, ip) >= 0 )
309
          out("Set OSC Remote address to %d.%d.%d.%d",
310
              (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, (ip>>0)&0xff);
311
        else
312
          out("ERROR: failed to set OSC Remote address!");
313
          }
314
        }
315
      }
316
    } else if( strcmp(parameter, "osc_remote_port") == 0 ) {
317
      if( !UIP_TASK_ServicesRunning() ) {
318
        out("ERROR: Ethernet services not running yet!");
319
      } else {
320
        s32 con = -1;
321
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
322
          con = get_dec(parameter);
323
        if( con < 1 || con >= OSC_SERVER_NUM_CONNECTIONS) {
324
          out("Invalid OSC connection specified as first parameter (expecting 1..%d)!", OSC_SERVER_NUM_CONNECTIONS);
325
        } else {
326
          con+=1; // the user counts from 1
327
 
328
          s32 value = -1;
329
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
330
        value = get_dec(parameter);
331
          if( value < 1024 || value >= 65535) {
332
        out("Expecting OSC connection (1..%d) and remote port value in range 1024..65535", OSC_SERVER_NUM_CONNECTIONS);
333
          } else {
334
        if( OSC_SERVER_RemotePortSet(con, value) >= 0 )
335
          out("Set OSC Remote port to %d", value);
336
        else
337
          out("ERROR: failed to set OSC remote port!");
338
          }
339
        }
340
      }
341
    } else if( strcmp(parameter, "osc_local_port") == 0 ) {
342
      if( !UIP_TASK_ServicesRunning() ) {
343
        out("ERROR: Ethernet services not running yet!");
344
      } else {
345
        s32 con = -1;
346
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
347
          con = get_dec(parameter);
348
        if( con < 1 || con >= OSC_SERVER_NUM_CONNECTIONS) {
349
          out("Invalid OSC connection specified as first parameter (expecting 1..%d)!", OSC_SERVER_NUM_CONNECTIONS);
350
        } else {
351
          con+=1; // the user counts from 1
352
 
353
          s32 value = -1;
354
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
355
        value = get_dec(parameter);
356
          if( value < 1024 || value >= 65535) {
357
        out("Expecting OSC connection (1..%d) and local port value in range 1024..65535", OSC_SERVER_NUM_CONNECTIONS);
358
          } else {
359
        if( OSC_SERVER_LocalPortSet(con, value) >= 0 )
360
          out("Set OSC Local port to %d", value);
361
        else
362
          out("ERROR: failed to set OSC local port!");
363
          }
364
        }
365
      }
366
    } else if( strcmp(parameter, "udpmon") == 0 ) {
367
      char *arg;
368
      if( (arg = strtok_r(NULL, separators, &brkt)) ) {
369
        int level = get_dec(arg);
370
        switch( level ) {
371
        case UDP_MONITOR_LEVEL_0_OFF:
372
          out("Set UDP monitor level to %d (off)\n", level);
373
          break;
374
        case UDP_MONITOR_LEVEL_1_OSC_REC:
375
          out("Set UDP monitor level to %d (received packets assigned to a OSC1..4 port)\n", level);
376
          break;
377
        case UDP_MONITOR_LEVEL_2_OSC_REC_AND_SEND:
378
          out("Set UDP monitor level to %d (received and sent packets assigned to a OSC1..4 port)\n", level);
379
          break;
380
        case UDP_MONITOR_LEVEL_3_ALL_GEQ_1024:
381
          out("Set UDP monitor level to %d (all received and sent packets with port number >= 1024)\n", level);
382
          break;
383
        case UDP_MONITOR_LEVEL_4_ALL:
384
          out("Set UDP monitor level to %d (all received and sent packets)\n", level);
385
          break;
386
        default:
387
          out("Invalid level %d - please specify monitor level 0..4\n", level);
388
          level = -1; // invalidate level for next if() check
389
        }
390
 
391
        if( level >= 0 )
392
          UIP_TASK_UDP_MonitorLevelSet(level);
393
      } else {
394
        out("Please specify monitor level (0..4)\n");
395
      }
396
    } else if( strcmp(parameter, "midimon") == 0 ) {
397
      s32 on_off = -1;
398
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
399
        on_off = get_on_off(parameter);
400
 
401
      if( on_off < 0 ) {
402
        out("Expecting 'on' or 'off'!");
403
      } else {
404
        MIDIMON_ActiveSet(on_off);
405
        out("MIDI Monitor %s!", MIDIMON_ActiveGet() ? "enabled" : "disabled");
406
      }
407
    } else if( strcmp(parameter, "midimon_filter") == 0 ) {
408
      s32 on_off = -1;
409
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
410
        on_off = get_on_off(parameter);
411
 
412
      if( on_off < 0 ) {
413
        out("Expecting 'on' or 'off'!");
414
      } else {
415
        MIDIMON_FilterActiveSet(on_off);
416
        out("MIDI Monitor Filter %s!", MIDIMON_FilterActiveGet() ? "enabled" : "disabled");
417
      }
418
    } else if( strcmp(parameter, "midimon_tempo") == 0 ) {
419
      s32 on_off = -1;
420
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
421
        on_off = get_on_off(parameter);
422
 
423
      if( on_off < 0 ) {
424
        out("Expecting 'on' or 'off'!");
425
      } else {
426
        MIDIMON_TempoActiveSet(on_off);
427
        out("MIDI Monitor Tempo Display %s!", MIDIMON_TempoActiveGet() ? "enabled" : "disabled");
428
      }
429
    } else if( strcmp(parameter, "dout") == 0 ) {
430
      s32 pin = -1;
431
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
432
        if( strcmp(parameter, "all") == 0 ) {
433
          pin = -42;
434
        } else {
435
          pin = get_dec(parameter);
436
        }
437
      }
438
 
439
      if( (pin < 0 && pin != -42) || pin >= (MIOS32_SRIO_NUM_SR*8) ) {
440
        out("Pin number should be between 0..%d", MIOS32_SRIO_NUM_SR*8 - 1);
441
      } else {
442
        s32 value = -1;
443
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
444
          value = get_dec(parameter);
445
 
446
        if( value < 0 || value > 1 ) {
447
          out("Expecting value 1 or 0 for DOUT pin %d", pin);
448
        } else {
449
          if( pin == -42 ) {
450
        for(pin=0; pin<(MIOS32_SRIO_NUM_SR*8); ++pin)
451
          MIOS32_DOUT_PinSet(pin, value);
452
        out("All DOUT pins set to %d", value);
453
          } else {
454
        MIOS32_DOUT_PinSet(pin, value);
455
        out("DOUT Pin %d (SR#%d.D%d) set to %d", pin, (pin/8)+1, 7-(pin%8), value);
456
          }
457
        }
458
      }
459
    } else {
460
      out("Unknown set parameter: '%s'!", parameter);
461
    }
462
      } else {
463
    out("Missing parameter after 'set'!");
464
      }
465
    } else {
466
      out("Unknown command - type 'help' to list available commands!");
467
    }
468
  }
469
 
470
  return 0; // no error
471
}
472
 
473
 
474
/////////////////////////////////////////////////////////////////////////////
475
// System Informations
476
/////////////////////////////////////////////////////////////////////////////
477
static s32 TERMINAL_PrintSystem(void *_output_function)
478
{
479
  void (*out)(char *format, ...) = _output_function;
480
 
481
  out("Application: " MIOS32_LCD_BOOT_MSG_LINE1);
482
 
483
  out("Ethernet module connected: %s", UIP_TASK_NetworkDeviceAvailable() ? "yes" : "no");
484
  out("Ethernet services running: %s", UIP_TASK_ServicesRunning() ? "yes" : "no");
485
  out("DHCP: %s", UIP_TASK_DHCP_EnableGet() ? "enabled" : "disabled");
486
 
487
  if( UIP_TASK_DHCP_EnableGet() && !UIP_TASK_ServicesRunning() ) {
488
    out("IP address: not available yet");
489
    out("Netmask: not available yet");
490
    out("Default Router (Gateway): not available yet");
491
  } else {
492
    TERMINAL_PrintIPs(_output_function);
493
  }
494
 
495
  int con;
496
  for(con=0; con<OSC_SERVER_NUM_CONNECTIONS; ++con) {
497
    u32 osc_remote_ip = OSC_SERVER_RemoteIP_Get(con);
498
    out("OSC%d Remote address: %d.%d.%d.%d",
499
    con+1,
500
    (osc_remote_ip>>24)&0xff, (osc_remote_ip>>16)&0xff,
501
    (osc_remote_ip>>8)&0xff, (osc_remote_ip>>0)&0xff);
502
    out("OSC%d Remote port: %d", con+1, OSC_SERVER_RemotePortGet(con));
503
    out("OSC%d Local port: %d", con+1, OSC_SERVER_LocalPortGet(con));
504
  }
505
 
506
  out("UDP Monitor: verbose level #%d\n", UIP_TASK_UDP_MonitorLevelGet());
507
 
508
  out("MIDI Monitor: %s", MIDIMON_ActiveGet() ? "enabled" : "disabled");
509
  out("MIDI Monitor Filters: %s", MIDIMON_FilterActiveGet() ? "enabled" : "disabled");
510
  out("MIDI Monitor Tempo Display: %s", MIDIMON_TempoActiveGet() ? "enabled" : "disabled");
511
 
512
  return 0; // no error
513
}
514
 
515
 
516
 
517
/////////////////////////////////////////////////////////////////////////////
518
// Print IP settings (used by multiple functions)
519
/////////////////////////////////////////////////////////////////////////////
520
static s32 TERMINAL_PrintIPs(void *_output_function)
521
{
522
  void (*out)(char *format, ...) = _output_function;
523
 
524
  uip_ipaddr_t ipaddr;
525
  uip_gethostaddr(&ipaddr);
526
  out("IP address: %d.%d.%d.%d",
527
      uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
528
      uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
529
 
530
  uip_ipaddr_t netmask;
531
  uip_getnetmask(&netmask);
532
  out("Netmask: %d.%d.%d.%d",
533
      uip_ipaddr1(netmask), uip_ipaddr2(netmask),
534
      uip_ipaddr3(netmask), uip_ipaddr4(netmask));
535
 
536
  uip_ipaddr_t draddr;
537
  uip_getdraddr(&draddr);
538
  out("Default Router (Gateway): %d.%d.%d.%d",
539
      uip_ipaddr1(draddr), uip_ipaddr2(draddr),
540
      uip_ipaddr3(draddr), uip_ipaddr4(draddr));
541
 
542
  return 0; // no error
543
}