bad3255ccc8729e7e82e0c2a0a0b0136c5f8e9f0
Christian Heimke BlinkenLib v.0.5.2 (2006-05...

Christian Heimke authored 13 years ago

1) /* BlinkenLib
Christian Heimke BlinkenLib v.0.5.4 (2008-01...

Christian Heimke authored 13 years ago

2)  * version 0.5.4 date 2008-01-10
3)  * Copyright 2004-2008 Stefan Schuermans <stefan@schuermans.info>
Christian Heimke BlinkenLib v.0.5.2 (2006-05...

Christian Heimke authored 13 years ago

4)  * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
5)  * a blinkenarea.org project
6)  */
7) 
8) #include <fcntl.h>
9) #include <stdlib.h>
10) #include <stdio.h>
11) #include <string.h>
12) #include <winsock2.h>
13) #include <windows.h>
14) 
15) #include "BlinkenLib.h"
16) 
17) //get serial settings from text
18) static int serial_settings_parse( char * str )
19) {
20)   int baud, data, stop;
21)   char parity;
22)   int set = 0;
23) 
24)   //split and parse settings string
25)   if( sscanf( str, "%i,%c,%i,%i", &baud, &parity, &data, &stop ) != 4 )
26)     return 0;
27) 
28)   //baud rate
29)   if( baud != 300 &&
30) 	  baud != 600 &&
31)       baud != 1200 &&
32)       baud != 2400 &&
33)       baud != 4800 &&
34)       baud != 9600 &&
35)       baud != 19200 &&
36)       baud != 38400 &&
37)       baud != 57600 &&
38)       baud != 115200 )
39)   {
40)     printf( "illegal baudrate: %d\n", baud );
41)     return 0;
42)   }
43) 
44)   //parity
45)   if( parity != 'n' && parity != 'N' &&
46)       parity != 'e' && parity != 'E' &&
47)       parity != 'o' && parity != 'O' )
48)   {
49)     printf( "invalid parity: %c\n", parity );
50)     return 0;
51)   }
52) 
53)   //data bits
54)   if( data != 5 &&
55)       data != 6 &&
56)       data != 7 &&
57)       data != 8 )
58)   {
59)     printf( "illegal number of data bits: %d\n", data );
60)     return 0;
61)   }
62) 
63)   //stop bits
64)   if( stop != 1 &&
65)       stop == 2 )
66)   {
67)     printf( "illegal number of stop bits: %d\n", stop );
68)     return 0;
69)   }
70) 
71)   //success
72)   return 1;
73) }
74) 
75) //set serial settings for fd
76) static int serial_settings_set( HANDLE hDev, char * settings )
77) {
78)   DCB PortDcb;
79)   COMMTIMEOUTS CommTimeouts;
80) 
81)   //set serial parameters
82)   if( ! GetCommState( hDev, &PortDcb ) )
83)   {
84)     printf( "error getting device comm state: error %u\n", GetLastError( ) );
85)     return 0;
86)   }
87)   if( ! BuildCommDCB( hDev, &PortDcb ) )
88)   {
89)     printf( "error building comm state: error %u\n", GetLastError( ) );
90)     return 0;
91)   }
92)   if( ! SetCommState( hDev, &PortDcb ) )
93)   {
94)     printf( "error setting device comm state: error %u\n", GetLastError( ) );
95)     return 0;
96)   }
97) 
98)   //set timeout parameters
99)   //maximum time between arrival of two characters: 10 ms
100)   //if this time elapses, read command will return even if buffer is not filled completely
101)   CommTimeouts.ReadIntervalTimeout = 10;
102)   //disable read timeouts
103)   CommTimeouts.ReadTotalTimeoutConstant = 0;
104)   CommTimeouts.ReadTotalTimeoutMultiplier = 0;
105)   //disable write timeouts
106)   CommTimeouts.WriteTotalTimeoutConstant = 0;
107)   CommTimeouts.WriteTotalTimeoutMultiplier = 0;
108)   if( ! SetCommTimeouts( hDev, &CommTimeouts ) )
109)   {
110)     printf( "error setting device timeout parameters: error %u\n", GetLastError( ) );
111)     return 0;
112)   }
113) 
114)   //success
115)   return 1;
116) }
117) 
118) //receive frames from socket and output them
119) //hDev may be INVALID_HANDLE_VALUE for not doing anything with device
120) //returns error code (not for device-errors, 0 for success)
121) static int recv_and_out( SOCKET udpSocket, HANDLE hDev,
122)                          int * p_device_output_active,
123)                          unsigned int format_change,
124)                          unsigned int format_height, unsigned int format_width,
125)                          unsigned int format_channels, unsigned int format_colors,
126)                          etBlinkenProto proto,
127)                          int use_msecs, unsigned int msecs, int is_serial_device )
128) {
129)   fd_set readFds, errFds;
130)   stBlinkenFrame * pFrame;
131)   char buffer[65536]; //64kB is more than maximum UDP size
132)   int len, dev_eof;
133)   struct timeval timeout, * p_timeout;
134)   DWORD DevWrLen, Err, start, end;
135)   COMSTAT ComStat;
136) 
137)   dev_eof = 0;
138)   for( ; ; )
139)   {
140)     //wait for next frame
141)     FD_ZERO( &readFds );
142)     FD_SET( udpSocket, &readFds );
143)     FD_ZERO( &errFds );
144)     FD_SET( udpSocket, &errFds );
145)     if( use_msecs ) //timeout
146)     {
147)       start = GetTickCount( );
148)       timeout.tv_sec = msecs / 1000;
149)       timeout.tv_usec = msecs % 1000 * 1000;
150)       p_timeout = &timeout;
151)     }
152)     else
153)       p_timeout = NULL;
154)     if( select( 0, &readFds, NULL, &errFds, p_timeout ) < 0 ) //error
155)     {
156)       printf( "error during select: %s\n", strerror( errno ) );
157)       return -1;
158)     }
159) 
160)     //error on socket
161)     if( FD_ISSET( udpSocket, &errFds ) )
162)     {
163)       printf( "error on socket\n" );
164)       return -1;
165)     }
166) 
167)     //received frame
168)     if( FD_ISSET( udpSocket, &readFds ) )
169)     {
170)       //fetch data
171)       len = recv( udpSocket, buffer, sizeof( buffer ), 0 );
172)       if( len < 0 )
173)       {
174)         printf( "could not read from socket\n" );
175)         return -1;
176)       }
177)       if( len == 0 )
178)         return -1;
179) 
180)       //get frame from data
181)       pFrame = BlinkenFrameFromNetwork( buffer, len, NULL );
182)       if( pFrame != NULL )
183)       {
184)         //change format
185)         if( format_change )
186)           BlinkenFrameResize( pFrame, format_height, format_width, format_channels, format_colors - 1 );
187) 
188)         //create output data from frame
189)         len = BlinkenFrameToNetwork( pFrame, proto, buffer, sizeof( buffer ) );
190) 
191)         //free frame
192)         BlinkenFrameFree( pFrame );
193) 
194)         //output data to device
195)         if( hDev != INVALID_HANDLE_VALUE && len > 0 )
196)         {
197)           if( ! WriteFile( hDev, buffer, len, &DevWrLen, NULL ) || (int)DevWrLen != len )
198)           {
199)             if( *p_device_output_active )
200)               printf( "error writing to device: error %lu\n", GetLastError( ) );
201)             break;
202)           }
203)           //message: output to device was restarted
204)           if( ! *p_device_output_active )
205)             printf( "restarted output to device...\n" );
206)           *p_device_output_active = 1;
207)         }
208)       }
209) 	}
210) 
211) 	//get state of serial device
212)     if( hDev != INVALID_HANDLE_VALUE && is_serial_device )
213) 	{
214) 	  ClearCommError( hDev, &Err, &ComStat );
215) 	  //reception error
216) 	  if( Err & (CE_BREAK | CE_FRAME | CE_OVERRUN | CE_RXOVER | CE_RXPARITY) )
217) 	  {
218)         if( *p_device_output_active )
219)           printf( "error reading from device (comm err=%X)\n", Err );
220)         break;
221) 	  }
222)     }
223) 
224)     //using time limit
225)     if( use_msecs )
226)     {
227)       unsigned int msec;
228)       //get time elapsed
229) 	  end = GetTickCount( );
230)       msec = end - start;
231)       //more than rest of timeout (or exact match)
232)       if( msec >= msecs )
233)         break;
234)       msecs -= msec;
235)     }
236) 
237)   } //for( ; ; )
238) 
239)   return 0;
240) }
241) 
242) //open device and output frames
243) //returns error code (not for device-errors, 0 for success)
244) static int open_and_output( SOCKET udpSocket, char * device,
245)                             int * p_device_output_active,
246)                             int serial_settings_change, char * serial_settings,
247)                             unsigned int format_change,
248)                             unsigned int format_height, unsigned int format_width,
249)                             unsigned int format_channels, unsigned int format_colors,
250)                             etBlinkenProto proto )
251) {
252)   HANDLE hDev;
253)   int err;
254) 
255)   //open device
256)   hDev = CreateFile( device, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
257)   if( hDev == INVALID_HANDLE_VALUE )
258)   {
259)     if( *p_device_output_active )
260)       printf( "could not open \"%s\": error %u\n", device, GetLastError( ) );
261)     return 0;
262)   }
263) 
264)   //setup serial port
265)   if( serial_settings_change )
266)   {
267)     if( ! serial_settings_set( hDev, serial_settings ) )
268)     {
269)       if( *p_device_output_active )
270)         printf( "could not set serial port to \"%s\"\n", serial_settings );
271)       CloseHandle( hDev );
272)       return 0;
273)     }
274)   }
275) 
276)   //receive frames and output to device
277)   err = recv_and_out( udpSocket, hDev, p_device_output_active,
278)                       format_change, format_height, format_width, format_channels, format_colors,
279)                       proto, 0, 0, serial_settings_change );
280) 
281)   //close device
282)   CloseHandle( hDev );
283) 
284)   return err;
285) }
286) 
287) //open device and output frames in a loop
288) //returns error code (not for device-errors, 0 for success)
289) static int open_and_output_loop( SOCKET udpSocket, char * device,
290)                                  int serial_settings_change, char * serial_settings,
291)                                  int reopen_device, unsigned int reopen_device_ms,
292)                                  unsigned int format_change,
293)                                  unsigned int format_height, unsigned int format_width,
294)                                  unsigned int format_channels, unsigned int format_colors,
295)                                  etBlinkenProto proto )
296) {
297)   int device_output_active, err;
298) 
299)   printf( "receiving frames and outputting them to \"%s\"...\n", device );
300)   device_output_active = 1;
301) 
302)   for( ; ; )
303)   {
304) 
305)     //try to open device and output frames
306)     err = open_and_output( udpSocket, device,
307)                            &device_output_active,
308)                            serial_settings_change, serial_settings,
309)                            format_change, format_height, format_width, format_channels, format_colors,
310)                            proto );
311)     if( err != 0 || ! reopen_device )
312)       break;
313) 
314)     //output to device stopped
315)     if( device_output_active )
316)       printf( "output to device stopped...\n" );
317)     device_output_active = 0;
318) 
319)     //only fetch data from socket for a short time
320)     err = recv_and_out( udpSocket, INVALID_HANDLE_VALUE, &device_output_active,
321)                         format_change, format_height, format_width, format_channels, format_colors,
322)                         proto, 1, reopen_device_ms, serial_settings_change );
323)     if( err != 0 )
324)       break;
325) 
326)   }
327) 
328)   //output to device finshed
329)   if( device_output_active )
330)     printf( "output to device finished...\n" );
331)   device_output_active = 0;
332) 
333)   return err;
334) }
335) 
336) int main( int argCnt, char * * args )
337) {
338)   WSADATA WsaData;
339)   int i, bound;
340)   SOCKET udpSocket;
341)   char * serial_settings;
342)   etBlinkenProto proto;
343)   unsigned int format_change, format_height, format_width, format_channels, format_colors;
344)   unsigned int height, width, channels, colors, reopen_device_ms;
345)   int serial_settings_change, reopen_device, unblock;
346)   char txt[64];
347)   unsigned short port;
348)   struct sockaddr_in addr;
349)   char * device;
350) 
351)   //print info
352)   printf( "BlinkenLib - BlinkenOutput\n"
Christian Heimke BlinkenLib v.0.5.4 (2008-01...

Christian Heimke authored 13 years ago

353)           "version 0.5.4 date 2008-01-10\n"
354)           "Copyright 2004-2008 Stefan Schuermans <stefan@schuermans.info>\n"