00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <cstdio>
00038 #include <ctime>
00039 #include <atlbase.h>
00040
00041 #include "liblnp.h"
00042
00043
00044
00045
00046
00047 #define DEBUGLNP 0
00048 #define LNPCHECKSOMSTOP 0
00049 #define LNPBLOCK 0
00050
00051
00052
00053
00054 #define DEFAULT_LNP_ADDR 0x80
00055 #define DEFAULT_LNP_MASK 0xf0
00056 #define MAX_LNP_PACKET (256+3)
00057
00058
00059 #define TOWER_KEEP_ALIVE_CHAR 0xFF
00060 #define TOWER_KEEP_ALIVE_DELAY 2000 //ms
00061
00062
00063
00064 #define BAUDRATE 4800
00065 #define STOPBITS 0 // 1 stopbit
00066 #define PARITY 0 // no parity
00067 #define BYTESIZE 8 // read per 8 bits synchroon ( bits arive at fixed time intervals )
00068
00069
00070
00071 #define READTIMEOUT 2000 // package reading timeout in milliseconds
00072
00073 #define AFTERWRITESLEEPTIME 500 // time to sleep after write :
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static unsigned char lnp_host_address;
00086 static unsigned char lnp_host_mask;
00087 static unsigned char lnp_port_mask;
00088
00089 static int connected=0;
00090 static int lnp_stop=0;
00091
00092 static lnp_tx_result tx_result;
00093
00094 static unsigned char lnp_buffer[MAX_LNP_PACKET];
00095
00096 static lnp_integrity_handler_t integrity_handler;
00097 static lnp_addressing_handler_t addressing_handler[256];
00098
00099
00100 typedef enum lnp_integrity_state_t
00101 {
00102 LNPwaitHeader,
00103 LNPwaitLength,
00104 LNPwaitData,
00105 LNPwaitCRC
00106 } lnp_integrity_state_t;
00107
00108
00109 static lnp_integrity_state_t lnp_integrity_state=LNPwaitHeader;
00110
00111
00112
00113
00114
00115 static CComAutoCriticalSection crit_sect;
00116 static HANDLE comHandle=NULL;
00117 static HANDLE h_KeepAliveComThread;
00118 static HANDLE h_ComReaderThread;
00119 static char *ComPort="com1";
00120 static char *USBPort="\\\\.\\legotower1";
00121
00122 static BOOL UseUSB = true;
00123
00124
00125
00126
00127 static time_t stoptime=-1;
00128
00129
00130
00131
00132
00133
00134
00135 static unsigned char
00136 lnp_checksum( const unsigned char *data, unsigned length )
00137 {
00138 unsigned char a = 0xff;
00139 unsigned char b = 0xff;
00140
00141 while (length > 0)
00142 {
00143 a = a + *data;
00144 b = b + a;
00145 data++;
00146 length--;
00147 }
00148
00149 return a + (b << 8);
00150 }
00151
00152
00153
00154 static void
00155 block_rcv(void)
00156 {
00157 crit_sect.Lock();
00158 }
00159
00160
00161 static void
00162 unblock_rcv(void)
00163 {
00164 crit_sect.Unlock();
00165 }
00166
00167
00168
00169 void
00170 lnp_shutdown(void)
00171 {
00172 block_rcv();
00173 connected = 0;
00174 lnp_stop=1;
00175 lnp_integrity_state=LNPwaitHeader;
00176 unblock_rcv();
00177 DWORD rvalue=0;
00178 GetExitCodeThread(h_ComReaderThread,&rvalue);
00179 while ( rvalue == STILL_ACTIVE )
00180 {
00181 GetExitCodeThread(h_ComReaderThread,&rvalue);
00182 };
00183 CloseHandle(h_ComReaderThread);
00184 if( ! UseUSB )
00185 {
00186 GetExitCodeThread(h_KeepAliveComThread,&rvalue);
00187 while ( rvalue == STILL_ACTIVE )
00188 {
00189 GetExitCodeThread(h_KeepAliveComThread,&rvalue);
00190 };
00191 CloseHandle(h_KeepAliveComThread);
00192 }
00193 lnp_stop=0;
00194 CloseHandle( comHandle );
00195 comHandle=NULL;
00196 }
00197
00198
00199
00200
00201 bool lnp_test(void)
00202 {
00203 return ( comHandle != NULL );
00204 }
00205
00206
00207 static lnp_tx_result
00208 lnp_logical_write( unsigned char *data, int length )
00209 {
00210 BOOL fWriteStat;
00211 DWORD nWritten = 0;
00212
00213 if( ! connected )
00214 {
00215 return( TX_ERROR );
00216 }
00217
00218
00219 #if LNPBLOCK
00220 printf("write BLOCK\n");
00221 #endif
00222 block_rcv();
00223 #if LNPBLOCK
00224 printf("write BLOCKED\n");
00225 #endif
00226
00227 fWriteStat = WriteFile( comHandle,
00228 data,
00229 (unsigned long)length,
00230 &nWritten,
00231 NULL );
00232 #if LNPBLOCK
00233 printf("write UNBLOCK\n");
00234 #endif
00235 unblock_rcv();
00236
00237 if( !fWriteStat )
00238 {
00239 printf("write error\n");
00240 return( TX_ERROR );
00241
00242 }
00243
00244 if( nWritten != (unsigned long) length )
00245 {
00246 printf("write error\n");
00247 return( TX_FAILURE );
00248
00249 }
00250
00251
00252 Sleep( AFTERWRITESLEEPTIME );
00253
00254 return( TX_SUCCESS );
00255 }
00256
00257
00258 lnp_tx_result
00259 lnp_integrity_write( const unsigned char *data,unsigned char length )
00260 {
00261 lnp_buffer[0]=0xf0;
00262 lnp_buffer[1]=length;
00263 memcpy( lnp_buffer+2, data, length );
00264 lnp_buffer[length+2]=(unsigned char) lnp_checksum( lnp_buffer, length+2 );
00265 #if DEBUGLNP
00266 printf("send broadcat package of length %d from this host 0x%02x ",
00267 length,lnp_host_address);
00268 #endif
00269 return( lnp_logical_write( lnp_buffer, length+3 ) );
00270 }
00271
00272
00273 lnp_tx_result
00274 lnp_addressing_write( const unsigned char *data,
00275 unsigned char length,
00276 unsigned char dest,
00277 unsigned char srcport )
00278 {
00279 lnp_buffer[0]=0xf1;
00280 lnp_buffer[1]=length+2;
00281 lnp_buffer[2]=dest;
00282 lnp_buffer[3]=lnp_host_address | (srcport & lnp_port_mask);
00283 memcpy( lnp_buffer+4, data, length );
00284 lnp_buffer[length+4]=(unsigned char) lnp_checksum( lnp_buffer, length+4 );
00285 #if DEBUGLNP
00286 printf("send package of length %d to dest 0x%02x from this host 0x%02x from port 0x%x\n",
00287 length,dest,lnp_host_address,(srcport & lnp_port_mask));
00288 #endif
00289 return( lnp_logical_write( lnp_buffer, length+5 ) );
00290 }
00291
00292
00293 void
00294 lnp_integrity_set_handler( lnp_integrity_handler_t handler )
00295 {
00296 #if LNPBLOCK
00297 printf( "integrity handler BLOCK\n" );
00298 #endif
00299 block_rcv();
00300 #if LNPBLOCK
00301 printf( "integrity handler BLOCKED\n" );
00302 #endif
00303 integrity_handler = handler;
00304 #if LNPBLOCK
00305 printf( "integrity handler UNBLOCK\n" );
00306 #endif
00307 unblock_rcv();
00308 }
00309
00310
00311 void
00312 lnp_addressing_set_handler( unsigned char port,
00313 lnp_addressing_handler_t handler )
00314 {
00315 #if LNPBLOCK
00316 printf( "addressing handler BLOCK\n" );
00317 #endif
00318 block_rcv();
00319 #if LNPBLOCK
00320 printf( "addressing handler BLOCKED\n" );
00321 #endif
00322 addressing_handler[port] = handler;
00323 #if LNPBLOCK
00324 printf( "addressing handler UNBLOCK\n" );
00325 #endif
00326 unblock_rcv();
00327 }
00328
00329
00330
00331 void
00332 lnp_receive_packet( const unsigned char *data )
00333 {
00334 unsigned char header=*(data++);
00335 unsigned char length=*(data++);
00336
00337
00338
00339
00340 switch(header)
00341 {
00342 case 0xf0:
00343 #if DEBUGLNP
00344 printf("send to integrity handler\n");
00345 #endif
00346 if( integrity_handler )
00347 {
00348 integrity_handler(data,length);
00349 }
00350 break;
00351 case 0xf1:
00352
00353 #if DEBUGLNP
00354 printf("send to addressing handler for port %x if hostmatch %02x=%02x&%02x \n",
00355 (*data & lnp_port_mask),lnp_host_address ,*data , lnp_host_mask);
00356 #endif
00357 if( length > 2 )
00358 {
00359 unsigned char dest=*(data++);
00360 if( lnp_host_address == (dest & lnp_host_mask))
00361 {
00362 unsigned char port=dest & lnp_port_mask;
00363
00364 if(addressing_handler[port])
00365 {
00366 unsigned char src=*(data++);
00367 addressing_handler[port](data,length-2,src);
00368 }
00369 }
00370 }
00371 }
00372 }
00373
00374
00375
00376
00377 static int
00378 lnp_integrity_active( void )
00379 {
00380 return( lnp_integrity_state != LNPwaitHeader );
00381 }
00382
00383
00384
00385
00386
00387 static void
00388 lnp_integrity_reset( void )
00389 {
00390 lnp_integrity_state=LNPwaitHeader;
00391 }
00392
00393
00394
00395
00396 void
00397 lnp_integrity_byte(unsigned char b)
00398 {
00399 static unsigned char buffer[MAX_LNP_PACKET];
00400 static int bytesRead,endOfData;
00401
00402 if( lnp_integrity_state == LNPwaitHeader )
00403 {
00404 bytesRead=0;
00405 }
00406
00407 buffer[bytesRead++]=b;
00408
00409 switch( lnp_integrity_state )
00410 {
00411 case LNPwaitHeader:
00412
00413
00414
00415 #if DEBUGLNP
00416 printf("header 0x%02x ",b);
00417 #endif
00418
00419 if( (b & (unsigned char) 0xfe) == (unsigned char) 0xf0 )
00420 {
00421 lnp_integrity_state= LNPwaitLength ;
00422
00423
00424
00425 stoptime = clock() + CLOCKS_PER_SEC * READTIMEOUT / 1000;
00426 #if DEBUGLNP
00427 printf(" SETTING stoptime %ld at currentime %ld", stoptime,clock());
00428 #endif
00429
00430 } else {
00431
00432 #if LNPBLOCK
00433 printf("read UNBLOCK\n");
00434 #endif
00435 unblock_rcv();
00436 }
00437 break;
00438 case LNPwaitLength:
00439 endOfData=b+2;
00440 lnp_integrity_state=LNPwaitData;
00441 #if DEBUGLNP
00442 printf("\n length 0x%02x \n",b);
00443 printf(" currentime %ld stoptime %ld ",clock(),stoptime);
00444 #endif
00445 break;
00446
00447 case LNPwaitData:
00448 if( bytesRead == endOfData )
00449 {
00450 lnp_integrity_state=LNPwaitCRC;
00451 }
00452 #if DEBUGLNP
00453 printf("data 0x%02x ",b);
00454 printf(" currentime %ld stoptime %ld ",clock(),stoptime);
00455 #endif
00456 break;
00457
00458 case LNPwaitCRC:
00459 if( b == (unsigned char)lnp_checksum(buffer,endOfData) )
00460 {
00461 #if DEBUGLNP
00462 printf( "\n\nCORRECT checksum\n" );
00463 printf( "checksum %02x %d \n", b, b );
00464 printf( "stoptime-currenttime %d \n", (stoptime-clock()) );
00465 printf( "\nreceive packet\n");
00466 #endif
00467 #if LNPCHECKSOMSTOP
00468 getchar( );
00469 #endif
00470 #if LNPBLOCK
00471 printf( "read UNBLOCK\n" );
00472 #endif
00473 unblock_rcv( );
00474 lnp_receive_packet( buffer );
00475 } else {
00476 #if DEBUGLNP
00477 printf( "\n\nFALSE checksum\n" );
00478 printf( "checksum %02x %d != %02x %d \n", b, b, lnp_checksum( buffer, endOfData ), lnp_checksum( buffer, endOfData ) );
00479 #endif
00480 #if LNPCHECKSOMSTOP
00481 getchar( );
00482 #endif
00483 #if LNPBLOCK
00484 printf( "read UNBLOCK\n" );
00485 #endif
00486 unblock_rcv( );
00487 }
00488 lnp_integrity_reset( );
00489 }
00490 }
00491
00492
00493
00494 static DWORD WINAPI
00495 ComReaderThread(LPVOID pParam)
00496 {
00497
00498 unsigned char recvd_byte;
00499 int totalsleep=0;
00500 DWORD dwRead=0;
00501 BOOL fReadStat;
00502 while( ! lnp_stop )
00503 {
00504
00505 if( lnp_integrity_state==LNPwaitHeader )
00506 {
00507 #if LNPBLOCK
00508 printf("read header BLOCK\n");
00509 #endif
00510 block_rcv();
00511 #if LNPBLOCK
00512 printf("read header BLOCKED\n");
00513 #endif
00514 }
00515
00516 fReadStat = ReadFile( comHandle,
00517 &recvd_byte,
00518 1,
00519 &dwRead,
00520 NULL );
00521
00522
00523 if( lnp_integrity_state == LNPwaitHeader )
00524 {
00525 stoptime=-1;
00526 totalsleep=0;
00527 }
00528
00529 if ( fReadStat && (dwRead == 1) )
00530 {
00531 lnp_integrity_byte( recvd_byte );
00532 totalsleep=0;
00533 }
00534
00535 if ( ! fReadStat )
00536 {
00537 #if LNPBLOCK
00538 printf("read header UNBLOCK\n");
00539 #endif
00540 unblock_rcv();
00541
00542
00543
00544
00545 if( lnp_integrity_state != LNPwaitHeader )
00546 {
00547 lnp_integrity_state=LNPwaitHeader;
00548 totalsleep=0;
00549 unblock_rcv( );
00550 }
00551 Sleep( 50 );
00552 continue;
00553 }
00554
00555 if( dwRead == 0 )
00556 {
00557
00558
00559 if( lnp_integrity_state==LNPwaitHeader )
00560 {
00561 #if LNPBLOCK
00562 printf( "read header UNBLOCK\n" );
00563 #endif
00564 unblock_rcv( );
00565
00566
00567
00568
00569 Sleep( 50 );
00570 #if DEBUGLNP
00571 printf( "sleep 50 , %d ", totalsleep );
00572 #endif
00573 continue;
00574 } else {
00575
00576
00577
00578
00579
00580
00581
00582
00583
00585
00586
00587
00588
00589 if( totalsleep > 30 )
00590 {
00591 lnp_integrity_state=LNPwaitHeader;
00592 totalsleep=0;
00593 #if DEBUGLNP
00594 printf( "\n\nREADING SLEEPED TOO LONG\n\n" );
00595 #endif
00596 unblock_rcv( );
00597 Sleep( 50 );
00598 }
00599
00601
00602
00603 time_t currenttime;
00604 currenttime=clock( );
00605
00606
00607 if(currenttime > stoptime)
00608 {
00609
00610 lnp_integrity_state= LNPwaitHeader;
00611
00612 #if DEBUGLNP
00613 printf( "\n\nPACKET TAKES TOO LONG : currentime %d stoptime %d \n\n", currenttime, stoptime );
00614 #endif
00615 #if LNPBLOCK
00616 printf( "read timeout UNBLOCK\n" );
00617 #endif
00618 unblock_rcv( );
00619 Sleep( 50 );
00620 }
00621
00622
00623
00624 #if DEBUGLNP
00625 printf( "sleep 5 , %d ", totalsleep );
00626 #endif
00627 Sleep( 5 );
00628 totalsleep=totalsleep+5;
00629 continue;
00630 }
00631 }
00632
00633
00634
00635
00636 }
00637
00638 ExitThread( 0 );
00639
00640 return( 1 );
00641 }
00642
00643
00644
00645
00646
00647 static DWORD WINAPI
00648 KeepAliveComThread(LPVOID pParam)
00649 {
00650 unsigned char cKeepAliveByte = TOWER_KEEP_ALIVE_CHAR;
00651
00652 while ( ! lnp_stop )
00653 {
00654 #if DEBUGLNP
00655 printf( "\n\n TRY to start wakeup tower \n\n" );
00656 #endif
00657 lnp_logical_write( &cKeepAliveByte, 1 );
00658 #if DEBUGLNP
00659 printf( "\n\n wakeup tower DONE \n\n" );
00660 #endif
00661 Sleep( (unsigned long)TOWER_KEEP_ALIVE_DELAY );
00662 }
00663
00664 ExitThread( 0 );
00665 return( 1 );
00666 }
00667
00668
00669 static int
00670 lnp_init_com()
00671 {
00672
00673 COMMTIMEOUTS CommTimeOuts;
00674 DCB dcb;
00675 BOOL fRetVal;
00676
00677
00678 if( ( comHandle = CreateFile( ComPort,
00679 GENERIC_READ | GENERIC_WRITE,
00680 0,
00681 NULL,
00682 OPEN_EXISTING,
00683 FILE_ATTRIBUTE_NORMAL,
00684 NULL ) ) == INVALID_HANDLE_VALUE )
00685 {
00686 printf( "Cannot open communication port" );
00687 comHandle=NULL;
00688 return( INIT_ERROR );
00689 }
00690
00691
00692 SetupComm( comHandle, 4096, 4096 );
00693
00694
00695 PurgeComm( comHandle,
00696 PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
00697
00698
00699
00700
00701
00702
00703 CommTimeOuts.ReadIntervalTimeout = 0;
00704 CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
00705 CommTimeOuts.ReadTotalTimeoutConstant = 20;
00706 CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
00707 CommTimeOuts.WriteTotalTimeoutConstant = 2000;
00708 SetCommTimeouts(comHandle, &CommTimeOuts ) ;
00709
00710
00711 dcb.DCBlength = sizeof( DCB ) ;
00712
00713 GetCommState( comHandle, &dcb );
00714
00715
00716 dcb.BaudRate = BAUDRATE;
00717 dcb.ByteSize = BYTESIZE;
00718 dcb.Parity = PARITY;
00719 dcb.StopBits = STOPBITS;
00720
00721 fRetVal = SetCommState( comHandle, &dcb );
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 EscapeCommFunction( comHandle, SETDTR );
00738
00739 if ( ! fRetVal )
00740 {
00741 CloseHandle( comHandle );
00742 comHandle=NULL;
00743 printf( "SetCommState()\n" );
00744 return( INIT_ERROR );
00745 }
00746
00747 return( INIT_OK );
00748 }
00749
00750 static int
00751 lnp_init_usb()
00752 {
00753
00754
00755 if( ( comHandle = CreateFile( USBPort,
00756 GENERIC_ALL,
00757 0,
00758 NULL,
00759 OPEN_EXISTING,
00760 FILE_ATTRIBUTE_NORMAL,
00761 NULL ) ) == INVALID_HANDLE_VALUE )
00762 {
00763 printf( "Cannot open communication port" );
00764 comHandle=NULL;
00765 return( INIT_ERROR );
00766 }
00767
00768 return( INIT_OK );
00769 }
00770
00771
00772
00773
00774 static int
00775 lnp_init_threads( )
00776 {
00777 DWORD dwThreadID;
00778
00779
00780 if( ! UseUSB )
00781 {
00782 h_KeepAliveComThread = CreateThread( NULL,
00783 0,
00784 KeepAliveComThread,
00785 0,
00786 NULL,
00787 &dwThreadID );
00788
00789 if( !h_KeepAliveComThread )
00790 {
00791 return( INIT_ERROR );
00792 }
00793
00794 SetThreadPriority( h_KeepAliveComThread, THREAD_PRIORITY_HIGHEST );
00795 Sleep( 1000 );
00796 }
00797
00798 h_ComReaderThread = CreateThread( NULL,
00799 0,
00800 ComReaderThread,
00801 0,
00802 NULL,
00803 &dwThreadID );
00804
00805 if (!h_ComReaderThread)
00806 {
00807 return( INIT_ERROR );
00808 }
00809
00810 SetThreadPriority( h_ComReaderThread, THREAD_PRIORITY_ABOVE_NORMAL );
00811
00812 return( INIT_OK );
00813 }
00814
00815
00816
00817 lnp_init_result
00818 lnp_init ( char *tcp_hostname,
00819 unsigned short tcp_port,
00820 unsigned char lnp_address,
00821 unsigned char lnp_mask,
00822 int flags )
00823 {
00824 int returnvalue;
00825 if( lnp_stop )
00826 {
00827 return( INIT_ERROR );
00828 }
00829
00830
00831
00832
00833 if ( lnp_test() )
00834
00835 {
00836
00837 return( INIT_OK );
00838
00839 };
00840
00841
00842 lnp_host_address = lnp_address ? lnp_address : DEFAULT_LNP_ADDR;
00843 lnp_host_mask = lnp_mask ? lnp_mask : DEFAULT_LNP_MASK;
00844 lnp_port_mask = lnp_host_mask ^ 0xFF;
00845 if( ( lnp_host_address & lnp_host_mask ) != lnp_host_address )
00846 {
00847 return( INIT_BAD_PARAM );
00848 }
00849
00850 lnp_integrity_state=LNPwaitHeader;
00851 connected = 1;
00852
00853
00854 char *rcxtty = getenv( "RCXTTY" );
00855
00856 UseUSB = ( strcmpi( rcxtty, "COM" ) != 0 );
00857
00858
00859 if( UseUSB )
00860 {
00861 returnvalue = lnp_init_usb( );
00862 } else {
00863 returnvalue = lnp_init_com( );
00864 }
00865
00866
00867
00868 if( returnvalue != INIT_OK )
00869 {
00870 lnp_shutdown( );
00871 return( INIT_ERROR );
00872 }
00873
00874 returnvalue = lnp_init_threads( );
00875
00876
00877
00878 if( returnvalue != INIT_OK )
00879 {
00880 lnp_shutdown();
00881 return( INIT_ERROR );
00882 }
00883
00884 return( INIT_OK );
00885 }
00886
00887