Subversion Repositories svn.mios32

Rev

Rev 1284 | Rev 1320 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1260 tk 1
// $Id: terminal.c 1292 2011-08-13 20:43:22Z 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)");
1284 tk 187
      out("  set udpmon <0..4>:                enables UDP monitor (verbose level: %d)\n", UIP_TASK_UDP_MonitorLevelGet());
1260 tk 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");
1292 tk 191
      out("  set dout <pin> <0|1>:             directly sets DOUT (all or 0..%d) to given level (1 or 0)", MIOS32_SRIO_NUM_SR*8 - 1);
1264 tk 192
      out("  save <name>:                      stores current config on SD Card");
193
      out("  load <name>:                      restores config from SD Card");
1260 tk 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);
1264 tk 200
    } else if( strcmp(parameter, "save") == 0 ) {
201
      if( !(parameter = strtok_r(NULL, separators, &brkt)) ) {
202
    out("ERROR: please specify filename for patch (up to 8 characters)!");
1260 tk 203
      } else {
1264 tk 204
    if( strlen(parameter) > 8 ) {
205
      out("ERROR: 8 characters maximum!");
206
    } else {
207
      s32 status = MIDIO_PATCH_Store(parameter);
208
      if( status >= 0 ) {
209
        out("Patch '%s' stored on SD Card!", parameter);
210
      } else {
211
        out("ERROR: failed to store patch '%s' on SD Card (status %d)!", parameter, status);
212
      }
213
    }
1260 tk 214
      }
1264 tk 215
    } else if( strcmp(parameter, "load") == 0 ) {
216
      if( !(parameter = strtok_r(NULL, separators, &brkt)) ) {
217
    out("ERROR: please specify filename for patch (up to 8 characters)!");
1260 tk 218
      } else {
1264 tk 219
    if( strlen(parameter) > 8 ) {
220
      out("ERROR: 8 characters maximum!");
221
    } else {
222
      s32 status = MIDIO_PATCH_Load(parameter);
223
      if( status >= 0 ) {
224
        out("Patch '%s' loaded from SD Card!", parameter);
225
      } else {
226
        out("ERROR: failed to load patch '%s' on SD Card (status %d)!", parameter, status);
227
      }
228
    }
1260 tk 229
      }
230
    } else if( strcmp(parameter, "show") == 0 ) {
231
      MIDIO_FILE_P_Debug();
232
    } else if( strcmp(parameter, "reset") == 0 ) {
233
      MIOS32_SYS_Reset();
234
    } else if( strcmp(parameter, "set") == 0 ) {
235
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
236
    if( strcmp(parameter, "dhcp") == 0 ) {
237
      s32 on_off = -1;
238
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
239
        on_off = get_on_off(parameter);
240
 
241
      if( on_off < 0 ) {
242
        out("Expecting 'on' or 'off'!");
243
      } else {
244
        UIP_TASK_DHCP_EnableSet(on_off);
245
        if( UIP_TASK_DHCP_EnableGet() ) {
246
          out("DHCP enabled - waiting for IP address from server!\n");
247
        } else {
248
          out("DHCP disabled - using predefined values:");
249
          TERMINAL_PrintIPs(_output_function);
250
        }
251
      }
252
    } else if( strcmp(parameter, "ip") == 0 ) {
253
      if( UIP_TASK_DHCP_EnableGet() ) {
254
        out("ERROR: DHCP enabled - please disable it first via 'set dhcp off'");
255
      } else {
256
        u32 ip = 0;
257
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
258
          ip = get_ip(parameter);
259
        if( !ip ) {
260
          out("Expecting IP address in format a.b.c.d!");
261
        } else {
262
          uip_ipaddr_t ipaddr;
263
          UIP_TASK_IP_AddressSet(ip);
264
          uip_gethostaddr(&ipaddr);
265
          out("Set IP address to %d.%d.%d.%d",
266
          uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
267
          uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
268
        }
269
      }
270
    } else if( strcmp(parameter, "netmask") == 0 ) {
271
      if( UIP_TASK_DHCP_EnableGet() ) {
272
        out("ERROR: DHCP enabled - please disable it first via 'set dhcp off'");
273
      } else {
274
        u32 ip = 0;
275
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
276
          ip = get_ip(parameter);
277
        if( !ip ) {
278
          out("Expecting netmask in format a.b.c.d!");
279
        } else {
280
          uip_ipaddr_t ipaddr;
281
          UIP_TASK_NetmaskSet(ip);
282
          uip_getnetmask(&ipaddr);
283
          out("Set netmask to %d.%d.%d.%d",
284
          uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
285
          uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
286
        }
287
      }
288
    } else if( strcmp(parameter, "gateway") == 0 ) {
289
      if( UIP_TASK_DHCP_EnableGet() ) {
290
        out("ERROR: DHCP enabled - please disable it first via 'set dhcp off'");
291
      } else {
292
        u32 ip = 0;
293
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
294
          ip = get_ip(parameter);
295
        if( !ip ) {
296
          out("Expecting gateway address in format a.b.c.d!");
297
        } else {
298
          uip_ipaddr_t ipaddr;
299
          UIP_TASK_GatewaySet(ip);
300
          uip_getdraddr(&ipaddr);
301
          out("Set gateway to %d.%d.%d.%d",
302
          uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
303
          uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
304
        }
305
      }
306
    } else if( strcmp(parameter, "osc_remote") == 0 ) {
307
      if( !UIP_TASK_ServicesRunning() ) {
308
        out("ERROR: Ethernet services not running yet!");
309
      } else {
310
        s32 con = -1;
311
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
312
          con = get_dec(parameter);
313
        if( con < 1 || con >= OSC_SERVER_NUM_CONNECTIONS) {
314
          out("Invalid OSC connection specified as first parameter (expecting 1..%d)!", OSC_SERVER_NUM_CONNECTIONS);
315
        } else {
1284 tk 316
          con-=1; // the user counts from 1
1260 tk 317
 
318
          u32 ip = 0;
319
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
320
        ip = get_ip(parameter);
321
          if( !ip ) {
322
        out("Expecting OSC connection <1..%d> and remote address in format a.b.c.d!", OSC_SERVER_NUM_CONNECTIONS);
323
          } else {
1284 tk 324
        if( OSC_SERVER_RemoteIP_Set(con, ip) >= 0 ) {
325
          out("Set OSC%d Remote address to %d.%d.%d.%d",
326
              con+1,
1260 tk 327
              (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, (ip>>0)&0xff);
1284 tk 328
          OSC_SERVER_Init(0);
329
        } else
330
          out("ERROR: failed to set OSC%d Remote address!", con+1);
1260 tk 331
          }
332
        }
333
      }
334
    } else if( strcmp(parameter, "osc_remote_port") == 0 ) {
335
      if( !UIP_TASK_ServicesRunning() ) {
336
        out("ERROR: Ethernet services not running yet!");
337
      } else {
338
        s32 con = -1;
339
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
340
          con = get_dec(parameter);
341
        if( con < 1 || con >= OSC_SERVER_NUM_CONNECTIONS) {
342
          out("Invalid OSC connection specified as first parameter (expecting 1..%d)!", OSC_SERVER_NUM_CONNECTIONS);
343
        } else {
1284 tk 344
          con-=1; // the user counts from 1
1260 tk 345
 
346
          s32 value = -1;
347
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
348
        value = get_dec(parameter);
349
          if( value < 1024 || value >= 65535) {
350
        out("Expecting OSC connection (1..%d) and remote port value in range 1024..65535", OSC_SERVER_NUM_CONNECTIONS);
351
          } else {
1284 tk 352
        if( OSC_SERVER_RemotePortSet(con, value) >= 0 ) {
353
          out("Set OSC%d Remote port to %d", con+1, value);
354
          OSC_SERVER_Init(0);
355
        } else
356
          out("ERROR: failed to set OSC%d remote port!", con+1);
1260 tk 357
          }
358
        }
359
      }
360
    } else if( strcmp(parameter, "osc_local_port") == 0 ) {
361
      if( !UIP_TASK_ServicesRunning() ) {
362
        out("ERROR: Ethernet services not running yet!");
363
      } else {
364
        s32 con = -1;
365
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
366
          con = get_dec(parameter);
367
        if( con < 1 || con >= OSC_SERVER_NUM_CONNECTIONS) {
368
          out("Invalid OSC connection specified as first parameter (expecting 1..%d)!", OSC_SERVER_NUM_CONNECTIONS);
369
        } else {
1284 tk 370
          con-=1; // the user counts from 1
1260 tk 371
 
372
          s32 value = -1;
373
          if( (parameter = strtok_r(NULL, separators, &brkt)) )
374
        value = get_dec(parameter);
375
          if( value < 1024 || value >= 65535) {
376
        out("Expecting OSC connection (1..%d) and local port value in range 1024..65535", OSC_SERVER_NUM_CONNECTIONS);
377
          } else {
1284 tk 378
        if( OSC_SERVER_LocalPortSet(con, value) >= 0 ) {
379
          out("Set OSC%d Local port to %d", con+1, value);
380
          OSC_SERVER_Init(0);
381
        } else
382
          out("ERROR: failed to set OSC%d local port!", con+1);
1260 tk 383
          }
384
        }
385
      }
386
    } else if( strcmp(parameter, "udpmon") == 0 ) {
387
      char *arg;
388
      if( (arg = strtok_r(NULL, separators, &brkt)) ) {
389
        int level = get_dec(arg);
390
        switch( level ) {
391
        case UDP_MONITOR_LEVEL_0_OFF:
392
          out("Set UDP monitor level to %d (off)\n", level);
393
          break;
394
        case UDP_MONITOR_LEVEL_1_OSC_REC:
395
          out("Set UDP monitor level to %d (received packets assigned to a OSC1..4 port)\n", level);
396
          break;
397
        case UDP_MONITOR_LEVEL_2_OSC_REC_AND_SEND:
398
          out("Set UDP monitor level to %d (received and sent packets assigned to a OSC1..4 port)\n", level);
399
          break;
400
        case UDP_MONITOR_LEVEL_3_ALL_GEQ_1024:
401
          out("Set UDP monitor level to %d (all received and sent packets with port number >= 1024)\n", level);
402
          break;
403
        case UDP_MONITOR_LEVEL_4_ALL:
404
          out("Set UDP monitor level to %d (all received and sent packets)\n", level);
405
          break;
406
        default:
407
          out("Invalid level %d - please specify monitor level 0..4\n", level);
408
          level = -1; // invalidate level for next if() check
409
        }
410
 
411
        if( level >= 0 )
412
          UIP_TASK_UDP_MonitorLevelSet(level);
413
      } else {
414
        out("Please specify monitor level (0..4)\n");
415
      }
416
    } else if( strcmp(parameter, "midimon") == 0 ) {
417
      s32 on_off = -1;
418
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
419
        on_off = get_on_off(parameter);
420
 
421
      if( on_off < 0 ) {
422
        out("Expecting 'on' or 'off'!");
423
      } else {
424
        MIDIMON_ActiveSet(on_off);
425
        out("MIDI Monitor %s!", MIDIMON_ActiveGet() ? "enabled" : "disabled");
426
      }
427
    } else if( strcmp(parameter, "midimon_filter") == 0 ) {
428
      s32 on_off = -1;
429
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
430
        on_off = get_on_off(parameter);
431
 
432
      if( on_off < 0 ) {
433
        out("Expecting 'on' or 'off'!");
434
      } else {
435
        MIDIMON_FilterActiveSet(on_off);
436
        out("MIDI Monitor Filter %s!", MIDIMON_FilterActiveGet() ? "enabled" : "disabled");
437
      }
438
    } else if( strcmp(parameter, "midimon_tempo") == 0 ) {
439
      s32 on_off = -1;
440
      if( (parameter = strtok_r(NULL, separators, &brkt)) )
441
        on_off = get_on_off(parameter);
442
 
443
      if( on_off < 0 ) {
444
        out("Expecting 'on' or 'off'!");
445
      } else {
446
        MIDIMON_TempoActiveSet(on_off);
447
        out("MIDI Monitor Tempo Display %s!", MIDIMON_TempoActiveGet() ? "enabled" : "disabled");
448
      }
449
    } else if( strcmp(parameter, "dout") == 0 ) {
450
      s32 pin = -1;
451
      if( (parameter = strtok_r(NULL, separators, &brkt)) ) {
452
        if( strcmp(parameter, "all") == 0 ) {
453
          pin = -42;
454
        } else {
455
          pin = get_dec(parameter);
456
        }
457
      }
458
 
459
      if( (pin < 0 && pin != -42) || pin >= (MIOS32_SRIO_NUM_SR*8) ) {
460
        out("Pin number should be between 0..%d", MIOS32_SRIO_NUM_SR*8 - 1);
461
      } else {
462
        s32 value = -1;
463
        if( (parameter = strtok_r(NULL, separators, &brkt)) )
464
          value = get_dec(parameter);
465
 
466
        if( value < 0 || value > 1 ) {
467
          out("Expecting value 1 or 0 for DOUT pin %d", pin);
468
        } else {
469
          if( pin == -42 ) {
470
        for(pin=0; pin<(MIOS32_SRIO_NUM_SR*8); ++pin)
471
          MIOS32_DOUT_PinSet(pin, value);
472
        out("All DOUT pins set to %d", value);
473
          } else {
474
        MIOS32_DOUT_PinSet(pin, value);
475
        out("DOUT Pin %d (SR#%d.D%d) set to %d", pin, (pin/8)+1, 7-(pin%8), value);
476
          }
477
        }
478
      }
479
    } else {
480
      out("Unknown set parameter: '%s'!", parameter);
481
    }
482
      } else {
483
    out("Missing parameter after 'set'!");
484
      }
485
    } else {
486
      out("Unknown command - type 'help' to list available commands!");
487
    }
488
  }
489
 
490
  return 0; // no error
491
}
492
 
493
 
494
/////////////////////////////////////////////////////////////////////////////
495
// System Informations
496
/////////////////////////////////////////////////////////////////////////////
497
static s32 TERMINAL_PrintSystem(void *_output_function)
498
{
499
  void (*out)(char *format, ...) = _output_function;
500
 
501
  out("Application: " MIOS32_LCD_BOOT_MSG_LINE1);
502
 
503
  out("Ethernet module connected: %s", UIP_TASK_NetworkDeviceAvailable() ? "yes" : "no");
504
  out("Ethernet services running: %s", UIP_TASK_ServicesRunning() ? "yes" : "no");
505
  out("DHCP: %s", UIP_TASK_DHCP_EnableGet() ? "enabled" : "disabled");
506
 
507
  if( UIP_TASK_DHCP_EnableGet() && !UIP_TASK_ServicesRunning() ) {
508
    out("IP address: not available yet");
509
    out("Netmask: not available yet");
510
    out("Default Router (Gateway): not available yet");
511
  } else {
512
    TERMINAL_PrintIPs(_output_function);
513
  }
514
 
515
  int con;
516
  for(con=0; con<OSC_SERVER_NUM_CONNECTIONS; ++con) {
517
    u32 osc_remote_ip = OSC_SERVER_RemoteIP_Get(con);
518
    out("OSC%d Remote address: %d.%d.%d.%d",
519
    con+1,
520
    (osc_remote_ip>>24)&0xff, (osc_remote_ip>>16)&0xff,
521
    (osc_remote_ip>>8)&0xff, (osc_remote_ip>>0)&0xff);
522
    out("OSC%d Remote port: %d", con+1, OSC_SERVER_RemotePortGet(con));
523
    out("OSC%d Local port: %d", con+1, OSC_SERVER_LocalPortGet(con));
524
  }
525
 
526
  out("UDP Monitor: verbose level #%d\n", UIP_TASK_UDP_MonitorLevelGet());
527
 
528
  out("MIDI Monitor: %s", MIDIMON_ActiveGet() ? "enabled" : "disabled");
529
  out("MIDI Monitor Filters: %s", MIDIMON_FilterActiveGet() ? "enabled" : "disabled");
530
  out("MIDI Monitor Tempo Display: %s", MIDIMON_TempoActiveGet() ? "enabled" : "disabled");
531
 
532
  return 0; // no error
533
}
534
 
535
 
536
 
537
/////////////////////////////////////////////////////////////////////////////
538
// Print IP settings (used by multiple functions)
539
/////////////////////////////////////////////////////////////////////////////
540
static s32 TERMINAL_PrintIPs(void *_output_function)
541
{
542
  void (*out)(char *format, ...) = _output_function;
543
 
544
  uip_ipaddr_t ipaddr;
545
  uip_gethostaddr(&ipaddr);
546
  out("IP address: %d.%d.%d.%d",
547
      uip_ipaddr1(ipaddr), uip_ipaddr2(ipaddr),
548
      uip_ipaddr3(ipaddr), uip_ipaddr4(ipaddr));
549
 
550
  uip_ipaddr_t netmask;
551
  uip_getnetmask(&netmask);
552
  out("Netmask: %d.%d.%d.%d",
553
      uip_ipaddr1(netmask), uip_ipaddr2(netmask),
554
      uip_ipaddr3(netmask), uip_ipaddr4(netmask));
555
 
556
  uip_ipaddr_t draddr;
557
  uip_getdraddr(&draddr);
558
  out("Default Router (Gateway): %d.%d.%d.%d",
559
      uip_ipaddr1(draddr), uip_ipaddr2(draddr),
560
      uip_ipaddr3(draddr), uip_ipaddr4(draddr));
561
 
562
  return 0; // no error
563
}