BlinkenArea - GitList
Repositories
Blog
Wiki
BlinkenLib
Code
Commits
Branches
Tags
Search
Tree:
90c67b3
Branches
Tags
master
v0.1
v0.2
v0.3
v0.3.1
v0.4
v0.4.1
v0.5
v0.5.1
v0.5.2
v0.5.3
v0.5.4
v0.5.5
v0.6.0
v0.6.1
v0.6.2
v0.6.3
v0.6.4
v0.6.5
v0.6.6
v0.6.7
v0.6.8
v0.6.9
v0.7.0
v0.7.1
v0.7.10
v0.7.2
v0.7.3
v0.7.4
v0.7.5
v0.7.6
v0.7.7
v0.7.8
v0.7.9
v0.8.0
v0.8.1
BlinkenLib
BlinkenOutput.c
BlinkenLib v.0.5 (2005-12-06)
Christian Heimke
commited
90c67b3
at 2011-07-15 09:03:55
BlinkenOutput.c
Blame
History
Raw
/* BlinkenLib * version 0.5 date 2005-12-06 * Copyright 2004-2005 Stefan Schuermans <1stein@schuermans.info> * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html * a blinkenarea.org project */ #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <termios.h> #include <time.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include "BlinkenLib.h" //get serial settings from text static int serial_settings_parse( char * str, int * settings ) { int baud, data, stop; char parity; int set = 0; //split and parse settings string if( sscanf( str, "%i,%c,%i,%i", &baud, &parity, &data, &stop ) != 4 ) return 0; //baud rate if( baud == 300 ) set |= B300; else if( baud == 600 ) set |= B600; else if( baud == 1200 ) set |= B1200; else if( baud == 2400 ) set |= B2400; else if( baud == 4800 ) set |= B4800; else if( baud == 9600 ) set |= B9600; else if( baud == 19200 ) set |= B19200; else if( baud == 38400 ) set |= B38400; else if( baud == 57600 ) set |= B57600; else if( baud == 115200 ) set |= B115200; else { printf( "illegal baudrate: %d\n", baud ); return 0; } //parity if( parity == 'n' || parity == 'N' ) set |= 0; else if( parity == 'e' || parity == 'E' ) set |= PARENB; else if( parity == 'o' || parity == 'O' ) set |= PARENB | PARODD; else { printf( "invalid parity: %c\n", parity ); return 0; } //data bits if( data == 5 ) set |= CS5; else if( data == 6 ) set |= CS6; else if( data == 7 ) set |= CS7; else if( data == 8 ) set |= CS8; else { printf( "illegal number of data bits: %d\n", data ); return 0; } //stop bits if( stop == 1 ) set |= 0; else if( stop == 2 ) set |= CSTOPB; else { printf( "illegal number of stop bits: %d\n", stop ); return 0; } //success *settings = set; return 1; } //convert serial settings to text static void serial_settings_to_str( int settings, char * buf, unsigned int maxlen ) { int baud, data, stop; char parity; //baud rate if( settings & B300 ) baud = 300; else if( settings & B600 ) baud = 600; else if( settings & B1200 ) baud = 1200; else if( settings & B2400 ) baud = 2400; else if( settings & B4800 ) baud = 4800; else if( settings & B9600 ) baud = 9600; else if( settings & B19200 ) baud = 19200; else if( settings & B38400 ) baud = 38400; else if( settings & B57600 ) baud = 57600; else if( settings & B115200 ) baud = 115200; else baud = 0; //parity if( settings & PARENB ) if( settings & PARODD) parity = 'O'; else parity = 'E'; else parity = 'N'; //data bits if( settings & CS5) data = 5; else if( settings & CS6) data = 6; else if( settings & CS7) data = 7; else if( settings & CS8) data = 8; else data = 0; //stop bits if( settings & CSTOPB ) stop = 2; else stop = 1; snprintf( buf, maxlen, "%d,%c,%d,%d", baud, parity, data, stop ); } //set serial settings for fd static int serial_settings_set( int fd, int settings ) { struct termios tio; //set port settings bzero( &tio, sizeof( tio ) ); tio.c_cflag = CLOCAL | HUPCL | CREAD | settings; tio.c_iflag = IGNBRK | IGNPAR; tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cc[VTIME] = 10; //1 sec timeout tio.c_cc[VMIN] = 0; //return on single char read if( tcsetattr( fd, TCSANOW, &tio ) == -1 ) { printf( "tcsetattr: error: %s\n", strerror( errno ) ); return 0; } //success return 1; } //recevie frames from socket and output them static void recv_and_out( int udpSocket, int dev_fd, unsigned int format_change, unsigned int format_height, unsigned int format_width, unsigned int format_channels, unsigned int format_colors, etBlinkenProto proto ) { fd_set readFds, errFds; stBlinkenFrame * pLastFrame, * pFrame; char buffer[65536]; //64kB is more than maximum UDP size int maxFd, len; int dev_eof = 0; for( ; ; ) { //wait for next frame FD_ZERO( &readFds ); FD_SET( udpSocket, &readFds ); if( ! dev_eof ) FD_SET( dev_fd, &readFds ); FD_ZERO( &errFds ); FD_SET( udpSocket, &errFds ); FD_SET( dev_fd, &errFds ); maxFd = 0; if( udpSocket > maxFd ) maxFd = udpSocket; if( dev_fd > maxFd ) maxFd = dev_fd; if( select( maxFd + 1, &readFds, NULL, &errFds, NULL ) < 0 ) // error break; //error on socket or device if( FD_ISSET( udpSocket, &errFds ) ) { printf( "error on socket\n" ); break; } if( FD_ISSET( dev_fd, &errFds ) ) { printf( "error on device\n" ); break; } //received frame if( FD_ISSET( udpSocket, &readFds ) ) { //fetch data len = recv( udpSocket, buffer, sizeof( buffer ), 0 ); if( len < 0 ) { printf( "could not read from socket\n" ); break; } if( len == 0 ) break; //get frame from data pFrame = BlinkenFrameFromNetwork( buffer, len, NULL ); if( pFrame != NULL ) { //change format if( format_change ) BlinkenFrameResize( pFrame, format_height, format_width, format_channels, format_colors - 1 ); //create output data from frame len = BlinkenFrameToNetwork( pFrame, proto, buffer, sizeof( buffer ) ); //free frame BlinkenFrameFree( pFrame ); //output data to device if( len > 0 ) write( dev_fd, buffer, len ); } } //received data from device if( FD_ISSET( dev_fd, &readFds ) ) { //read data len = read( dev_fd, buffer, sizeof( buffer ) ); if( len < 0 ) { printf( "error while reading from device\n" ); break; } if( len == 0 ) dev_eof = 1; } } //for( ; ; ) } int main( int argCnt, char * * args ) { int i, udpSocket, bound, val, serial_settings, dev_fd; etBlinkenProto proto; unsigned int format_change, format_height, format_width, format_channels, format_colors; unsigned int height, width, channels, colors; unsigned int serial_settings_change; char txt[64]; unsigned short port; struct sockaddr_in addr; char * device; //print info printf( "BlinkenLib - BlinkenOutput\n" "version 0.5 date 2005-12-06\n" "Copyright 2004-2005 Stefan Schuermans <1stein@schuermans.info>\n" "Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html\n" "a blinkenarea.org project\n\n" ); //print syntax if( argCnt <= 1 ) { printf( "syntax: %s <parameter> [...]\n\n" "parameters:\n" " -l [<ip>:]<port>\n" " local address (defaults to 0.0.0.0:2323)\n" " must occur before -r and -o, may only occur once\n" " -r <ip>[:<port>]\n" " remote addess (defaults to every remote address)\n" " -p [BLP|EBLP|MCUF]\n" " protocol to outputframes in (defaults to MCUF)\n" " -f <width>x<height>-<channels>/<colors>\n" " format to output frames in (defaults to no change)\n" " -d <device>\n" " device to output frames to (defaults to \"/dev/null\")\n" " -s <baud-rate>,<parity>,<data-bits>,<stop-bits>\n" " settings to use for serial devices (defaults to no change)\n\n", args[0] ); return 0; } //create udp socket udpSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if( udpSocket == -1 ) { printf( "cannot create UDP socket\n" ); return -1; } bound = 0; //process parameters proto = BlinkenProtoMcuf; format_change = 0; device = "/dev/null"; serial_settings_change = 0; for( i = 1; i < argCnt; i++ ) { //local address if( strcmp( args[i], "-l" ) == 0 ) { if( i + 1 < argCnt ) { i++; if( sscanf( args[i], "%32[0-9.]:%hu", txt, &port ) == 2 ) { addr.sin_family = AF_INET; addr.sin_port = htons( port ); addr.sin_addr.s_addr = inet_addr( txt ); if( bind( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 ) printf( "could not set local address to \"%s\"\n", args[i] ); else bound = 1; } else if( sscanf( args[i], "%hu", &port ) == 1 ) { addr.sin_family = AF_INET; addr.sin_port = htons( port ); addr.sin_addr.s_addr = htonl( INADDR_ANY ); if( bind( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 ) printf( "could not set local address to \"%s\"\n", args[i] ); else bound = 1; } else printf( "invalid local address \"%s\"\n", args[i] ); } else printf( "missing local address for \"-l\"\n" ); } //remote address else if( strcmp( args[i], "-r" ) == 0 ) { if( i + 1 < argCnt ) { i++; if( sscanf( args[i], "%32[0-9.]:%hu", txt, &port ) == 2 ) { addr.sin_family = AF_INET; addr.sin_port = htons( port ); addr.sin_addr.s_addr = inet_addr( txt ); if( connect( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 ) printf( "could not set remote address to \"%s\"\n", args[i] ); } else if( sscanf( args[i], "%32[0-9.]", txt ) == 1 ) { addr.sin_family = AF_INET; addr.sin_port = htons( 23230 ); addr.sin_addr.s_addr = inet_addr( txt ); if( connect( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) != 0 ) printf( "could not set remote address to \"%s\"\n", args[i] ); } else printf( "invalid remote address \"%s\"\n", args[i] ); } else printf( "missing remote address for \"-r\"\n" ); } //protocol to output frames in else if( strcmp( args[i], "-p" ) == 0 ) { if( i + 1 < argCnt ) { i++; if( strcasecmp( args[i], "BLP" ) == 0 ) proto = BlinkenProtoBlp; else if( strcasecmp( args[i], "EBLP" ) == 0 ) proto = BlinkenProtoEblp; else if( strcasecmp( args[i], "MCUF" ) == 0 ) proto = BlinkenProtoMcuf; else printf( "unknown protocol \"%s\"\n", args[i] ); } else printf( "missing protocol for \"-p\"\n" ); } //format to output frames in else if( strcmp( args[i], "-f" ) == 0 ) { if( i + 1 < argCnt ) { i++; if( sscanf( args[i], "%ux%u-%u/%u", &width, &height, &channels, &colors ) == 4 && width > 0 && width < 1000 && height > 0 && height < 1000 && channels > 0 && channels < 20 && colors > 1 && colors <= 256 ) { format_change = 1; format_height = height; format_width = width; format_channels = channels; format_colors = colors; } else printf( "invalid frame format \"%s\"\n", args[i] ); } else printf( "missing frame format for \"-r\"\n" ); } //device to output frames to else if( strcmp( args[i], "-d" ) == 0 ) { if( i + 1 < argCnt ) { i++; device = args[i]; } else printf( "missing device name for \"-d\"\n" ); } //settings for serial output devices else if( strcmp( args[i], "-s" ) == 0 ) { if( i + 1 < argCnt ) { i++; if( serial_settings_parse( args[i], &serial_settings ) ) { serial_settings_change = 1; } else printf( "invalid serial settings \"%s\"\n", args[i] ); } else printf( "missing serial settings for \"-s\"\n" ); } //unknown parameter else printf( "unknown parameter \"%s\", call without parameters to get help\n", args[i] ); } //for( i ... //try to bind if not bound if( ! bound ) { printf( "no local address to receive frames on,\n" " using default local address \"0.0.0.0:2323\"\n" ); addr.sin_family = AF_INET; addr.sin_port = htons( 2323 ); addr.sin_addr.s_addr = htonl( INADDR_ANY ); if( bind( udpSocket, (struct sockaddr *)&addr, sizeof( addr ) ) == 0 ) bound = 1; else { printf( "could not set local address to \"0.0.0.0:2323\"\n" ); close( udpSocket ); return -1; } } //open device dev_fd = open( device, O_RDWR | O_NOCTTY | O_NONBLOCK ); if( dev_fd == -1 ) { printf( "could not open \"%s\": error: %s\n", device, strerror( errno ) ); close( udpSocket ); return -1; } //setup serial port if( serial_settings_change ) { if( ! serial_settings_set( dev_fd, serial_settings ) ) { serial_settings_to_str( serial_settings, txt, sizeof( txt ) ); printf( "could not set serial port to \"%s\"\n", txt ); close( dev_fd ); close( udpSocket ); return -1; } } //recieve frames and output to device printf( "receiving frames and outputting them to \"%s\"...\n", device ); recv_and_out( udpSocket, dev_fd, format_change, format_height, format_width, format_channels, format_colors, proto ); //cleanup close( dev_fd ); close( udpSocket ); return 0; }