BlinkenLib v.0.5 (2005-12-06)
Christian Heimke

Christian Heimke commited on 2011-07-15 09:03:55
Showing 1 changed files, with 488 additions and 0 deletions.

... ...
@@ -0,0 +1,488 @@
1
+/* BlinkenLib
2
+ * version 0.5 date 2005-12-06
3
+ * Copyright 2004-2005 Stefan Schuermans <1stein@schuermans.info>
4
+ * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
5
+ * a blinkenarea.org project
6
+ */
7
+
8
+#include <errno.h>
9
+#include <fcntl.h>
10
+#include <stdlib.h>
11
+#include <stdio.h>
12
+#include <string.h>
13
+#include <termios.h>
14
+#include <time.h>
15
+#include <unistd.h>
16
+#include <arpa/inet.h>
17
+#include <netinet/in.h>
18
+#include <sys/types.h>
19
+#include <sys/socket.h>
20
+
21
+#include "BlinkenLib.h"
22
+
23
+//get serial settings from text
24
+static int serial_settings_parse( char * str, int * settings )
25
+{
26
+  int baud, data, stop;
27
+  char parity;
28
+  int set = 0;
29
+
30
+  //split and parse settings string
31
+  if( sscanf( str, "%i,%c,%i,%i", &baud, &parity, &data, &stop ) != 4 )
32
+    return 0;
33
+
34
+  //baud rate
35
+  if( baud == 300 ) set |= B300;
36
+  else if( baud == 600 ) set |= B600;
37
+  else if( baud == 1200 ) set |= B1200;
38
+  else if( baud == 2400 ) set |= B2400;
39
+  else if( baud == 4800 ) set |= B4800;
40
+  else if( baud == 9600 ) set |= B9600;
41
+  else if( baud == 19200 ) set |= B19200;
42
+  else if( baud == 38400 ) set |= B38400;
43
+  else if( baud == 57600 ) set |= B57600;
44
+  else if( baud == 115200 ) set |= B115200;
45
+  else
46
+  {
47
+    printf( "illegal baudrate: %d\n", baud );
48
+    return 0;
49
+  }
50
+
51
+  //parity
52
+  if( parity == 'n' || parity == 'N' ) set |= 0;
53
+  else if( parity == 'e' || parity == 'E' ) set |= PARENB;
54
+  else if( parity == 'o' || parity == 'O' ) set |= PARENB | PARODD;
55
+  else
56
+  {
57
+    printf( "invalid parity: %c\n", parity );
58
+    return 0;
59
+  }
60
+
61
+  //data bits
62
+  if( data == 5 ) set |= CS5;
63
+  else if( data == 6 ) set |= CS6;
64
+  else if( data == 7 ) set |= CS7;
65
+  else if( data == 8 ) set |= CS8;
66
+  else
67
+  {
68
+    printf( "illegal number of data bits: %d\n", data );
69
+    return 0;
70
+  }
71
+
72
+  //stop bits
73
+  if( stop == 1 ) set |= 0;
74
+  else if( stop == 2 ) set |= CSTOPB;
75
+  else
76
+  {
77
+    printf( "illegal number of stop bits: %d\n", stop );
78
+    return 0;
79
+  }
80
+
81
+  //success
82
+  *settings = set;
83
+  return 1;
84
+}
85
+
86
+//convert serial settings to text
87
+static void serial_settings_to_str( int settings, char * buf, unsigned int maxlen )
88
+{
89
+  int baud, data, stop;
90
+  char parity;
91
+
92
+  //baud rate
93
+  if( settings & B300 ) baud = 300;
94
+  else if( settings & B600 ) baud = 600;
95
+  else if( settings & B1200 ) baud = 1200;
96
+  else if( settings & B2400 ) baud = 2400;
97
+  else if( settings & B4800 ) baud = 4800;
98
+  else if( settings & B9600 ) baud = 9600;
99
+  else if( settings & B19200 ) baud = 19200;
100
+  else if( settings & B38400 ) baud = 38400;
101
+  else if( settings & B57600 ) baud = 57600;
102
+  else if( settings & B115200 ) baud = 115200;
103
+  else baud = 0;
104
+
105
+  //parity
106
+  if( settings & PARENB )
107
+    if( settings & PARODD) parity = 'O';
108
+    else parity = 'E';
109
+  else parity = 'N';
110
+
111
+  //data bits
112
+  if( settings & CS5) data = 5;
113
+  else if( settings & CS6) data = 6;
114
+  else if( settings & CS7) data = 7;
115
+  else if( settings & CS8) data = 8;
116
+  else data = 0;
117
+  
118
+  //stop bits
119
+  if( settings & CSTOPB ) stop = 2;
120
+  else stop = 1;
121
+
122
+  snprintf( buf, maxlen, "%d,%c,%d,%d", baud, parity, data, stop );
123
+}
124
+
125
+//set serial settings for fd
126
+static int serial_settings_set( int fd, int settings )
127
+{
128
+  struct termios tio;
129
+
130
+  //set port settings
131
+  bzero( &tio, sizeof( tio ) );
132
+  tio.c_cflag = CLOCAL | HUPCL | CREAD | settings;
133
+  tio.c_iflag = IGNBRK | IGNPAR;
134
+  tio.c_oflag = 0;
135
+  tio.c_lflag = 0;
136
+  tio.c_cc[VTIME] = 10; //1 sec timeout
137
+  tio.c_cc[VMIN] = 0; //return on single char read
138
+  if( tcsetattr( fd, TCSANOW, &tio ) == -1 )
139
+  {
140
+    printf( "tcsetattr: error: %s\n", strerror( errno ) );
141
+    return 0;
142
+  }
143
+
144
+  //success
145
+  return 1;
146
+}
147
+
148
+//recevie frames from socket and output them
149
+static void recv_and_out( int udpSocket, int dev_fd,
150
+                          unsigned int format_change,
151
+                          unsigned int format_height, unsigned int format_width,
152
+                          unsigned int format_channels, unsigned int format_colors,
153
+                          etBlinkenProto proto )
154
+{
155
+  fd_set readFds, errFds;
156
+  stBlinkenFrame * pLastFrame, * pFrame;
157
+  char buffer[65536]; //64kB is more than maximum UDP size
158
+  int maxFd, len;
159
+  int dev_eof = 0;
160
+
161
+  for( ; ; )
162
+  {
163
+    //wait for next frame
164
+    FD_ZERO( &readFds );
165
+    FD_SET( udpSocket, &readFds );
166
+    if( ! dev_eof )
167
+      FD_SET( dev_fd, &readFds );
168
+    FD_ZERO( &errFds );
169
+    FD_SET( udpSocket, &errFds );
170
+    FD_SET( dev_fd, &errFds );
171
+    maxFd = 0;
172
+    if( udpSocket > maxFd )
173
+      maxFd = udpSocket;
174
+    if( dev_fd > maxFd )
175
+      maxFd = dev_fd;
176
+    if( select( maxFd + 1, &readFds, NULL, &errFds, NULL ) < 0 ) // error
177
+      break;
178
+
179
+    //error on socket or device
180
+    if( FD_ISSET( udpSocket, &errFds ) )
181
+    {
182
+      printf( "error on socket\n" );
183
+      break;
184
+    }
185
+    if( FD_ISSET( dev_fd, &errFds ) )
186
+    {
187
+      printf( "error on device\n" );
188
+      break;
189
+    }
190
+
191
+    //received frame
192
+    if( FD_ISSET( udpSocket, &readFds ) )
193
+    {
194
+      //fetch data
195
+      len = recv( udpSocket, buffer, sizeof( buffer ), 0 );
196
+      if( len < 0 )
197
+      {
198
+        printf( "could not read from socket\n" );
199
+        break;
200
+      }
201
+      if( len == 0 )
202
+        break;
203
+
204
+      //get frame from data
205
+      pFrame = BlinkenFrameFromNetwork( buffer, len, NULL );
206
+      if( pFrame != NULL )
207
+      {
208
+        //change format
209
+        if( format_change )
210
+          BlinkenFrameResize( pFrame, format_height, format_width, format_channels, format_colors - 1 );
211
+
212
+        //create output data from frame
213
+        len = BlinkenFrameToNetwork( pFrame, proto, buffer, sizeof( buffer ) );
214
+
215
+        //free frame
216
+        BlinkenFrameFree( pFrame );
217
+
218
+        //output data to device
219
+        if( len > 0 )
220
+          write( dev_fd, buffer, len );
221
+      }
222
+    }
223
+
224
+    //received data from device
225
+    if( FD_ISSET( dev_fd, &readFds ) )
226
+    {
227
+      //read data
228
+      len = read( dev_fd, buffer, sizeof( buffer ) );
229
+      if( len < 0 )
230
+      {
231
+        printf( "error while reading from device\n" );
232
+        break;
233
+      }
234
+      if( len == 0 )
235
+        dev_eof = 1;
236
+    }
237
+  } //for( ; ; )
238
+}
239
+
240
+int main( int argCnt, char * * args )
241
+{
242
+  int i, udpSocket, bound, val, serial_settings, dev_fd;
243
+  etBlinkenProto proto;
244
+  unsigned int format_change, format_height, format_width, format_channels, format_colors;
245
+  unsigned int height, width, channels, colors;
246
+  unsigned int serial_settings_change;
247
+  char txt[64];
248
+  unsigned short port;
249
+  struct sockaddr_in addr;
250
+  char * device;
251
+
252
+  //print info
253
+  printf( "BlinkenLib - BlinkenOutput\n"
254
+          "version 0.5 date 2005-12-06\n"
255
+          "Copyright 2004-2005 Stefan Schuermans <1stein@schuermans.info>\n"
256
+          "Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html\n"
257
+          "a blinkenarea.org project\n\n" );
258
+
259
+  //print syntax
260
+  if( argCnt <= 1 )
261
+  {
262
+    printf( "syntax: %s <parameter> [...]\n\n"
263
+            "parameters:\n"
264
+            "  -l [<ip>:]<port>\n"
265
+            "     local address (defaults to 0.0.0.0:2323)\n"
266
+            "     must occur before -r and -o, may only occur once\n"
267
+            "  -r <ip>[:<port>]\n"
268
+            "     remote addess (defaults to every remote address)\n"
269
+            "  -p [BLP|EBLP|MCUF]\n"
270
+            "     protocol to outputframes in (defaults to MCUF)\n"
271
+            "  -f <width>x<height>-<channels>/<colors>\n"
272
+            "     format to output frames in (defaults to no change)\n"
273
+            "  -d <device>\n"
274
+            "     device to output frames to (defaults to \"/dev/null\")\n"
275
+            "  -s <baud-rate>,<parity>,<data-bits>,<stop-bits>\n"
276
+            "     settings to use for serial devices (defaults to no change)\n\n",
277
+            args[0] );
278
+    return 0;
279
+  }
280
+
281
+  //create udp socket
282
+  udpSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
283
+  if( udpSocket == -1 )
284
+  {
285
+    printf( "cannot create UDP socket\n" );
286
+    return -1;
287
+  }
288
+  bound = 0;
289
+
290
+  //process parameters
291
+  proto = BlinkenProtoMcuf;
292
+  format_change = 0;
293
+  device = "/dev/null";
294
+  serial_settings_change = 0;
295
+  for( i = 1; i < argCnt; i++ )
296
+  {
297
+
298
+    //local address
299
+    if( strcmp( args[i], "-l" ) == 0 )
300
+    {
301
+      if( i + 1 < argCnt )
302
+      {
303
+        i++;
304
+        if( sscanf( args[i], "%32[0-9.]:%hu", txt, &port ) == 2 )
305
+        {
306
+          addr.sin_family = AF_INET;
307
+          addr.sin_port = htons( port );
308
+          addr.sin_addr.s_addr = inet_addr( txt );
309
+          if( bind( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 )
310
+            printf( "could not set local address to \"%s\"\n", args[i] );
311
+          else
312
+            bound = 1;
313
+        }
314
+        else if( sscanf( args[i], "%hu", &port ) == 1 )
315
+        {
316
+          addr.sin_family = AF_INET;
317
+          addr.sin_port = htons( port );
318
+          addr.sin_addr.s_addr = htonl( INADDR_ANY );
319
+          if( bind( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 )
320
+            printf( "could not set local address to \"%s\"\n", args[i] );
321
+          else
322
+            bound = 1;
323
+        }
324
+        else
325
+          printf( "invalid local address \"%s\"\n", args[i] );
326
+      }
327
+      else
328
+        printf( "missing local address for \"-l\"\n" );
329
+    }
330
+
331
+    //remote address
332
+    else if( strcmp( args[i], "-r" ) == 0 )
333
+    {
334
+      if( i + 1 < argCnt )
335
+      {
336
+        i++;
337
+        if( sscanf( args[i], "%32[0-9.]:%hu", txt, &port ) == 2 )
338
+        {
339
+          addr.sin_family = AF_INET;
340
+          addr.sin_port = htons( port );
341
+          addr.sin_addr.s_addr = inet_addr( txt );
342
+          if( connect( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 )
343
+            printf( "could not set remote address to \"%s\"\n", args[i] );
344
+        }
345
+        else if( sscanf( args[i], "%32[0-9.]", txt ) == 1 )
346
+        {
347
+          addr.sin_family = AF_INET;
348
+          addr.sin_port = htons( 23230 );
349
+          addr.sin_addr.s_addr = inet_addr( txt );
350
+          if( connect( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 )
351
+            printf( "could not set remote address to \"%s\"\n", args[i] );
352
+        }
353
+        else
354
+          printf( "invalid remote address \"%s\"\n", args[i] );
355
+      }
356
+      else
357
+        printf( "missing remote address for \"-r\"\n" );
358
+    }
359
+
360
+    //protocol to output frames in
361
+    else if( strcmp( args[i], "-p" ) == 0 )
362
+    {
363
+      if( i + 1 < argCnt )
364
+      {
365
+        i++;
366
+        if( strcasecmp( args[i], "BLP" ) == 0 )
367
+          proto = BlinkenProtoBlp;
368
+        else if( strcasecmp( args[i], "EBLP" ) == 0 )
369
+          proto = BlinkenProtoEblp;
370
+        else if( strcasecmp( args[i], "MCUF" ) == 0 )
371
+          proto = BlinkenProtoMcuf;
372
+        else
373
+          printf( "unknown protocol \"%s\"\n", args[i] );
374
+      }
375
+      else
376
+        printf( "missing protocol for \"-p\"\n" );
377
+    }
378
+
379
+    //format to output frames in
380
+    else if( strcmp( args[i], "-f" ) == 0 )
381
+    {
382
+      if( i + 1 < argCnt )
383
+      {
384
+        i++;
385
+        if( sscanf( args[i], "%ux%u-%u/%u", &width, &height, &channels, &colors ) == 4 &&
386
+            width > 0 && width < 1000 && height > 0 && height < 1000 &&
387
+            channels > 0 && channels < 20 && colors > 1 && colors <= 256 )
388
+        {
389
+          format_change = 1;
390
+          format_height = height;
391
+          format_width = width;
392
+          format_channels = channels;
393
+          format_colors = colors;
394
+        }
395
+        else
396
+          printf( "invalid frame format \"%s\"\n", args[i] );
397
+      }
398
+      else
399
+        printf( "missing frame format for \"-r\"\n" );
400
+    }
401
+
402
+    //device to output frames to
403
+    else if( strcmp( args[i], "-d" ) == 0 )
404
+    {
405
+      if( i + 1 < argCnt )
406
+      {
407
+        i++;
408
+        device = args[i];
409
+      }
410
+      else
411
+        printf( "missing device name for \"-d\"\n" );
412
+    }
413
+
414
+    //settings for serial output devices
415
+    else if( strcmp( args[i], "-s" ) == 0 )
416
+    {
417
+      if( i + 1 < argCnt )
418
+      {
419
+        i++;
420
+        if( serial_settings_parse( args[i], &serial_settings ) )
421
+        {
422
+          serial_settings_change = 1;
423
+        }
424
+        else
425
+          printf( "invalid serial settings \"%s\"\n", args[i] );
426
+      }
427
+      else
428
+        printf( "missing serial settings for \"-s\"\n" );
429
+    }
430
+
431
+    //unknown parameter
432
+    else
433
+      printf( "unknown parameter \"%s\", call without parameters to get help\n", args[i] );
434
+
435
+  } //for( i ...
436
+
437
+  //try to bind if not bound
438
+  if( ! bound )
439
+  {
440
+    printf( "no local address to receive frames on,\n"
441
+            "  using default local address \"0.0.0.0:2323\"\n" );
442
+    addr.sin_family = AF_INET;
443
+    addr.sin_port = htons( 2323 );
444
+    addr.sin_addr.s_addr = htonl( INADDR_ANY );
445
+    if( bind( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) == 0 )
446
+      bound = 1;
447
+    else
448
+    {
449
+      printf( "could not set local address to \"0.0.0.0:2323\"\n" );
450
+      close( udpSocket );
451
+      return -1;
452
+    }
453
+  }
454
+
455
+  //open device
456
+  dev_fd = open( device, O_RDWR | O_NOCTTY | O_NONBLOCK );
457
+  if( dev_fd == -1 )
458
+  {
459
+    printf( "could not open \"%s\": error: %s\n", device, strerror( errno ) );
460
+    close( udpSocket );
461
+    return -1;
462
+  }
463
+
464
+  //setup serial port
465
+  if( serial_settings_change )
466
+  {
467
+    if( ! serial_settings_set( dev_fd, serial_settings ) )
468
+    {
469
+      serial_settings_to_str( serial_settings, txt, sizeof( txt ) );
470
+      printf( "could not set serial port to \"%s\"\n", txt );
471
+      close( dev_fd );
472
+      close( udpSocket );
473
+      return -1;
474
+    }
475
+  }
476
+
477
+  //recieve frames and output to device
478
+  printf( "receiving frames and outputting them to \"%s\"...\n", device );
479
+  recv_and_out( udpSocket, dev_fd,
480
+                format_change, format_height, format_width, format_channels, format_colors,
481
+                proto );
482
+
483
+  //cleanup
484
+  close( dev_fd );
485
+  close( udpSocket );
486
+
487
+  return 0;
488
+}
0 489