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"
|