NULLMGR.CPP (96616B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /counterstrike/NULLMGR.CPP 2 3/07/97 6:40p Steve_tall $ */ 17 /*************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : NULLMGR.CPP * 24 * * 25 * Programmer : Bill Randolph * 26 * * 27 * Start Date : April 5, 1995 * 28 * * 29 * Last Update : May 1, 1995 [BRR] * 30 * * 31 *-------------------------------------------------------------------------* 32 * Functions: * 33 * NullModemClass::NullModemClass -- class constructor * 34 * NullModemClass::~NullModemClass -- class destructor * 35 * NullModemClass::Init -- initialization * 36 * NullModemClass::Send_Message -- sends a message * 37 * NullModemClass::Get_Message -- polls the Queue for a message * 38 * NullModemClass::Service -- main polling routine * 39 * NullModemClass::Num_Send -- Returns # of unACK'd send entries * 40 * NullModemClass::Num_Receive -- Returns # entries in the receive queue * 41 * NullModemClass::Response_Time -- Returns Queue's avg response time * 42 * NullModemClass::Reset_Response_Time -- Resets response time computatio* 43 * NullModemClass::Oldest_Send -- Returns ptr to oldest unACK'd send buf * 44 * NullModemClass::Detect_Modem -- Detects and initializes the modem * 45 * NullModemClass::Dial_Modem -- dials a number passed * 46 * NullModemClass::Answer_Modem -- waits for call and answers * 47 * NullModemClass::Hangup_Modem -- hangs up the modem * 48 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 49 #if (0)//PG 50 #include "function.h" 51 #ifdef WIN32 52 #include "wincomm.h" 53 #include "modemreg.h" 54 extern ModemRegistryEntryClass *ModemRegistry; 55 #endif //WIN32 56 #include "i86.h" 57 58 59 // Turn off "expression is not meaningful". 60 #pragma warning 628 9 61 62 63 // the following line was taken from Greenleaf's <ibmkeys.h> <asciidef.h> 64 // because of other define conflicts 65 66 #define ESC 27 67 #define NOKEY 0xffff 68 #define INIT_COMMAND_RETRIES 2 69 70 // this time is in milliseconds 71 72 #define DEFAULT_TIMEOUT 1500 73 74 // 75 // the following is for a fix around a greenleaf bug 76 // where they do not check for the value of abortkey 77 // to determine whether or not they call the abort modem function. 78 // 79 extern "C" { 80 extern void (*_AbortModemFunctionPtr)(int); 81 } 82 83 static void (*NullModemClass::OrigAbortModemFunc)(int); 84 85 static KeyNumType NullModemClass::Input; 86 static GadgetClass *NullModemClass::Commands; // button list 87 88 /* 89 ** Ugly hack: this string stores the string received from the modem 90 */ 91 char ModemRXString[80]; 92 93 94 /*************************************************************************** 95 * NullModemClass::NullModemClass -- class constructor * 96 * * 97 * INPUT: * 98 * numsend # desired entries for the send queue * 99 * numreceive # desired entries for the receive queue * 100 * maxlen application's max packet length * 101 * magicnum application-specific magic # (so we don't * 102 * accidentally end up talking to another one of our own * 103 * products using the same protocol) * 104 * * 105 * OUTPUT: * 106 * none. * 107 * * 108 * WARNINGS: * 109 * none. * 110 * * 111 * HISTORY: * 112 * 12/20/1994 BR : Created. * 113 *=========================================================================*/ 114 NullModemClass::NullModemClass (int numsend, int numreceive, int maxlen, 115 unsigned short magicnum) : ConnManClass() 116 { 117 /*------------------------------------------------------------------------ 118 Init Port to NULL; we haven't opened Greenleaf yet. 119 ------------------------------------------------------------------------*/ 120 #ifdef WIN32 121 PortHandle = NULL; 122 #else //WIN32 123 Port = NULL; 124 #endif //WIN32 125 126 Connection = NULL; 127 128 NumSend = numsend; 129 NumReceive = numreceive; 130 MaxLen = maxlen; 131 MagicNum = magicnum; 132 133 RXBuf = 0; 134 BuildBuf = 0; 135 136 EchoSize = 500; 137 EchoBuf = 0; 138 139 OldIRQPri = -1; 140 141 ModemVerboseOn = false; // default true 142 ModemEchoOn = false; // default true 143 ModemWaitCarrier = 50000; // default 50 * 1000ms = 50 secs 144 ModemCarrierDetect = 600; // default 6 * 100ms = .6 secs 145 ModemCarrierLoss = 1400; // default 14 * 100ms = 1.4 secs 146 ModemHangupDelay = 20000; // default 20 * 1000ms = 20 secs 147 ModemGuardTime = 1000; // default 50 * 20ms = 1 sec 148 ModemEscapeCode = '+'; // default ASCII 43 149 150 SendOverflows = 0; 151 ReceiveOverflows = 0; 152 CRCErrors = 0; 153 154 NumConnections = 0; 155 156 /*------------------------------------------------------------------------ 157 Init timing parameters 158 ------------------------------------------------------------------------*/ 159 RetryDelta = 60; // 60 ticks between retries 160 MaxRetries = -1; // disregard # retries 161 Timeout = 1200; // report bad connection after 20 seconds 162 163 } /* end of NullModemClass */ 164 165 166 /*************************************************************************** 167 * NullModemClass::~NullModemClass -- class destructor * 168 * * 169 * INPUT: * 170 * none. * 171 * * 172 * OUTPUT: * 173 * none. * 174 * * 175 * WARNINGS: * 176 * none. * 177 * * 178 * HISTORY: * 179 * 12/20/1994 BR : Created. * 180 *=========================================================================*/ 181 NullModemClass::~NullModemClass () 182 { 183 Delete_Connection(); 184 185 } /* end of ~NullModemClass */ 186 187 188 /*************************************************************************** 189 * NullModemClass::Init -- initialization * 190 * * 191 * INPUT: * 192 * port address * 193 * irq 2-15 * 194 * dev_name name of communications device (win32 only) * 195 * baud 300, 1200, 9600, etc * 196 * parity 'O' (odd), 'E' (even), 'N' (none), 'S' (space), * 197 * 'M' (mark) * 198 * wordlength 5, 6, 7, or 8 * 199 * stopbits 1 or 2 * 200 * * 201 * OUTPUT: * 202 * 1 = OK, 0 = error * 203 * * 204 * WARNINGS: * 205 * none. * 206 * * 207 * HISTORY: * 208 * 12/20/1994 BR : Created. * 209 * 10/9/1996 ST : Modified to take device name in win32 * 210 *=========================================================================*/ 211 int NullModemClass::Init (int port, int irq, char *dev_name, int baud, char parity, int wordlen, int stopbits, int flowcontrol) 212 { 213 int com; 214 215 #ifdef WIN32 216 217 /* 218 ** Get rid of the 'no reference to' warning 219 */ 220 irq = irq; 221 222 /* 223 ** Make sure the port is closed before we start 224 */ 225 if (PortHandle) { 226 CloseHandle (PortHandle); 227 PortHandle = NULL; 228 } 229 230 if (!Connection) { 231 232 #else //WIN32 233 234 int irqnum; 235 int address; 236 int status; 237 238 /* 239 ** Get rid of the 'no reference to' warning 240 */ 241 dev_name = dev_name; 242 243 if (Port) { 244 PortClose(Port); 245 Port = NULL; 246 }else { 247 248 #endif //WIN32 249 250 /*------------------------------------------------------------------------ 251 Init our Connection 252 ------------------------------------------------------------------------*/ 253 Connection = new NullModemConnClass (NumSend, NumReceive, MaxLen, 254 MagicNum); 255 256 Connection->Set_Retry_Delta (RetryDelta); 257 Connection->Set_Max_Retries (MaxRetries); 258 Connection->Set_TimeOut (Timeout); 259 260 /*--------------------------------------------------------------------- 261 Allocate our packet parsing buffer; make it the same # of packets as the 262 # of receive queue entries the application has requested. Use the 263 "Actual" maximum packet size, given from the connection; this allows for 264 both headers that get added to the packet. 265 ---------------------------------------------------------------------*/ 266 RXSize = Connection->Actual_Max_Packet() * NumReceive; 267 RXBuf = new char [RXSize]; 268 269 BuildBuf = new char [MaxLen]; 270 271 EchoBuf = new char [ EchoSize ]; 272 } 273 274 RXCount = 0; 275 EchoCount = 0; 276 277 278 /*------------------------------------------------------------------------ 279 This call allocates all necessary queue buffers 280 ------------------------------------------------------------------------*/ 281 switch (port) { 282 case 0x3f8: 283 com = COM1; 284 break; 285 286 case 0x2f8: 287 com = COM2; 288 break; 289 290 case 0x3e8: 291 com = COM3; 292 break; 293 294 case 0x2e8: 295 com = COM4; 296 break; 297 298 default: 299 com = COM5; 300 break; 301 } 302 303 #ifdef WIN32 304 int i; 305 306 /* 307 ** Create a new modem class for our com port 308 */ 309 if (!SerialPort) { 310 SerialPort = new WinModemClass; 311 } 312 313 /* 314 ** Shift up the baud rate to sensible values 315 */ 316 // if (baud == 14400) baud = 19200; 317 // if (baud == 28800) baud = 38400; 318 319 static char com_ids[9][5]={ 320 "COM1", 321 "COM2", 322 "COM3", 323 "COM4", 324 "COM5", 325 "COM6", 326 "COM7", 327 "COM8", 328 "COM9" 329 }; 330 331 char *device; 332 333 switch ( port ) { 334 335 case 0x3f8: 336 device = com_ids[0]; 337 break; 338 339 case 0x2f8: 340 device = com_ids[1]; 341 break; 342 343 case 0x3e8: 344 device = com_ids[2]; 345 break; 346 347 case 0x2e8: 348 device = com_ids[3]; 349 break; 350 351 case 1: 352 /* 353 ** 1 is a special value. It means use the device name not the port address. 354 */ 355 device = dev_name; 356 357 /* 358 ** If we can match a registry entry with the device name then use that, otherwise use 359 ** the device name directly to open the port with. 360 */ 361 if (ModemRegistry){ 362 delete ModemRegistry; 363 ModemRegistry = NULL; 364 } 365 for ( i=0 ; i<10 ; i++ ){ 366 ModemRegistry = new ModemRegistryEntryClass (i); 367 if (ModemRegistry->Get_Modem_Name()){ 368 if (!strcmp (dev_name, ModemRegistry->Get_Modem_Name() )){ 369 device = ModemRegistry->Get_Modem_Device_Name(); 370 break; 371 } 372 } 373 delete ModemRegistry; 374 ModemRegistry = NULL; 375 } 376 break; 377 378 default: 379 device = NULL; 380 } 381 382 383 384 /* 385 ** Open the com port 386 */ 387 PortHandle = SerialPort->Serial_Port_Open (device, baud, parity, wordlen, stopbits, flowcontrol); 388 if (PortHandle == INVALID_HANDLE_VALUE) { 389 Shutdown(); 390 return(false); 391 } 392 393 Connection->Init (PortHandle); 394 395 #else //WIN32 396 397 status = FastGetPortHardware( com, &irqnum, &address ); 398 if (status == ASSUCCESS) { 399 if (port != address || irq != irqnum) { 400 401 status = FastSetPortHardware( com, irq, port ); 402 403 if (status < ASSUCCESS) { 404 Mono_Printf( "Unable to set Com port status %d\n", status ); 405 Mono_Printf( "Com port number %d with address %x, irq %d\n", 406 com + 1, port, irq ); 407 } else { 408 Mono_Printf( "Changed Com port number %d to address %x, irq %d\n", 409 com + 1, port, irq ); 410 } 411 } else { 412 Mono_Printf( "No changes to Com port number %d with address %x, irq %d\n", 413 com + 1, port, irq ); 414 } 415 } else { 416 Mono_Printf( "Com port number %d\n", com + 1 ); 417 } 418 419 if (status != ASSUCCESS) { 420 Delete_Connection(); 421 return(false); 422 } 423 424 /*------------------------------------------------------------------------ 425 Open the Greenleaf port 426 ------------------------------------------------------------------------*/ 427 Port = PortOpenGreenleafFast (com, baud, parity, wordlen, stopbits); 428 429 if (Port->status != ASSUCCESS) { 430 Shutdown(); 431 return(false); 432 } 433 434 // UseRtsCts( Port, 1 ); // use RTS CTS hardware flow control 435 436 /*------------------------------------------------------------------------ 437 Init the Connection 438 ------------------------------------------------------------------------*/ 439 Connection->Init(Port); 440 //because Watcom is so stupid 441 flowcontrol = flowcontrol; 442 443 #endif //WIN32 444 445 NumConnections = 1; 446 447 return(true); 448 } 449 450 451 /*********************************************************************************************** 452 * NMC::Num_Connections -- returns NumConnections member * 453 * * 454 * * 455 * * 456 * INPUT: Nothing * 457 * * 458 * OUTPUT: NumConnections * 459 * * 460 * WARNINGS: None * 461 * * 462 * HISTORY: * 463 * 8/2/96 11:44AM ST : Documented / Win32 support * 464 *=============================================================================================*/ 465 int NullModemClass::Num_Connections( void ) 466 { 467 return(NumConnections); 468 } 469 470 471 /*********************************************************************************************** 472 * NMC::Delete_Connection -- removes the connection * 473 * * 474 * * 475 * * 476 * INPUT: Nothing * 477 * * 478 * OUTPUT: true * 479 * * 480 * WARNINGS: None * 481 * * 482 * HISTORY: * 483 * 8/2/96 11:44AM ST : Documented / Win32 support * 484 *=============================================================================================*/ 485 int NullModemClass::Delete_Connection( void ) 486 { 487 if (Connection) { 488 delete Connection; 489 Connection = NULL; 490 } 491 492 if (RXBuf) { 493 delete [] RXBuf; 494 RXBuf = NULL; 495 } 496 497 if (BuildBuf) { 498 delete [] BuildBuf; 499 BuildBuf = NULL; 500 } 501 502 if (EchoBuf) { 503 delete [] EchoBuf; 504 EchoBuf = NULL; 505 } 506 507 NumConnections = 0; 508 509 return( true ); 510 } /* end of Delete_Connection */ 511 512 513 514 /*********************************************************************************************** 515 * NMC::Init_Send_Queue -- Initialises the connections send queue * 516 * * 517 * * 518 * * 519 * INPUT: Nothing * 520 * * 521 * OUTPUT: true * 522 * * 523 * WARNINGS: None * 524 * * 525 * HISTORY: * 526 * 8/2/96 11:46AM ST : Documented / Win32 support * 527 *=============================================================================================*/ 528 int NullModemClass::Init_Send_Queue( void ) 529 { 530 531 /*------------------------------------------------------------------------ 532 Init the send queue 533 ------------------------------------------------------------------------*/ 534 if ( Connection ) { 535 Connection->Queue->Init_Send_Queue(); 536 } 537 538 return(true); 539 } 540 541 542 543 /*********************************************************************************************** 544 * NMC::Detect_Port -- Checks that the specified com port exists * 545 * * 546 * * 547 * * 548 * INPUT: ptr to SerialSettingsType * 549 * * 550 * OUTPUT: true if port is valid * 551 * * 552 * WARNINGS: Win32 version always returns true as win95 shouldnt allow us to open the * 553 * port if it doesnt exist or is in use by the mouse * 554 * * 555 * HISTORY: * 556 * 8/2/96 11:47AM ST : Documented / Win32 support * 557 *=============================================================================================*/ 558 DetectPortType NullModemClass::Detect_Port( SerialSettingsType *settings ) 559 { 560 561 #ifdef WIN32 562 563 static char com_ids[9][5]={ 564 "COM1", 565 "COM2", 566 "COM3", 567 "COM4", 568 "COM5", 569 "COM6", 570 "COM7", 571 "COM8", 572 "COM9" 573 }; 574 575 int i; 576 577 /* 578 ** Create a new modem class for our com port 579 */ 580 if (!SerialPort) { 581 SerialPort = new WinModemClass; 582 }else{ 583 SerialPort->Serial_Port_Close(); 584 } 585 586 /* 587 ** Shift up the baud rate to sensible values 588 */ 589 int baud = settings->Baud; 590 // if (baud == 14400) baud = 19200; 591 // if (baud == 28800) baud = 38400; 592 593 594 /* 595 ** Translate the port address into a usable device name 596 */ 597 char *device; 598 599 switch ( settings->Port ) { 600 601 case 0x3f8: 602 device = com_ids[0]; 603 break; 604 605 case 0x2f8: 606 device = com_ids[1]; 607 break; 608 609 case 0x3e8: 610 device = com_ids[2]; 611 break; 612 613 case 0x2e8: 614 device = com_ids[3]; 615 break; 616 617 case 1: 618 /* 619 ** 1 is a special value. It means use the device name not the port address. 620 */ 621 device = settings->ModemName; 622 623 /* 624 ** If we can match a registry entry with the device name then use that, otherwise use 625 ** the device name directly to open the port with. 626 */ 627 if (ModemRegistry){ 628 delete ModemRegistry; 629 ModemRegistry = NULL; 630 } 631 for ( i=0 ; i<10 ; i++){ 632 ModemRegistry = new ModemRegistryEntryClass (i); 633 if (ModemRegistry->Get_Modem_Name()){ 634 if (!strcmp (device, ModemRegistry->Get_Modem_Name() )){ 635 /* 636 ** Got a match. Break out leaving the registry info intact. 637 */ 638 device = ModemRegistry->Get_Modem_Device_Name(); 639 break; 640 } 641 } 642 delete ModemRegistry; 643 ModemRegistry = NULL; 644 } 645 break; 646 647 default: 648 return (PORT_INVALID); 649 } 650 651 /* 652 ** Open the com port 653 */ 654 HANDLE porthandle = SerialPort->Serial_Port_Open (device, baud, 0, 8, 1, settings->HardwareFlowControl); 655 656 if (porthandle == INVALID_HANDLE_VALUE){ 657 return (PORT_INVALID); 658 } 659 660 SerialPort->Serial_Port_Close(); 661 return (PORT_VALID); 662 663 664 665 #else //WIN32 666 667 union REGS regs ; 668 int com; 669 int irqnum; 670 int address; 671 int status; 672 673 674 // shutdown previous port 675 676 Shutdown(); 677 678 if (settings->IRQ > 0xf) { 679 return( PORT_INVALID ); 680 } 681 682 // 683 // check if the IRQ is the same as the mouse 684 // call mouse func to get mouse IRQ number 685 // 686 687 regs.x.eax = 0x0024; 688 int386( 0x33, ®s, ®s ); 689 690 // 691 // check for error 692 // 693 if (regs.w.ax != 0xffff) { 694 // 695 // is the mouse IRQ the same as that they selected 696 // 697 if (regs.h.cl == 0) { // PS/2 IRQ 0xc 698 if (settings->IRQ == 0xc) { 699 return( PORT_IRQ_INUSE ); 700 } 701 } else if (regs.h.cl == (unsigned char)(settings->IRQ)) { 702 return( PORT_IRQ_INUSE ); 703 } 704 } 705 706 if (settings->IRQ < 2 // 0 timer, 1 keyboard 707 || settings->IRQ == 6 // floppy disk 708 || settings->IRQ == 8 // CMOS real-time clock 709 || settings->IRQ == 0xd // math coprocessor error 710 || settings->IRQ == 0xe) { // hard disk 711 return( PORT_IRQ_INUSE ); 712 } 713 714 /*------------------------------------------------------------------------ 715 This call allocates all necessary queue buffers 716 ------------------------------------------------------------------------*/ 717 switch ( settings->Port ) { 718 case 0x3f8: 719 com = COM1; 720 break; 721 722 case 0x2f8: 723 com = COM2; 724 break; 725 726 case 0x3e8: 727 com = COM3; 728 break; 729 730 case 0x2e8: 731 com = COM4; 732 break; 733 734 default: 735 com = COM5; 736 break; 737 } 738 739 status = FastGetPortHardware( com, &irqnum, &address ); 740 if (status == ASSUCCESS) { 741 if (settings->Port != address || settings->IRQ != irqnum) { 742 status = FastSetPortHardware( com, settings->IRQ, settings->Port ); 743 } 744 } 745 746 if (status != ASSUCCESS) { 747 return( PORT_INVALID ); 748 } 749 750 /*------------------------------------------------------------------------ 751 Open the Greenleaf port 752 ------------------------------------------------------------------------*/ 753 Port = PortOpenGreenleafFast (com, settings->Baud, 'N', 8, 1); 754 755 status = Port->status; 756 757 PortClose(Port); 758 Port = NULL; 759 760 if (status == ASIRQINUSE) { 761 return( PORT_IRQ_INUSE ); 762 } else if (status != ASSUCCESS) { 763 return( PORT_INVALID ); 764 } 765 766 return( PORT_VALID ); 767 #endif //WIN32 768 } 769 770 771 /*********************************************************************************************** 772 * NullModemClass::ShutDown -- Closes serial port and removes the connection * 773 * * 774 * * 775 * * 776 * INPUT: Nothing * 777 * * 778 * OUTPUT: Nothing * 779 * * 780 * WARNINGS: None * 781 * * 782 * HISTORY: * 783 * 8/2/96 11:43AM ST : Documented / Win32 support * 784 *=============================================================================================*/ 785 void NullModemClass::Shutdown ( void ) 786 { 787 788 #ifdef WIN32 789 790 if (PortHandle && SerialPort) { 791 SerialPort->Serial_Port_Close(); 792 delete SerialPort; 793 SerialPort = NULL; 794 PortHandle = NULL; 795 Delete_Connection(); 796 } 797 798 #else //WIN32 799 if (Port) { 800 PortClose(Port); 801 Port = NULL; 802 Delete_Connection(); 803 } 804 805 #endif //WIN32 806 807 } /* end of Shutdown */ 808 809 810 /*************************************************************************** 811 * NullModemClass::Set_Timing -- sets timing for all connections * 812 * * 813 * This will set the timing parameters. This allows an application to * 814 * measure the Response_Time while running, and adjust timing accordingly. * 815 * * 816 * INPUT: * 817 * retrydelta value to set for retry delta * 818 * maxretries value to set for max # retries * 819 * timeout value to set for connection timeout * 820 * * 821 * OUTPUT: * 822 * none. * 823 * * 824 * WARNINGS: * 825 * none. * 826 * * 827 * HISTORY: * 828 * 08/07/1995 DRD : Created. * 829 *=========================================================================*/ 830 void NullModemClass::Set_Timing (unsigned long retrydelta, 831 unsigned long maxretries, unsigned long timeout) 832 { 833 RetryDelta = retrydelta; 834 MaxRetries = maxretries; 835 Timeout = timeout; 836 837 Connection->Set_Retry_Delta (RetryDelta); 838 Connection->Set_Max_Retries (MaxRetries); 839 Connection->Set_TimeOut (Timeout); 840 841 } /* end of Set_Timing */ 842 843 844 /*************************************************************************** 845 * NullModemClass::Send_Message -- sends a message * 846 * * 847 * For clarity's sake, here's what happens to the buffer passed in: * 848 * - It gets passed to the Connection's Send_Packet() routine * 849 * - The CommHeaderType header gets tacked onto it * 850 * - The resulting buffer gets added to the Connection's Send Queue * 851 * - When Service() determines that it needs to send the data, it * 852 * copies the entire packet (CommHeaderType and all) into its local * 853 * SendBuf, adds the packet start ID, length, and CRC, then sends it out.* 854 * * 855 * The ack_req argument will almost always be '1' (the default). The only * 856 * reason to use 0 is if you don't know whether the other system is * 857 * ready or not, so you have to periodically send out a query packet, * 858 * and wait for a response. (Using the connection's built-in retry * 859 * system would just blast out useless data if the other system isn't * 860 * even there.) * 861 * * 862 * INPUT: * 863 * buf buffer to send * 864 * buflen length of buffer * 865 * ack_req 1 = ACK is required; 0 = not * 866 * * 867 * OUTPUT: * 868 * 1 = OK; 0 = error * 869 * * 870 * WARNINGS: * 871 * none. * 872 * * 873 * HISTORY: * 874 * 12/20/1994 BR : Created. * 875 *=========================================================================*/ 876 int NullModemClass::Send_Message (void *buf, int buflen, int ack_req) 877 { 878 int rc; 879 880 if (NumConnections == 0) { 881 return( false ); 882 } 883 884 rc = Connection->Send_Packet(buf,buflen,ack_req); 885 if (!rc) 886 SendOverflows++; 887 888 return(rc); 889 890 } /* end of Send_Message */ 891 892 893 /*************************************************************************** 894 * NullModemClass::Get_Message -- polls the Queue for a message * 895 * * 896 * INPUT: * 897 * buf buffer to store message in * 898 * buflen ptr filled in with length of message * 899 * * 900 * OUTPUT: * 901 * 1 = message was received; 0 = wasn't * 902 * * 903 * WARNINGS: * 904 * none. * 905 * * 906 * HISTORY: * 907 * 12/20/1994 BR : Created. * 908 *=========================================================================*/ 909 int NullModemClass::Get_Message (void *buf, int *buflen) 910 { 911 if (NumConnections == 0) { 912 return( false ); 913 } 914 return( Connection->Get_Packet( buf, buflen ) ); 915 } 916 917 918 /*************************************************************************** 919 * NullModemClass::Service -- main polling routine * 920 * * 921 * INPUT: * 922 * none. * 923 * * 924 * OUTPUT: * 925 * 1 = OK, 0 = connection has gone bad * 926 * * 927 * WARNINGS: * 928 * none. * 929 * * 930 * HISTORY: * 931 * 12/20/1994 BR : Created. * 932 * 8/2/96 ST : Win32 support * 933 *=========================================================================*/ 934 int NullModemClass::Service (void) 935 { 936 int pos; // current position in RXBuf 937 int i; // loop counter 938 unsigned short length; 939 SerialHeaderType *header; // decoded packet start, length 940 SerialCRCType *crc; // decoded packet CRC 941 char moredata = 0; 942 943 if (NumConnections == 0) { 944 return( false ); 945 } 946 947 #ifdef WIN32 948 949 RXCount += SerialPort->Read_From_Serial_Port((unsigned char*)(RXBuf + RXCount), int(RXSize - RXCount) ); 950 951 #else //WIN32 952 953 int status; 954 static unsigned long last_time = 0; 955 956 /*------------------------------------------------------------------------ 957 First, copy all the bytes we can from the Greenleaf RX buffer to our 958 own buffer. 959 (For Win95, only call GetLineStatus() 60 times a second at most. 960 Otherwise, we don't receive any packets!) 961 ------------------------------------------------------------------------*/ 962 if ( (TickCount - last_time) > 0) { 963 if ( GetLineStatus( Port ) ) { 964 Mono_Set_Cursor(0,0); 965 ClearLineStatus( Port ); 966 } 967 last_time = TickCount; 968 } 969 970 status = SpaceUsedInRXBuffer( Port ); 971 972 if ( status < ASSUCCESS) { 973 // Smart_Printf( "SpaceUsedInRXBuffer status = %d, port status = %d \n", status, Port->status ); 974 975 if ( Port->status < ASSUCCESS ) { 976 ClearError( Port ); 977 } 978 979 } else if (status > 0) { 980 status = ReadBuffer( Port, RXBuf + RXCount, RXSize - RXCount ); 981 982 #if (CONN_DEBUG) 983 printf( "ReadBuffer status = %d, port status = %d, count = %d \n", status, Port->status, Port->count ); 984 #endif 985 // Smart_Printf( "ReadBuffer status = %d, port status = %d, count = %d \n", status, Port->status, Port->count ); 986 if (status < ASSUCCESS && status != ASBUFREMPTY) { 987 // Smart_Printf( "ReadBuffer ERRRRRRORRRRRR! \n" ); 988 } else { 989 moredata = 1; 990 } 991 992 if ( Port->status < ASSUCCESS ) { 993 ClearError( Port ); 994 } 995 996 RXCount += Port->count; 997 } 998 999 1000 #endif //WIN32 1001 1002 // minimum packet size 1003 1004 if ( RXCount < (PACKET_SERIAL_OVERHEAD_SIZE + 1) ) { 1005 return( Connection->Service() ); 1006 } 1007 1008 /*------------------------------------------------------------------------ 1009 Now scan the buffer for the start of a packet. 1010 ------------------------------------------------------------------------*/ 1011 pos = -1; 1012 for (i = 0; i <= RXCount - sizeof( short ); i++) { 1013 if ( *((unsigned short *)(RXBuf + i)) == PACKET_SERIAL_START ) { 1014 pos = i; 1015 break; 1016 } 1017 } 1018 1019 /*------------------------------------------------------------------------ 1020 No start code was found; throw away all bytes except the last few, and 1021 return. 1022 ------------------------------------------------------------------------*/ 1023 if (pos==-1) { 1024 // Smart_Printf( "No magic number found \n" ); 1025 /*..................................................................... 1026 move the remaining, un-checked bytes to the start of the buffer 1027 .....................................................................*/ 1028 memmove (RXBuf, RXBuf + i, sizeof( short ) - 1); 1029 RXCount = sizeof( short ) - 1; 1030 return( Connection->Service() ); 1031 } 1032 1033 /*------------------------------------------------------------------------ 1034 Check to see if there are enough bytes for the header to be decoded 1035 ------------------------------------------------------------------------*/ 1036 if ( (RXCount - pos) < sizeof( SerialHeaderType ) ) { 1037 memmove (RXBuf, RXBuf + pos, RXCount - pos); 1038 RXCount -= pos; 1039 return(Connection->Service()); 1040 } 1041 1042 /*------------------------------------------------------------------------ 1043 A start code was found; check the packet's length & CRC 1044 ------------------------------------------------------------------------*/ 1045 header = (SerialHeaderType *)(RXBuf + pos); 1046 1047 /*------------------------------------------------------------------------ 1048 If we lost a byte in the length, we may end up waiting a very long time 1049 for the buffer to get to the right length; check the verify value to 1050 make sure this didn't happen. 1051 ------------------------------------------------------------------------*/ 1052 if ( header->MagicNumber2 != PACKET_SERIAL_VERIFY ) { 1053 // Smart_Printf( "Verify failed\n"); 1054 // Hex_Dump_Data( (RXBuf + pos), PACKET_SERIAL_OVERHEAD_SIZE ); 1055 1056 pos += sizeof ( short ); // throw away the bogus start code 1057 memmove (RXBuf, RXBuf + pos, RXCount - pos); 1058 RXCount -= pos; 1059 return(Connection->Service()); 1060 } 1061 1062 length = header->Length; 1063 1064 /*------------------------------------------------------------------------ 1065 Special case: if the length comes out too long for us to process: 1066 - Assume the packet is bad 1067 - Throw away the bogus packet-start code 1068 - Return; we'll search for another packet-start code next time. 1069 ------------------------------------------------------------------------*/ 1070 if (length > MaxLen) { 1071 #if (CONN_DEBUG) 1072 printf( "length too lonnng\n" ); 1073 #endif 1074 // Smart_Printf( "length too lonnng %d, max %d \n", length, MaxLen ); 1075 1076 pos += sizeof ( short ); // throw away the bogus start code 1077 memmove (RXBuf, RXBuf + pos, RXCount - pos); 1078 RXCount -= pos; 1079 return(Connection->Service()); 1080 } 1081 1082 /*------------------------------------------------------------------------ 1083 If the entire packet isn't stored in our buffer, copy the remaining bytes 1084 to the front of the buffer & return. 1085 ------------------------------------------------------------------------*/ 1086 if ( (pos + length + PACKET_SERIAL_OVERHEAD_SIZE) > RXCount) { 1087 1088 if ( moredata ) { 1089 // Smart_Printf( "waiting for more data %d, pos = %d \n", ((length + PACKET_SERIAL_OVERHEAD_SIZE) - (RXCount - pos)), pos ); 1090 } 1091 1092 if (pos) { 1093 memmove (RXBuf, RXBuf + pos, RXCount - pos); 1094 RXCount -= pos; 1095 } 1096 return(Connection->Service()); 1097 } 1098 1099 /*------------------------------------------------------------------------ 1100 Now grab the CRC value in the packet, & compare it to the CRC value 1101 computed from the actual data. If they don't match, throw away the bogus 1102 start-code, move the rest to the front of the buffer, & return. 1103 We'll continue parsing this data when we're called next time. 1104 ------------------------------------------------------------------------*/ 1105 crc = (SerialCRCType *)(RXBuf + pos + sizeof( SerialHeaderType ) + length); 1106 if (NullModemConnClass::Compute_CRC(RXBuf + pos + 1107 sizeof( SerialHeaderType ), length) != crc->SerialCRC) { 1108 1109 CRCErrors++; 1110 1111 #if (CONN_DEBUG) 1112 printf( "CRC check failed\n" ); 1113 #endif 1114 // Smart_Printf( "CRC check failed for packet of length %d \n", length ); 1115 1116 // if (length < 100) { 1117 // Hex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) ); 1118 // } 1119 1120 pos += sizeof ( short ); // throw away the bogus start code 1121 memmove (RXBuf, RXBuf + pos, RXCount - pos); 1122 RXCount -= pos; 1123 return(Connection->Service()); 1124 } 1125 1126 #if(0) 1127 // Mono_Printf( "received %d bytes \n", sendlen ); 1128 Debug_Modem_Dump = true; 1129 Smart_Printf( "Received tick=%d, Protocol=%d \n", TickCount, Session.CommProtocol ); 1130 Hex_Dump_Data( (RXBuf + pos), (sizeof( SerialHeaderType) + length) ); 1131 Debug_Modem_Dump = false; 1132 #endif 1133 1134 /*------------------------------------------------------------------------ 1135 Give the new packet to the Connection to process. 1136 ------------------------------------------------------------------------*/ 1137 if (!Connection->Receive_Packet(RXBuf + pos + sizeof( SerialHeaderType ), length)) { 1138 ReceiveOverflows++; 1139 // Smart_Printf( "Received overflows %d \n", ReceiveOverflows ); 1140 } 1141 1142 #if(0) 1143 else { 1144 // Mono_Printf( "added packet \n", sendlen ); 1145 Debug_Modem_Dump = true; 1146 Smart_Printf( "Received Packet \n" ); 1147 Debug_Modem_Dump = false; 1148 } 1149 #endif 1150 1151 #if (0) 1152 Hex_Dump_Data( (RXBuf + pos), (PACKET_SERIAL_OVERHEAD_SIZE + length) ); 1153 #endif 1154 1155 /*------------------------------------------------------------------------ 1156 Move all data past this packet to the front of the buffer. 1157 ------------------------------------------------------------------------*/ 1158 pos += (PACKET_SERIAL_OVERHEAD_SIZE + length); 1159 memmove (RXBuf, RXBuf + pos, RXCount - pos); 1160 RXCount -= pos; 1161 1162 /*------------------------------------------------------------------------ 1163 Now, service the connection's Queue's; this will handle ACK & Retries. 1164 ------------------------------------------------------------------------*/ 1165 return(Connection->Service()); 1166 1167 } /* end of Service */ 1168 1169 1170 /*************************************************************************** 1171 * NullModemClass::Num_Send -- Returns # of unACK'd send entries * 1172 * * 1173 * INPUT: * 1174 * * 1175 * OUTPUT: * 1176 * * 1177 * WARNINGS: * 1178 * * 1179 * HISTORY: * 1180 * 05/01/1995 BRR : Created. * 1181 *=========================================================================*/ 1182 int NullModemClass::Num_Send(void) 1183 { 1184 if (Connection) 1185 return( Connection->Queue->Num_Send() ); 1186 else 1187 return (0); 1188 1189 } /* end of Num_Send */ 1190 1191 1192 /*************************************************************************** 1193 * NullModemClass::Num_Receive -- Returns # entries in the receive queue * 1194 * * 1195 * INPUT: * 1196 * * 1197 * OUTPUT: * 1198 * * 1199 * WARNINGS: * 1200 * * 1201 * HISTORY: * 1202 * 05/01/1995 BRR : Created. * 1203 *=========================================================================*/ 1204 int NullModemClass::Num_Receive(void) 1205 { 1206 if (Connection) 1207 return( Connection->Queue->Num_Receive() ); 1208 else 1209 return (0); 1210 1211 } /* end of Num_Receive */ 1212 1213 1214 /*************************************************************************** 1215 * NullModemClass::Response_Time -- Returns Queue's avg response time * 1216 * * 1217 * INPUT: * 1218 * * 1219 * OUTPUT: * 1220 * * 1221 * WARNINGS: * 1222 * * 1223 * HISTORY: * 1224 * 05/01/1995 BRR : Created. * 1225 *=========================================================================*/ 1226 unsigned long NullModemClass::Response_Time(void) 1227 { 1228 if (Connection) 1229 return( Connection->Queue->Avg_Response_Time() ); 1230 else 1231 return (0); 1232 1233 } /* end of Response_Time */ 1234 1235 1236 /*************************************************************************** 1237 * NullModemClass::Reset_Response_Time -- Resets response time computation * 1238 * * 1239 * INPUT: * 1240 * * 1241 * OUTPUT: * 1242 * * 1243 * WARNINGS: * 1244 * * 1245 * HISTORY: * 1246 * 05/01/1995 BRR : Created. * 1247 *=========================================================================*/ 1248 void NullModemClass::Reset_Response_Time(void) 1249 { 1250 if (Connection) 1251 Connection->Queue->Reset_Response_Time(); 1252 1253 } /* end of Reset_Response_Time */ 1254 1255 1256 /*************************************************************************** 1257 * Oldest_Send -- Returns ptr to oldest unACK'd send buffer * 1258 * * 1259 * INPUT: * 1260 * * 1261 * OUTPUT: * 1262 * * 1263 * WARNINGS: * 1264 * * 1265 * HISTORY: * 1266 * 05/01/1995 BRR : Created. * 1267 *=========================================================================*/ 1268 void * NullModemClass::Oldest_Send(void) 1269 { 1270 int i; 1271 SendQueueType *send_entry; // ptr to send entry header 1272 CommHeaderType *packet; 1273 void *buf = NULL; 1274 1275 for (i = 0; i < Connection->Queue->Num_Send(); i++) { 1276 send_entry = Connection->Queue->Get_Send(i); 1277 if (send_entry) { 1278 packet = (CommHeaderType *)send_entry->Buffer; 1279 if (packet->Code == ConnectionClass::PACKET_DATA_ACK && send_entry->IsACK == 0) { 1280 buf = send_entry->Buffer; 1281 break; 1282 } 1283 } 1284 } 1285 1286 return(buf); 1287 1288 } /* end of Oldest_Send */ 1289 1290 1291 /*************************************************************************** 1292 * NullModemClass::Configure_Debug -- sets up special debug values * 1293 * * 1294 * Mono_Debug_Print2() can look into a packet to pull out a particular * 1295 * ID, and can print both that ID and a string corresponding to * 1296 * that ID. This routine configures these values so it can find * 1297 * and decode the ID. This ID is used in addition to the normal * 1298 * CommHeaderType values. * 1299 * * 1300 * INPUT: * 1301 * index (not used) * 1302 * type_offset ID's byte offset into packet * 1303 * type_size size of ID, in bytes; 0 if none * 1304 * names ptr to array of names; use ID as an index into this * 1305 * namestart numerical start of the 1st name value * 1306 * namecount # in the names array; 0 if none. * 1307 * * 1308 * OUTPUT: * 1309 * none. * 1310 * * 1311 * WARNINGS: * 1312 * Names shouldn't be longer than 12 characters. * 1313 * * 1314 * HISTORY: * 1315 * 05/31/1995 BRR : Created. * 1316 *=========================================================================*/ 1317 void NullModemClass::Configure_Debug(int, int type_offset, int type_size, 1318 char **names, int namestart, int namecount) 1319 { 1320 if (Connection) 1321 Connection->Queue->Configure_Debug (type_offset, type_size, names, 1322 namestart, namecount); 1323 } 1324 1325 #ifdef CHEAT_KEYS 1326 /*************************************************************************** 1327 * Mono_Debug_Print -- Debug output routine * 1328 * * 1329 * INPUT: * 1330 * index (not used) * 1331 * refresh 1 = clear screen & completely refresh * 1332 * * 1333 * OUTPUT: * 1334 * none. * 1335 * * 1336 * WARNINGS: * 1337 * none. * 1338 * * 1339 * HISTORY: * 1340 * 05/02/1995 BRR : Created. * 1341 *=========================================================================*/ 1342 void NullModemClass::Mono_Debug_Print(int,int refresh) 1343 { 1344 if (!Connection) 1345 return; 1346 1347 Connection->Queue->Mono_Debug_Print (refresh); 1348 1349 if (refresh) { 1350 Mono_Set_Cursor (31,1); 1351 Mono_Printf ("Serial Port Queues"); 1352 1353 Mono_Set_Cursor (9,2); 1354 Mono_Printf ("Average Response Time:"); 1355 1356 Mono_Set_Cursor (20,3); 1357 Mono_Printf ("CRC Errors:"); 1358 1359 Mono_Set_Cursor (43,2); 1360 Mono_Printf ("Send Overflows:"); 1361 1362 Mono_Set_Cursor (40,3); 1363 Mono_Printf ("Receive Overflows:"); 1364 } 1365 1366 Mono_Set_Cursor (32,2); 1367 Mono_Printf ("%d ", Connection->Queue->Avg_Response_Time()); 1368 1369 Mono_Set_Cursor (32,3); 1370 Mono_Printf ("%d ", CRCErrors); 1371 1372 Mono_Set_Cursor (59,2); 1373 Mono_Printf ("%d ", SendOverflows); 1374 1375 Mono_Set_Cursor (59,3); 1376 Mono_Printf ("%d ", ReceiveOverflows); 1377 1378 Mono_Set_Cursor (2,5); 1379 Mono_Printf ("%d ", Num_Send()); 1380 1381 Mono_Set_Cursor (41,5); 1382 Mono_Printf ("%d ", Num_Receive()); 1383 1384 } /* end of Mono_Debug_Print */ 1385 #endif 1386 1387 1388 /*************************************************************************** 1389 * NullModemClass::Detect_Modem -- Detects and initializes the modem * 1390 * * 1391 * INPUT: * 1392 * settings ptr to SerialSettings structure * 1393 * * 1394 * OUTPUT: * 1395 * -1 init string invalid * 1396 * 0 no modem found * 1397 * 1 modem found * 1398 * * 1399 * WARNINGS: * 1400 * none. * 1401 * * 1402 * HISTORY: * 1403 * 06/02/1995 DRD : Created. * 1404 * 8/2/96 ST : Added Win32 support * 1405 *=========================================================================*/ 1406 int NullModemClass::Detect_Modem( SerialSettingsType *settings, bool reconnect ) 1407 { 1408 /*------------------------------------------------------------------------ 1409 Button Enumerations 1410 ------------------------------------------------------------------------*/ 1411 int status; 1412 int error_count = 0; 1413 1414 int x,y,width,height; // dialog dimensions 1415 char buffer[80*3]; 1416 1417 /* 1418 ** Get resolution factor 1419 */ 1420 // int factor = SeenBuff.Get_Width()/320; 1421 1422 /*------------------------------------------------------------------------ 1423 Determine the dimensions of the text to be used for the dialog box. 1424 These dimensions will control how the dialog box looks. 1425 ------------------------------------------------------------------------*/ 1426 strcpy( buffer, Text_String( TXT_INITIALIZING_MODEM ) ); 1427 1428 Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT); 1429 int lines = Format_Window_String(buffer, SeenBuff.Get_Height(), width, height); 1430 1431 width = max(width, 90 * RESFACTOR); 1432 width += 40 * RESFACTOR; 1433 height += 40 * RESFACTOR; 1434 1435 x = (SeenBuff.Get_Width() - width) / 2; 1436 y = (SeenBuff.Get_Height() - height) / 2; 1437 1438 /*------------------------------------------------------------------------ 1439 Initialize 1440 ------------------------------------------------------------------------*/ 1441 Set_Logic_Page(SeenBuff); 1442 1443 /*------------------------------------------------------------------------ 1444 Draw the dialog 1445 ------------------------------------------------------------------------*/ 1446 Hide_Mouse(); 1447 if ( !reconnect ) { 1448 Load_Title_Page(true); 1449 } 1450 1451 Dialog_Box(x, y, width, height); 1452 Draw_Caption(TXT_NONE, x, y, width); 1453 1454 if (lines == 1) { 1455 Fancy_Text_Print(buffer, x + width/2, y + 25, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT|TPF_CENTER); 1456 } else { 1457 Fancy_Text_Print(buffer, x + 20*RESFACTOR, y + 25, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT); 1458 } 1459 1460 Show_Mouse(); 1461 1462 1463 HMWaitForOK( 0, NULL ); 1464 1465 1466 /* 1467 ** OK, lets not mess about any more. Just turn on echo, verbose, and result codes 1468 ** before we even begin. At least this way when we get an error later on we have already 1469 ** removed all the steps we use to try and recover. 1470 ** The timeouts need to be quite small in case the modem is turned off. 1471 */ 1472 1473 /* 1474 ** Turn on result codes. 1475 */ 1476 Send_Modem_Command ( "ATQ0", '\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2); 1477 1478 /* 1479 ** Make result codes verbose. 1480 */ 1481 Send_Modem_Command ( "ATV1", '\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2); 1482 1483 /* 1484 ** Turn on echo. 1485 */ 1486 Send_Modem_Command ( "ATE1", '\r', buffer, 81, DEFAULT_TIMEOUT / 2, 2); 1487 1488 ModemVerboseOn = true; 1489 ModemEchoOn = true; 1490 1491 1492 1493 1494 1495 /* 1496 ** Try sending a plain old AT command to the modem. Now that we have theoretically 1497 ** turned on verbose result codes we should get an 'OK' back. 1498 ** 1499 */ 1500 status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 2 ); 1501 1502 if (status < ASSUCCESS) { 1503 #ifdef FIXIT_MULTI_SAVE 1504 return(false); 1505 #else 1506 if (WWMessageBox().Process(TXT_ERROR_NO_RESP, TXT_IGNORE, TXT_CANCEL)) return( false ); 1507 error_count++; 1508 #endif 1509 } 1510 1511 /* 1512 ** Send the user supplied modem init string 1513 */ 1514 if (settings->InitStringIndex == -1) { 1515 status = Send_Modem_Command( "", '\r', buffer, 81, 300, 1 ); 1516 } else { 1517 /* 1518 ** Split up the init string into seperate strings if it contains one or more '|' characters. 1519 ** This character acts as a carriage return/pause. 1520 */ 1521 char *istr = new char [2 + strlen( Session.InitStrings [settings->InitStringIndex] )]; 1522 char *tokenptr; 1523 strcpy (istr, Session.InitStrings [settings->InitStringIndex] ); 1524 1525 /* 1526 ** Tokenise the string and send it in chunks 1527 */ 1528 tokenptr = strtok ( istr, "|" ); 1529 while ( tokenptr ) { 1530 1531 status = Send_Modem_Command( tokenptr, '\r', buffer, 81, 3000, 1 ); 1532 /* 1533 ** Handle error case. 1534 */ 1535 if (status < ASSUCCESS) { 1536 if (WWMessageBox().Process(TXT_ERROR_NO_INIT, TXT_IGNORE, TXT_CANCEL)) { 1537 delete istr; 1538 return( false ); 1539 } 1540 #ifdef WIN32 1541 error_count++; 1542 #endif //WIN32 1543 break; 1544 } 1545 1546 tokenptr = strtok ( NULL, "|"); 1547 1548 } 1549 } 1550 1551 #ifdef WIN32 1552 1553 if (settings->Port == 1 && ModemRegistry) { 1554 /* 1555 ** Send the init strings from the registry if available 1556 */ 1557 char send_string[256] = {"AT"}; 1558 1559 /* 1560 ** Send the init string for hardware flow control 1561 */ 1562 if (settings->HardwareFlowControl){ 1563 if (ModemRegistry->Get_Modem_Hardware_Flow_Control()) { 1564 strcpy (&send_string[2], ModemRegistry->Get_Modem_Hardware_Flow_Control()); 1565 status = Send_Modem_Command (send_string, '\r', buffer, 81, 300, 1); 1566 if (status != MODEM_CMD_OK && status != MODEM_CMD_0) { 1567 if (WWMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false); 1568 } 1569 } 1570 }else{ 1571 /* 1572 ** Send the init string for no flow control 1573 */ 1574 if (ModemRegistry->Get_Modem_No_Flow_Control()) { 1575 strcpy (&send_string[2], ModemRegistry->Get_Modem_No_Flow_Control()); 1576 status = Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1); 1577 if (status != MODEM_CMD_OK && status != MODEM_CMD_0) { 1578 if (WWMessageBox().Process(TXT_NO_FLOW_CONTROL_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false); 1579 } 1580 } 1581 } 1582 1583 1584 /* 1585 ** Send the string for data compresseion 1586 */ 1587 if (settings->Compression){ 1588 1589 if (ModemRegistry->Get_Modem_Compression_Enable()) { 1590 strcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Enable()); 1591 Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1); 1592 if (status != MODEM_CMD_OK && status != MODEM_CMD_0) { 1593 if (WWMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false); 1594 } 1595 } 1596 }else{ 1597 1598 if (ModemRegistry->Get_Modem_Compression_Disable()) { 1599 strcpy (&send_string[2], ModemRegistry->Get_Modem_Compression_Disable()); 1600 Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1); 1601 if (status != MODEM_CMD_OK && status != MODEM_CMD_0) { 1602 if (WWMessageBox().Process(TXT_NO_COMPRESSION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false); 1603 } 1604 } 1605 } 1606 1607 1608 /* 1609 ** Send the string for error correction 1610 */ 1611 if (settings->ErrorCorrection){ 1612 1613 if (ModemRegistry->Get_Modem_Error_Correction_Enable()) { 1614 strcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Enable()); 1615 Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1); 1616 if (status != MODEM_CMD_OK && status != MODEM_CMD_0) { 1617 if (WWMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false); 1618 } 1619 } 1620 }else{ 1621 if (ModemRegistry->Get_Modem_Error_Correction_Disable()) { 1622 strcpy (&send_string[2], ModemRegistry->Get_Modem_Error_Correction_Disable()); 1623 Send_Modem_Command (send_string, '\r', buffer, 81, DEFAULT_TIMEOUT, 1); 1624 if (status != MODEM_CMD_OK && status != MODEM_CMD_0) { 1625 if (WWMessageBox().Process(TXT_NO_ERROR_CORRECTION_RESPONSE, TXT_IGNORE, TXT_CANCEL)) return (false); 1626 } 1627 } 1628 } 1629 } 1630 1631 #endif //WIN32 1632 1633 1634 /* 1635 ** We require that auto-answer be disabled so turn it off now. 1636 */ 1637 status = Send_Modem_Command( "ATS0=0", '\r', buffer, 81, DEFAULT_TIMEOUT, INIT_COMMAND_RETRIES ); 1638 if (status != MODEM_CMD_OK) { 1639 if (WWMessageBox().Process(TXT_ERROR_NO_DISABLE, TXT_IGNORE, TXT_CANCEL)) return( false ); 1640 error_count++; 1641 } 1642 1643 /* 1644 ** If we had an unreasonable number of ignored errors then return failure 1645 */ 1646 if (error_count >= 3) { 1647 WWMessageBox().Process(TXT_ERROR_TOO_MANY, TXT_OK); 1648 return (false); 1649 } 1650 1651 return( true ); 1652 } 1653 1654 1655 /*************************************************************************** 1656 * NullModemClass::Dial_Modem -- dials a number passed * 1657 * * 1658 * INPUT: * 1659 * settings ptr to SerialSettings structure * 1660 * * 1661 * OUTPUT: * 1662 * status DialStatus * 1663 * * 1664 * WARNINGS: * 1665 * none. * 1666 * * 1667 * HISTORY: * 1668 * 06/02/1995 DRD : Created. * 1669 * 8/2/96 ST : Win32 support * 1670 *=========================================================================*/ 1671 DialStatusType NullModemClass::Dial_Modem( char *string, DialMethodType method, bool reconnect ) 1672 { 1673 /* 1674 ** Get the resolution factor 1675 */ 1676 // int factor = SeenBuff.Get_Width()/320; 1677 1678 /*------------------------------------------------------------------------ 1679 Button Enumerations 1680 ------------------------------------------------------------------------*/ 1681 enum { 1682 BUTTON_CANCEL = 100, 1683 }; 1684 1685 /*------------------------------------------------------------------------ 1686 Dialog variables 1687 ------------------------------------------------------------------------*/ 1688 bool process = true; // process while true 1689 #ifndef WIN32 1690 int status; 1691 #endif //WIN32 1692 int delay; 1693 DialStatusType dialstatus; 1694 1695 int x,y,width,height; // dialog dimensions 1696 char buffer[80*3]; 1697 1698 1699 /*------------------------------------------------------------------------ 1700 Determine the dimensions of the text to be used for the dialog box. 1701 These dimensions will control how the dialog box looks. 1702 ------------------------------------------------------------------------*/ 1703 if (reconnect) { 1704 strcpy( buffer, Text_String( TXT_MODEM_CONNERR_REDIALING ) ); 1705 } else { 1706 strcpy( buffer, Text_String( TXT_DIALING ) ); 1707 } 1708 1709 Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_TEXT); 1710 Format_Window_String(buffer, SeenBuff.Get_Height(), width, height); 1711 1712 int text_width = width; 1713 width = max(width, 90 * RESFACTOR); 1714 width += 40 * RESFACTOR; 1715 height += 60 * RESFACTOR; 1716 1717 x = (SeenBuff.Get_Width() - width) / 2; 1718 y = (SeenBuff.Get_Height() - height) / 2; 1719 1720 TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 1721 x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1), 1722 y + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR); 1723 1724 /*------------------------------------------------------------------------ 1725 Initialize 1726 ------------------------------------------------------------------------*/ 1727 Set_Logic_Page(SeenBuff); 1728 1729 /*------------------------------------------------------------------------ 1730 Create the list 1731 ------------------------------------------------------------------------*/ 1732 Commands = &cancelbtn; 1733 1734 Commands->Flag_List_To_Redraw(); 1735 1736 /*------------------------------------------------------------------------ 1737 Draw the dialog 1738 ------------------------------------------------------------------------*/ 1739 Hide_Mouse(); 1740 if ( !reconnect ) { 1741 Load_Title_Page(true); 1742 } 1743 1744 Dialog_Box(x, y, width, height); 1745 Draw_Caption(TXT_NONE, x, y, width); 1746 1747 Fancy_Text_Print(buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25 *RESFACTOR, GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT); 1748 1749 Commands->Draw_All(); 1750 Show_Mouse(); 1751 1752 /* 1753 ** Start waiting for connection response 1754 */ 1755 #ifdef WIN32 1756 SerialPort->Set_Modem_Dial_Type((WinCommDialMethodType) method); 1757 /* 1758 ** Clear out any old modem results that might be hanging around 1759 */ 1760 SerialPort->Get_Modem_Result(60, buffer, 81); 1761 /* 1762 ** Dial that sucker 1763 */ 1764 SerialPort->Dial_Modem(string); 1765 1766 #else //WIN32 1767 HMSetDialingMethod( Port, (int)method ); 1768 status = HMDial( Port, string ); 1769 1770 #endif //WIN32 1771 1772 1773 /* 1774 ** Sets up the ability to abort modem commands when any input is in the 1775 ** Keyboard buffer. This also calls the game CallBack(). 1776 */ 1777 Setup_Abort_Modem(); 1778 1779 /*------------------------------------------------------------------------ 1780 Main Processing Loop 1781 ------------------------------------------------------------------------*/ 1782 process = true; 1783 delay = ModemWaitCarrier; 1784 while (process) { 1785 #ifdef WIN32 1786 /* 1787 ** If we have just received input focus again after running in the background then 1788 ** we need to redraw. 1789 */ 1790 if (AllSurfaces.SurfacesRestored) { 1791 AllSurfaces.SurfacesRestored=FALSE; 1792 Commands->Draw_All(); 1793 } 1794 1795 delay = SerialPort->Get_Modem_Result(delay, buffer, 81); 1796 #else //WIN32 1797 delay = HMInputLine( Port, delay, buffer, 81 ); 1798 #endif //WIN32 1799 1800 /*..................................................................... 1801 Process input 1802 .....................................................................*/ 1803 switch (Input) { 1804 case (KN_ESC): 1805 case (BUTTON_CANCEL | KN_BUTTON): 1806 dialstatus = DIAL_CANCELED; 1807 process = false; 1808 break; 1809 1810 default: 1811 break; 1812 } 1813 1814 if (process) { 1815 if ( strncmp( buffer, "CON", 3 ) == 0 ) { 1816 memset (ModemRXString, 0, 80); 1817 strncpy (ModemRXString, buffer, 79); 1818 dialstatus = DIAL_CONNECTED; 1819 process = false; 1820 } else if ( strncmp( buffer, "BUSY", 4 ) == 0 ) { 1821 dialstatus = DIAL_BUSY; 1822 process = false; 1823 } else if ( strncmp( buffer, "NO C", 4 ) == 0 ) { 1824 dialstatus = DIAL_NO_CARRIER; 1825 process = false; 1826 } else if ( strncmp( buffer, "NO D", 4 ) == 0 ) { 1827 dialstatus = DIAL_NO_DIAL_TONE; 1828 process = false; 1829 } else if ( strncmp( buffer, "ERRO", 4 ) == 0 ) { 1830 dialstatus = DIAL_ERROR; 1831 process = false; 1832 } 1833 } 1834 1835 if (delay <= 0) { 1836 process = false; 1837 } 1838 } 1839 1840 Remove_Abort_Modem(); 1841 1842 return( dialstatus ); 1843 1844 } /* end of Dial_Modem */ 1845 1846 1847 /*************************************************************************** 1848 * NullModemClass::Answer_Modem -- waits for call and answers * 1849 * * 1850 * INPUT: * 1851 * reconnect whether this is to reconnect * 1852 * * 1853 * OUTPUT: * 1854 * status DialStatus * 1855 * * 1856 * WARNINGS: * 1857 * none. * 1858 * * 1859 * HISTORY: * 1860 * 06/02/1995 DRD : Created. * 1861 * 8/2/96 ST : Added Win32 support * 1862 *=========================================================================*/ 1863 DialStatusType NullModemClass::Answer_Modem( bool reconnect ) 1864 { 1865 /* 1866 ** Get the resolution factor 1867 */ 1868 // int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2; 1869 1870 /*------------------------------------------------------------------------ 1871 Button Enumerations 1872 ------------------------------------------------------------------------*/ 1873 enum { 1874 BUTTON_CANCEL = 100, 1875 }; 1876 1877 /*------------------------------------------------------------------------ 1878 Redraw values: in order from "top" to "bottom" layer of the dialog 1879 ------------------------------------------------------------------------*/ 1880 typedef enum { 1881 REDRAW_NONE = 0, 1882 REDRAW_BUTTONS, 1883 REDRAW_BACKGROUND, 1884 REDRAW_ALL = REDRAW_BACKGROUND 1885 } RedrawType; 1886 1887 /*------------------------------------------------------------------------ 1888 Dialog variables 1889 ------------------------------------------------------------------------*/ 1890 RedrawType display = REDRAW_ALL; // redraw level 1891 bool process = true; // process while true 1892 #ifndef WIN32 1893 int status; 1894 #endif //WIN32 1895 int delay; 1896 DialStatusType dialstatus; 1897 bool ring = false; 1898 1899 int x,y,width,height; // dialog dimensions 1900 int text_width; 1901 char text_buffer[80*3]; 1902 char comm_buffer[80*3]; 1903 1904 /*------------------------------------------------------------------------ 1905 Determine the dimensions of the text to be used for the dialog box. 1906 These dimensions will control how the dialog box looks. 1907 ------------------------------------------------------------------------*/ 1908 if (reconnect) { 1909 strcpy( text_buffer, Text_String( TXT_MODEM_CONNERR_WAITING ) ); 1910 } else { 1911 strcpy( text_buffer, Text_String( TXT_WAITING_FOR_CALL ) ); 1912 } 1913 1914 Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TPF_TEXT); 1915 Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height); 1916 1917 text_width = width; 1918 width = max(width, 90 * RESFACTOR); 1919 width += 40 * RESFACTOR; 1920 height += 60 * RESFACTOR; 1921 1922 x = (SeenBuff.Get_Width() - width) / 2; 1923 y = (SeenBuff.Get_Height() - height) / 2; 1924 1925 TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 1926 x + ((width - (String_Pixel_Width( Text_String( TXT_CANCEL ) ) + 8 * RESFACTOR)) >> 1), 1927 y + height - (FontHeight + FontYSpacing + 2 * RESFACTOR) - 10 * RESFACTOR); 1928 1929 /*------------------------------------------------------------------------ 1930 Initialize 1931 ------------------------------------------------------------------------*/ 1932 Set_Logic_Page(SeenBuff); 1933 Load_Title_Page(true); 1934 1935 Input = KN_NONE; 1936 1937 /*------------------------------------------------------------------------ 1938 Create the list 1939 ------------------------------------------------------------------------*/ 1940 Commands = &cancelbtn; 1941 1942 Commands->Flag_List_To_Redraw(); 1943 1944 /* 1945 ** Sets up the ability to abort modem commands when any input is in the 1946 ** Keyboard buffer. This also calls the game CallBack() and Input(). 1947 */ 1948 Setup_Abort_Modem(); 1949 1950 /*------------------------------------------------------------------------ 1951 Main Processing Loop 1952 ------------------------------------------------------------------------*/ 1953 process = true; 1954 delay = 60000; 1955 while (process) { 1956 #ifdef WIN32 1957 /* 1958 ** If we have just received input focus again after running in the background then 1959 ** we need to redraw. 1960 */ 1961 if (AllSurfaces.SurfacesRestored) { 1962 AllSurfaces.SurfacesRestored=FALSE; 1963 display=REDRAW_ALL; 1964 } 1965 #endif //WIN32 1966 1967 /*..................................................................... 1968 Refresh display if needed 1969 .....................................................................*/ 1970 if (display) { 1971 Hide_Mouse(); 1972 if (display >= REDRAW_BACKGROUND) { 1973 /*............................................................... 1974 Refresh the backdrop 1975 ...............................................................*/ 1976 if ( !reconnect ) { 1977 Load_Title_Page(true); 1978 } 1979 1980 /*............................................................... 1981 Draw the background 1982 ...............................................................*/ 1983 Dialog_Box(x, y, width, height); 1984 1985 /*............................................................... 1986 Draw the labels 1987 ...............................................................*/ 1988 Draw_Caption(TXT_NONE, x, y, width); 1989 1990 Fancy_Text_Print(text_buffer, SeenBuff.Get_Width()/2 - text_width/2, y + 25 * RESFACTOR, 1991 GadgetClass::Get_Color_Scheme(), TBLACK, TPF_TEXT); 1992 1993 Commands->Draw_All(); 1994 } 1995 Show_Mouse(); 1996 display = REDRAW_NONE; 1997 } 1998 1999 #ifdef WIN32 2000 delay = SerialPort->Get_Modem_Result(delay, comm_buffer, 81); 2001 #else //WIN32 2002 delay = HMInputLine( Port, delay, comm_buffer, 81 ); 2003 #endif //WIN32 2004 2005 2006 /*..................................................................... 2007 Process input 2008 .....................................................................*/ 2009 if (!Input) Input = Commands->Input(); 2010 switch (Input) { 2011 case (KN_ESC): 2012 case (BUTTON_CANCEL | KN_BUTTON): 2013 dialstatus = DIAL_CANCELED; 2014 process = false; 2015 break; 2016 2017 default: 2018 break; 2019 } 2020 2021 if (process) { 2022 if ( strncmp( comm_buffer, "RING", 4 ) == 0 ) { 2023 2024 strcpy( text_buffer, Text_String( TXT_ANSWERING ) ); 2025 2026 Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_TEXT); 2027 Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height); 2028 2029 text_width = width; 2030 width = max(width, 90 * RESFACTOR); 2031 width += 40 * RESFACTOR; 2032 height += 60 * RESFACTOR; 2033 2034 x = (SeenBuff.Get_Width() - width) / 2; 2035 y = (SeenBuff.Get_Height() - height) / 2; 2036 2037 #ifdef WIN32 2038 SerialPort->Write_To_Serial_Port ((unsigned char*)"ATA\r", strlen("ATA\r")); 2039 #else //WIN32 2040 PortKillTime( Port, 100 ); 2041 HMWaitForOK( 0, NULL ); 2042 status = HMAnswer( Port ); 2043 #endif //WIN32 2044 2045 ring = true; 2046 delay = ModemWaitCarrier; 2047 display = REDRAW_ALL; 2048 } else if ( strncmp( comm_buffer, "CON", 3 ) == 0 ) { 2049 memset (ModemRXString, 0, 80); 2050 strncpy (ModemRXString, comm_buffer, 79); 2051 dialstatus = DIAL_CONNECTED; 2052 process = false; 2053 } else if ( strncmp( comm_buffer, "BUSY", 4 ) == 0 ) { 2054 dialstatus = DIAL_BUSY; 2055 process = false; 2056 } else if ( strncmp( comm_buffer, "NO C", 4 ) == 0 ) { 2057 dialstatus = DIAL_NO_CARRIER; 2058 process = false; 2059 } else if ( strncmp( comm_buffer, "ERRO", 4 ) == 0 ) { 2060 dialstatus = DIAL_ERROR; 2061 WWMessageBox().Process(TXT_ERROR_ERROR, TXT_OK); 2062 process = false; 2063 } 2064 } 2065 2066 #ifdef WIN32 2067 2068 if (delay <= 0) { 2069 if (ring) { 2070 if (SerialPort->Get_Modem_Status() & CD_SET) { 2071 sprintf(ModemRXString, "%s", "Connected"); 2072 dialstatus = DIAL_CONNECTED; 2073 } else { 2074 dialstatus = DIAL_ERROR; 2075 WWMessageBox().Process(TXT_ERROR_TIMEOUT, TXT_OK); 2076 } 2077 process = false; 2078 } else { 2079 delay = 60000; 2080 } 2081 } 2082 #else //WIN32 2083 2084 if (delay <= 0) { 2085 if (ring) { 2086 process = false; 2087 } else { 2088 delay = 60000; 2089 } 2090 } 2091 #endif //WIN32 2092 2093 } 2094 2095 Remove_Abort_Modem(); 2096 2097 return( dialstatus ); 2098 2099 } /* end of Answer_Modem */ 2100 2101 2102 /*************************************************************************** 2103 * NullModemClass::Hangup_Modem -- hangs up the modem * 2104 * * 2105 * INPUT: * 2106 * none * 2107 * * 2108 * OUTPUT: * 2109 * status successful or not * 2110 * * 2111 * WARNINGS: * 2112 * none. * 2113 * * 2114 * HISTORY: * 2115 * 06/02/1995 DRD : Created. * 2116 * 8/2/96 : Added Win32 support * 2117 *=========================================================================*/ 2118 bool NullModemClass::Hangup_Modem( void ) 2119 { 2120 int status; 2121 int delay; 2122 char buffer[81]; 2123 char escape[4]; 2124 2125 /* 2126 ** Turn modem servicing off in the callback routine. 2127 */ 2128 Session.ModemService = false; 2129 2130 status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 ); 2131 2132 if (status == MODEM_CMD_OK) { 2133 Session.ModemService = true; 2134 return( true ); 2135 } 2136 2137 /* 2138 ** Toggle DTR low then high 2139 */ 2140 #ifdef WIN32 2141 SerialPort->Set_Serial_DTR(FALSE); 2142 Delay(3200/60); 2143 SerialPort->Set_Serial_DTR(TRUE); 2144 #else //WIN32 2145 2146 SetDtr( Port, 0 ); 2147 PortKillTime( Port, 3200 ); 2148 SetDtr( Port, 1 ); 2149 #endif //WIN32 2150 2151 status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 ); 2152 2153 if (status == MODEM_CMD_OK) { 2154 Session.ModemService = true; 2155 return( true ); 2156 } 2157 2158 delay = ModemGuardTime; 2159 while ( delay > 0 ) { 2160 #ifdef WIN32 2161 delay = SerialPort->Get_Modem_Result(delay, buffer, 81); 2162 #else //WIN32 2163 delay = HMInputLine( Port, delay, buffer, 81 ); 2164 #endif //WIN32 2165 } 2166 2167 /* 2168 ** Send modem break commmand 2169 */ 2170 escape[0] = ModemEscapeCode; 2171 escape[1] = ModemEscapeCode; 2172 escape[2] = ModemEscapeCode; 2173 escape[3] = 0; 2174 2175 #ifdef WIN32 2176 SerialPort->Write_To_Serial_Port((unsigned char*)escape, 3); 2177 #else //WIN32 2178 status = HMSendStringNoWait( Port, escape, -1 ); 2179 #endif //WIN32 2180 2181 2182 delay = ModemGuardTime; 2183 while ( delay > 0 ) { 2184 #ifdef WIN32 2185 delay = SerialPort->Get_Modem_Result(delay, buffer, 81); 2186 #else //WIN32 2187 delay = HMInputLine( Port, delay, buffer, 81 ); 2188 #endif //WIN32 2189 2190 if ( strncmp( buffer, "OK", 2 ) == 0 ) { 2191 break; 2192 } 2193 } 2194 2195 /* 2196 ** Send the hangup command 2197 */ 2198 status = Send_Modem_Command( "ATH", '\r', buffer, 81, ModemHangupDelay, 1 ); 2199 2200 if (status == MODEM_CMD_OK) { 2201 } else { 2202 Session.ModemService = true; 2203 return( false ); 2204 } 2205 2206 /* 2207 ** Send spurious ATZ command for no apparent reason 2208 */ 2209 status = Send_Modem_Command( "ATZ", '\r', buffer, 81, 5000, 1 ); 2210 2211 if (status != MODEM_CMD_OK) { 2212 Session.ModemService = true; 2213 return( false ); 2214 } 2215 2216 Session.ModemService = true; 2217 return( true ); 2218 2219 } /* end of Hangup_Modem */ 2220 2221 2222 /*********************************************************************************************** 2223 * NMC::Setup_Modem_Echo -- Sets the echo callback function pointer * 2224 * * 2225 * * 2226 * * 2227 * INPUT: Ptr to callback function * 2228 * * 2229 * OUTPUT: Nothing * 2230 * * 2231 * WARNINGS: None * 2232 * * 2233 * HISTORY: * 2234 * 8/2/96 12:48PM ST : Documented and added WIn32 support * 2235 *=============================================================================================*/ 2236 void NullModemClass::Setup_Modem_Echo( void ( *func )( char c) ) 2237 { 2238 #ifdef WIN32 2239 SerialPort->Set_Echo_Function(func); 2240 #else //WIN32 2241 HMSetUpEchoRoutine( func ); 2242 #endif //WIN32 2243 2244 } /* end of Setup_Modem_Echo */ 2245 2246 2247 /*********************************************************************************************** 2248 * NMC::Remove_Modem_Echo -- Set the echo function callback pointer to null * 2249 * * 2250 * * 2251 * * 2252 * INPUT: Nothing * 2253 * * 2254 * OUTPUT: Nothing * 2255 * * 2256 * WARNINGS: None * 2257 * * 2258 * HISTORY: * 2259 * 8/2/96 12:50PM ST : Documented / Win32 support added * 2260 *=============================================================================================*/ 2261 void NullModemClass::Remove_Modem_Echo( void ) 2262 { 2263 // Smart_Printf( "Remove Echo modem code\n" ); 2264 HMSetUpEchoRoutine( NULL ); 2265 2266 } /* end of Remove_Modem_Echo */ 2267 2268 2269 2270 /*********************************************************************************************** 2271 * NMC::Print_EchoBuf -- Print out the contents of the echo buffer * 2272 * * 2273 * * 2274 * * 2275 * INPUT: Nothing * 2276 * * 2277 * OUTPUT: Nothing * 2278 * * 2279 * WARNINGS: None * 2280 * * 2281 * HISTORY: * 2282 * 8/2/96 12:51PM ST : Documented * 2283 *=============================================================================================*/ 2284 void NullModemClass::Print_EchoBuf( void ) 2285 { 2286 for (int i = 0; i < strlen(NullModem.EchoBuf); i++) { 2287 if (NullModem.EchoBuf[i] == '\r') { 2288 NullModem.EchoBuf[i] = 1; 2289 } else { 2290 if (NullModem.EchoBuf[i] == '\n') { 2291 NullModem.EchoBuf[i] = 2; 2292 } 2293 } 2294 } 2295 // Smart_Printf( "Echo buffer length %d (%s)\n", NullModem.EchoCount, NullModem.EchoBuf ); 2296 } 2297 2298 2299 2300 /*********************************************************************************************** 2301 * NMC::Reset_EchoBuf -- Empties the echo buffer * 2302 * * 2303 * * 2304 * * 2305 * INPUT: Nothing * 2306 * * 2307 * OUTPUT: Nothing * 2308 * * 2309 * WARNINGS: None * 2310 * * 2311 * HISTORY: * 2312 * 8/2/96 12:51PM ST : Documented * 2313 *=============================================================================================*/ 2314 void NullModemClass::Reset_EchoBuf( void ) 2315 { 2316 *EchoBuf = 0; 2317 EchoCount = 0; 2318 } 2319 2320 2321 /*********************************************************************************************** 2322 * NMC::Abort_Modem -- Checks for user input so that modem operations can be aborted * 2323 * * 2324 * * 2325 * * 2326 * INPUT: Nothing * 2327 * * 2328 * OUTPUT: ASUSERABORT if abort key pressed. ASSUCESS otherwise. * 2329 * * 2330 * WARNINGS: None * 2331 * * 2332 * HISTORY: * 2333 * 8/2/96 12:52PM ST : Documented * 2334 *=============================================================================================*/ 2335 int NullModemClass::Abort_Modem( PORT * ) 2336 { 2337 /* 2338 ** Button Enumerations 2339 */ 2340 enum { 2341 BUTTON_CANCEL = 100, 2342 }; 2343 2344 /* 2345 ** Invoke game callback 2346 */ 2347 Call_Back(); 2348 2349 /* 2350 ** Get user input 2351 */ 2352 Input = Commands->Input(); 2353 2354 switch ( Input ) { 2355 case (KN_ESC): 2356 case (BUTTON_CANCEL | KN_BUTTON): 2357 return( ASUSERABORT ); 2358 } 2359 2360 return( ASSUCCESS ); 2361 2362 } /* end of Abort_Modem */ 2363 2364 2365 /*********************************************************************************************** 2366 * NMC::Setup_Abort_Modem -- sets the modem abort function pointer * 2367 * * 2368 * * 2369 * * 2370 * INPUT: Nothing * 2371 * * 2372 * OUTPUT: Nothing * 2373 * * 2374 * WARNINGS: None * 2375 * * 2376 * HISTORY: * 2377 * 8/2/96 2:59PM ST : Documented / Win32 support added * 2378 *=============================================================================================*/ 2379 void NullModemClass::Setup_Abort_Modem( void ) 2380 { 2381 2382 #ifdef WIN32 2383 2384 SerialPort->Set_Abort_Function((int(*)(void))Abort_Modem); 2385 2386 #else //WIN32 2387 /* 2388 ** save off original abort modem function to later restore 2389 */ 2390 OrigAbortModemFunc = _AbortModemFunctionPtr; 2391 HMSetUpAbortKey( ESC ); 2392 SetAbortModemFunctionPtr( Abort_Modem ); 2393 #endif //WIN32 2394 2395 } /* end of Setup_Abort_Modem */ 2396 2397 2398 /*********************************************************************************************** 2399 * NMC::Remove_Abort_Modem -- Removes the modem abort function pointer * 2400 * * 2401 * * 2402 * * 2403 * INPUT: Nothing * 2404 * * 2405 * OUTPUT: Nothing * 2406 * * 2407 * WARNINGS: None * 2408 * * 2409 * HISTORY: * 2410 * 8/2/96 3:01PM ST : Documented / Win32 support added * 2411 *=============================================================================================*/ 2412 void NullModemClass::Remove_Abort_Modem( void ) 2413 { 2414 2415 #ifdef WIN32 2416 SerialPort->Set_Abort_Function(NULL); 2417 2418 #else //WIN32 2419 2420 HMSetUpAbortKey( NOKEY ); 2421 2422 /* 2423 ** Restore the original abort modem function 2424 */ 2425 _AbortModemFunctionPtr = OrigAbortModemFunc; 2426 #endif //WIN32 2427 2428 } /* end of Remove_Abort_Modem */ 2429 2430 2431 2432 /*********************************************************************************************** 2433 * NMC::Change_IRQ_Priority -- Increases the priority of the serial interrupt * 2434 * * 2435 * * 2436 * * 2437 * INPUT: Interrupt request number * 2438 * * 2439 * OUTPUT: ASSUCCESS if changed * 2440 * * 2441 * WARNINGS: The Win32 version of this function does nothing. * 2442 * Priorities are controlled by windoze * 2443 * * 2444 * HISTORY: * 2445 * 8/2/96 3:03PM ST : Documented / Win32 support added * 2446 *=============================================================================================*/ 2447 int NullModemClass::Change_IRQ_Priority( int irq ) 2448 { 2449 #ifdef WIN32 2450 2451 irq = irq; 2452 return ( ASSUCCESS ); 2453 2454 #else //WIN32 2455 2456 if (irq != OldIRQPri) { 2457 OldIRQPri = irq; 2458 return( Change8259Priority( irq ) ); 2459 } else { 2460 return( ASSUCCESS ); 2461 } 2462 2463 #endif //WIN32 2464 2465 } /* end of Change_IRQ_Priority */ 2466 2467 2468 2469 /*********************************************************************************************** 2470 * NMC::Get_Modem_Status -- returns status of modem control bits * 2471 * * 2472 * * 2473 * * 2474 * INPUT: Nothing * 2475 * * 2476 * OUTPUT: Modem status * 2477 * * 2478 * WARNINGS: None * 2479 * * 2480 * HISTORY: * 2481 * 8/2/96 3:06PM ST : Documented / Win32 support added * 2482 *=============================================================================================*/ 2483 int NullModemClass::Get_Modem_Status( void ) 2484 { 2485 int modemstatus; 2486 int status; 2487 char buffer[81]; 2488 2489 #ifdef WIN32 2490 modemstatus = SerialPort->Get_Modem_Status(); 2491 #else //WIN32 2492 modemstatus = GetModemStatus( Port ); 2493 #endif //WIN32 2494 2495 status = Send_Modem_Command( "AT", '\r', buffer, 81, DEFAULT_TIMEOUT, 1 ); 2496 2497 if (status == MODEM_CMD_OK) { 2498 modemstatus &= (~CD_SET); 2499 } 2500 2501 return( modemstatus ); 2502 2503 } /* end of Get_Modem_Status */ 2504 2505 2506 /*********************************************************************************************** 2507 * NMC::Send_Modem_Command -- Sends an 'AT' command to the modem and gets the response * 2508 * * 2509 * * 2510 * * 2511 * INPUT: command to send to modem. e.g. 'ATZ' * 2512 * terminator byte for command string * 2513 * buffer to put modem response into * 2514 * length of above buffer * 2515 * delay to wait for response * 2516 * number of times to retry when modem doesnt respond * 2517 * * 2518 * OUTPUT: input delay less the time it took the modem to respond * 2519 * * 2520 * WARNINGS: None * 2521 * * 2522 * HISTORY: * 2523 * 8/2/96 3:09PM ST : Documented / Win32 support added * 2524 *=============================================================================================*/ 2525 int NullModemClass::Send_Modem_Command( char *command, char terminator, char *buffer, int buflen, int delay, int retries ) 2526 { 2527 2528 #ifdef WIN32 2529 return (SerialPort->Send_Command_To_Modem(command, terminator, buffer, buflen, delay, retries)); 2530 #else //WIN32 2531 2532 int status, tmpdelay, retry; 2533 char tempbuf[81]; 2534 2535 2536 *buffer = 0; 2537 2538 for ( retry = 0; retry < retries; retry++ ) { 2539 2540 PortKillTime( Port, 100 ); 2541 2542 status = HMSendStringNoWait( Port, command, terminator ); 2543 2544 2545 if (status < ASSUCCESS) { 2546 return( status ); 2547 } 2548 2549 tmpdelay = delay; 2550 while ( tmpdelay > 0 ) { 2551 2552 tmpdelay = HMInputLine( Port, tmpdelay, tempbuf, 81 ); 2553 2554 if ( strcmp( tempbuf, "OK" ) == 0 ) { 2555 return( MODEM_CMD_OK ); 2556 } else if ( strcmp( tempbuf, "0" ) == 0 ) { 2557 return( MODEM_CMD_0 ); 2558 } else if ( strcmp( tempbuf, "ERROR" ) == 0 ) { 2559 return( MODEM_CMD_ERROR ); 2560 } else if ( tempbuf[0] != 0 ) { 2561 strncpy( buffer, tempbuf, buflen ); 2562 } 2563 } 2564 2565 PortKillTime( Port, 100 ); 2566 2567 /* 2568 ** Send and extra return to help clear out any problems with the modem (if any). 2569 */ 2570 HMWaitForOK( 300, NULL ); 2571 status = HMSendString( Port, "" ); 2572 HMWaitForOK( 0, NULL ); 2573 } 2574 2575 return( tmpdelay ); 2576 2577 #endif //WIN32 2578 } 2579 2580 2581 /*********************************************************************************************** 2582 * NMC::Verify_And_Convert_To_Int -- converts a text string of numbers to an int * 2583 * * 2584 * * 2585 * * 2586 * INPUT: ptr to buffer * 2587 * * 2588 * OUTPUT: value of text number in buffer * 2589 * * 2590 * WARNINGS: None * 2591 * * 2592 * HISTORY: * 2593 * 8/2/96 3:13PM ST : Documented * 2594 *=============================================================================================*/ 2595 int NullModemClass::Verify_And_Convert_To_Int( char *buffer ) 2596 { 2597 int value = 0; 2598 int len = strlen(buffer); 2599 2600 2601 for (int i = 0; i < len; i++) { 2602 if ( !isdigit( *(buffer + i) ) ) { 2603 value = -1; 2604 break; 2605 } 2606 } 2607 2608 if (value == 0) { 2609 value = atoi( buffer ); 2610 } 2611 2612 return( value ); 2613 2614 } /* end of Verify_And_Convert_To_Int */ 2615 2616 /*************************** end of nullmgr.cpp ****************************/ 2617 2618 #endif