|
|
1.1 ! root 1: /* RIOLIB.C */ ! 2: ! 3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */ ! 4: ! 5: /* Remote communications Input/Output Library for OS/2 and Win32 */ ! 6: ! 7: #define RIOLIB_VER 100 ! 8: ! 9: #ifdef __OS2__ ! 10: #define INCL_DOSDEVICES ! 11: #define INCL_DOSDEVIOCTL ! 12: #define INCL_DOS ! 13: #include <os2.h> ! 14: ! 15: #else // Win32 ! 16: ! 17: #include <windows.h> ! 18: #endif ! 19: ! 20: #include <time.h> ! 21: #include <stdio.h> ! 22: #include <fcntl.h> ! 23: #include <string.h> ! 24: #include <process.h> ! 25: #include "riolib.h" ! 26: #include "riodefs.h" ! 27: ! 28: int rio_handle=-1; ! 29: ! 30: int rio_abort=0,rio_aborted=0; ! 31: int inbufbot,inbuftop; ! 32: int outbufbot,outbuftop; ! 33: char inbuf[RIO_INCOM_BUFLEN]; ! 34: char outbuf[RIO_OUTCOM_BUFLEN]; ! 35: ! 36: /****************************************************************************/ ! 37: /* OS/2 Specific */ ! 38: /****************************************************************************/ ! 39: ! 40: #ifdef __OS2__ ! 41: ! 42: HEV rio_sem; ! 43: ! 44: typedef struct { /* Packet for Get/Set Device Control Block Parms */ ! 45: ! 46: ushort wr_timeout; ! 47: ushort rd_timeout; ! 48: uchar flags1; ! 49: uchar flags2; ! 50: uchar flags3; ! 51: uchar err_char; ! 52: uchar brk_char; ! 53: uchar xon_char; ! 54: uchar xoff_char; ! 55: ! 56: } async_dcb_t; ! 57: ! 58: typedef struct { /* Parameter Packet for Extended Set Bit Rate */ ! 59: ! 60: ulong rate; ! 61: uchar frac; ! 62: ! 63: } setrate_t; ! 64: ! 65: typedef struct { /* Data Packet for Extended Query Bit Rate */ ! 66: ! 67: ulong cur_rate; ! 68: uchar cur_rate_frac; ! 69: ulong min_rate; ! 70: uchar min_rate_frac; ! 71: ulong max_rate; ! 72: uchar max_rate_frac; ! 73: ! 74: } getrate_t; ! 75: ! 76: typedef struct { /* Data Packet for Query Number of Chars Queue */ ! 77: ! 78: ushort cur, ! 79: max; ! 80: ! 81: } getqueue_t; ! 82: ! 83: typedef struct { /* Parameter Packet for Set Modem Control Signals */ ! 84: ! 85: uchar on; ! 86: uchar off; ! 87: ! 88: } setmdmctrl_t; ! 89: ! 90: typedef struct { /* Parameter Packet for Set Line Characteristics */ ! 91: ! 92: uchar data; ! 93: uchar parity; ! 94: uchar stop; ! 95: ! 96: } setline_t; ! 97: ! 98: #else ! 99: ! 100: /****************************************************************************/ ! 101: /* Win32 Specific */ ! 102: /****************************************************************************/ ! 103: ! 104: HANDLE rio_event; ! 105: ! 106: #endif ! 107: ! 108: /************************************************************************/ ! 109: /* Opens COM port, ignoring IRQ argument */ ! 110: /* Returns 0 on no error */ ! 111: /************************************************************************/ ! 112: int rioini(int com, int unused) ! 113: { ! 114: char str[64]; ! 115: #ifdef __OS2__ ! 116: async_dcb_t async_dcb; ! 117: #else // Win32 ! 118: DCB dcb; ! 119: COMMTIMEOUTS timeouts; ! 120: #endif ! 121: ! 122: #ifdef __WATOMC__ ! 123: char *stack; ! 124: #endif ! 125: ! 126: inbufbot=inbuftop=outbufbot=outbuftop=0; /* clear our i/o buffers */ ! 127: ! 128: if(!com) { /* Close port */ ! 129: if(rio_handle>=0) { ! 130: #ifdef __OS2__ ! 131: close(rio_handle); ! 132: rio_handle=-1; /* signal outcom_thread() to end */ ! 133: DosPostEventSem(rio_sem); ! 134: #else // Win32 ! 135: CloseHandle((HANDLE)rio_handle); ! 136: rio_handle=-1; ! 137: SetEvent(rio_event); ! 138: #endif ! 139: return(0); } ! 140: return(-2); } ! 141: ! 142: sprintf(str,"COM%u",com); ! 143: #ifdef __OS2__ ! 144: if(rio_handle==-1) { /* Not already opened */ ! 145: if((rio_handle=open(str,O_RDWR|O_BINARY,0))==-1) ! 146: return(-1); } ! 147: #else // Win32 ! 148: if(rio_handle==-1) { /* Not already opened */ ! 149: if((rio_handle=(int)CreateFile(str ! 150: ,GENERIC_READ|GENERIC_WRITE /* Access */ ! 151: ,0 /* Share mode */ ! 152: ,NULL /* Security attributes */ ! 153: ,OPEN_EXISTING /* Create access */ ! 154: ,FILE_ATTRIBUTE_NORMAL /* File attributes */ ! 155: ,NULL /* Template */ ! 156: ))==(int)INVALID_HANDLE_VALUE) ! 157: return(-1); } ! 158: #endif ! 159: ! 160: #ifdef __OS2__ ! 161: ! 162: if(DosDevIOCtl(rio_handle ! 163: ,IOCTL_ASYNC, 0x73 /* Query Device Control Block (DCB) Parms */ ! 164: ,NULL ! 165: ,0 ! 166: ,NULL ! 167: ,&async_dcb ! 168: ,sizeof(async_dcb) ! 169: ,NULL)) ! 170: return(-6); ! 171: ! 172: async_dcb.flags2&=~(1<<1); /* Disable Automatic Recv XON/XOFF flow ctrl */ ! 173: /* Extended Hardware Buffering (16550 FIFO) */ ! 174: if(async_dcb.flags3&((1<<4)|(1<<3))) { /* Supported */ ! 175: async_dcb.flags3&=~((1<<3)|(1<<6)|(1<<5)); /* Set to 1 char trgr lvl */ ! 176: async_dcb.flags3|=((1<<4)|(1<<7)); } /* Set to 16 char tx buf */ ! 177: async_dcb.flags3|=((1<<2)|(1<<1)); /* No-Wait read timeout */ ! 178: async_dcb.flags3&=~(1<<0); /* Normal write timeout */ ! 179: async_dcb.wr_timeout=499; /* 5 seconds? */ ! 180: DosDevIOCtl(rio_handle ! 181: ,IOCTL_ASYNC, 0x53 /* Set Device Control Block (DCB) Parms */ ! 182: ,(void *)&async_dcb ! 183: ,sizeof(async_dcb) ! 184: ,NULL ! 185: ,NULL ! 186: ,0 ! 187: ,NULL); ! 188: ! 189: if(DosCreateEventSem(NULL,&rio_sem,0,0)) ! 190: return(-5); ! 191: ! 192: #else // Win32 ! 193: ! 194: if(GetCommState((HANDLE)rio_handle,&dcb)!=TRUE) ! 195: return(-6); ! 196: ! 197: dcb.fBinary=1; // No EOF check ! 198: dcb.fDtrControl=DTR_CONTROL_ENABLE; ! 199: dcb.fDsrSensitivity=FALSE; ! 200: dcb.fOutX=0; // No Xon/Xoff out ! 201: dcb.fInX=0; // No Xon/Xoff in ! 202: dcb.fErrorChar=FALSE; // No character replacement ! 203: dcb.fNull=0; // No null stripping ! 204: dcb.fAbortOnError=0; // Continue to communicate even if error detected ! 205: ! 206: SetCommState((HANDLE)rio_handle,&dcb); ! 207: ! 208: if(GetCommTimeouts((HANDLE)rio_handle,&timeouts)!=TRUE) ! 209: return(-7); ! 210: ! 211: timeouts.ReadIntervalTimeout=MAXDWORD; ! 212: timeouts.ReadTotalTimeoutMultiplier=0; ! 213: timeouts.ReadTotalTimeoutConstant=0; // No-wait read timeout ! 214: timeouts.WriteTotalTimeoutMultiplier=0; ! 215: timeouts.WriteTotalTimeoutConstant=5000; // 5 seconds ! 216: SetCommTimeouts((HANDLE)rio_handle,&timeouts); ! 217: ! 218: SetupComm((HANDLE)rio_handle,4096,4096); /* Init Rx and Tx buffer sizes */ ! 219: ! 220: if((rio_event=CreateEvent(NULL /* Security attributes */ ! 221: ,TRUE /* Manual reset */ ! 222: ,FALSE /* Non-signaled by default */ ! 223: ,NULL /* Event name */ ! 224: ))==NULL) ! 225: return(-5); ! 226: ! 227: #endif ! 228: ! 229: #ifdef __WATCOMC__ ! 230: stack=malloc(RIO_OUTCOM_STACK); ! 231: if(stack==NULL) ! 232: return(-4); ! 233: if(_beginthread(outcom_thread,stack,RIO_OUTCOM_STKLEN,NULL)==-1) ! 234: return(-3); ! 235: #else ! 236: if(_beginthread(outcom_thread,RIO_OUTCOM_STKLEN,NULL)==(ulong)-1) ! 237: return(-3); ! 238: #endif ! 239: ! 240: ! 241: return(0); ! 242: } ! 243: ! 244: /************************************************************************/ ! 245: /* Raise or lower DTR */ ! 246: /* If onoff is 0, drop and exit, 1 raise and exit, >1 drop and wait */ ! 247: /* up to x seconds for DCD to drop, return 0 on success, 1 on failure */ ! 248: /************************************************************************/ ! 249: int dtr(char onoff) ! 250: { ! 251: #ifdef __OS2__ ! 252: setmdmctrl_t setmdmctrl; ! 253: ulong start; ! 254: ushort w; ! 255: uchar c; ! 256: ! 257: if(onoff==1) { ! 258: setmdmctrl.on=1; ! 259: setmdmctrl.off=0xff; } ! 260: else { ! 261: setmdmctrl.on=0; ! 262: setmdmctrl.off=0xfe; } ! 263: ! 264: DosDevIOCtl(rio_handle, IOCTL_ASYNC, 0x46 /* Set Modem Ctrl Signals */ ! 265: ,&setmdmctrl ! 266: ,sizeof(setmdmctrl) ! 267: ,NULL ! 268: ,&w ! 269: ,sizeof(short) ! 270: ,NULL); ! 271: ! 272: if(onoff<=1) ! 273: return(0); ! 274: ! 275: start=time(NULL); ! 276: while(time(NULL)-start<=onoff) { ! 277: DosDevIOCtl(rio_handle ! 278: ,IOCTL_ASYNC, 0x67 /* Get Modem Input Signals */ ! 279: ,NULL ! 280: ,0 ! 281: ,NULL ! 282: ,&c ! 283: ,1 ! 284: ,NULL); ! 285: if(!(c&DCD)) /* DCD is low */ ! 286: return(0); ! 287: DosSleep(1); } ! 288: ! 289: #else // Win32 ! 290: ! 291: ulong l,start; ! 292: ! 293: if(onoff==1) ! 294: EscapeCommFunction((HANDLE)rio_handle,SETDTR); ! 295: else ! 296: EscapeCommFunction((HANDLE)rio_handle,CLRDTR); ! 297: ! 298: if(onoff<=1) ! 299: return(0); ! 300: ! 301: start=time(NULL); ! 302: while(time(NULL)-start<=onoff) { ! 303: GetCommModemStatus((HANDLE)rio_handle,&l); ! 304: if(!(l&MS_RLSD_ON)) // DCD is low ! 305: return(0); ! 306: Sleep(1000); } ! 307: ! 308: #endif ! 309: ! 310: return(1); /* Dropping DTR failed to lower DCD */ ! 311: } ! 312: ! 313: ! 314: ! 315: /************************************************************************/ ! 316: /* Returns the current DTE rate of the currently open COM port */ ! 317: /************************************************************************/ ! 318: long rio_getbaud(void) ! 319: { ! 320: #ifdef __OS2__ ! 321: getrate_t getrate; ! 322: ! 323: if(DosDevIOCtl(rio_handle, IOCTL_ASYNC, 0x63 /* Extended Query Bit Rate */ ! 324: ,NULL ! 325: ,0 ! 326: ,NULL ! 327: ,&getrate ! 328: ,sizeof(getrate) ! 329: ,NULL)==0) ! 330: return(getrate.cur_rate); ! 331: ! 332: #else // Win32 ! 333: ! 334: DCB dcb; ! 335: ! 336: if(GetCommState((HANDLE)rio_handle,&dcb)==TRUE) { ! 337: switch(dcb.BaudRate) { ! 338: case CBR_110: ! 339: return(110); ! 340: case CBR_300: ! 341: return(300); ! 342: case CBR_600: ! 343: return(600); ! 344: case CBR_1200: ! 345: return(1200); ! 346: case CBR_2400: ! 347: return(2400); ! 348: case CBR_4800: ! 349: return(4800); ! 350: case CBR_9600: ! 351: return(9600); ! 352: case CBR_14400: ! 353: return(14400); ! 354: case CBR_19200: ! 355: return(19200); ! 356: case CBR_38400: ! 357: return(38400); ! 358: case CBR_56000: ! 359: return(56000); ! 360: case CBR_57600: ! 361: return(57600); ! 362: case CBR_115200: ! 363: return(115200); ! 364: case CBR_128000: ! 365: return(128000); ! 366: case CBR_256000: ! 367: return(256000); ! 368: default: ! 369: return(dcb.BaudRate); } } ! 370: ! 371: #endif ! 372: ! 373: return(-1); // Error ! 374: } ! 375: ! 376: ! 377: /************************************************************************/ ! 378: /* Sets the current DTE rate */ ! 379: /* Returns 0 on success */ ! 380: /************************************************************************/ ! 381: int setbaud(int rate) ! 382: { ! 383: #ifdef __OS2__ ! 384: setrate_t setrate; ! 385: APIRET ret; ! 386: ! 387: setrate.rate=rate; ! 388: setrate.frac=0; ! 389: ! 390: ret=DosDevIOCtl(rio_handle, IOCTL_ASYNC, 0x43 /* Extended Set Bit Rate */ ! 391: ,&setrate ! 392: ,sizeof(setrate) ! 393: ,NULL ! 394: ,NULL ! 395: ,0 ! 396: ,NULL); ! 397: ! 398: if(ret) ! 399: return(ret); ! 400: ! 401: if(rio_getbaud()!=rate) /* Make sure it actually changed rates */ ! 402: return(-1); ! 403: ! 404: #else // Win32 ! 405: ! 406: DCB dcb; ! 407: ! 408: if(GetCommState((HANDLE)rio_handle,&dcb)!=TRUE) ! 409: return(-1); ! 410: dcb.BaudRate=rate; ! 411: if(SetCommState((HANDLE)rio_handle,&dcb)!=TRUE) ! 412: return(-1); ! 413: ! 414: #endif ! 415: ! 416: return(0); ! 417: } ! 418: ! 419: /************************************************************************/ ! 420: /* Return next incoming character from COM port, NOINP if none avail. */ ! 421: /* Uses a linear buffer. */ ! 422: /************************************************************************/ ! 423: int incom(void) ! 424: { ! 425: char c; ! 426: ! 427: if(inbufbot!=inbuftop) { ! 428: c=inbuf[inbufbot]; ! 429: inbufbot++; ! 430: if(inbufbot==inbuftop) ! 431: inbufbot=inbuftop=0; ! 432: if(rio_abort && c==3) { /* Ctrl-C */ ! 433: rio_aborted=1; ! 434: rioctl(IOFO); ! 435: return(NOINP); } ! 436: return(c); } ! 437: ! 438: inbufbot=0; ! 439: #ifdef __OS2__ ! 440: inbuftop=read(rio_handle,inbuf,RIO_INCOM_BUFLEN); ! 441: #else // Win32 ! 442: ReadFile((HANDLE)rio_handle,inbuf,RIO_INCOM_BUFLEN,(DWORD *)&inbuftop,NULL); ! 443: #endif ! 444: if(inbuftop<=0 || inbuftop>RIO_INCOM_BUFLEN) { ! 445: inbuftop=0; ! 446: return(NOINP); } ! 447: else ! 448: return(inbuf[inbufbot++]); ! 449: } ! 450: ! 451: /************************************************************************/ ! 452: /* Return number of chars in our input buffer */ ! 453: /************************************************************************/ ! 454: int inbufcnt(void) ! 455: { ! 456: return(inbuftop-inbufbot); ! 457: } ! 458: ! 459: /************************************************************************/ ! 460: /* Place a character into outbound buffer, return TXBOF on buffer */ ! 461: /* overflow, 0 on success. */ ! 462: /************************************************************************/ ! 463: int outcom(int ch) ! 464: { ! 465: int i=outbuftop+1; ! 466: ! 467: if(i==RIO_OUTCOM_BUFLEN) ! 468: i=0; ! 469: if(i==outbufbot) ! 470: return(TXBOF); ! 471: outbuf[outbuftop++]=ch; ! 472: if(outbuftop==RIO_OUTCOM_BUFLEN) ! 473: outbuftop=0; ! 474: #ifdef __OS2__ ! 475: DosPostEventSem(rio_sem); // Enable output ! 476: #else // Win32 ! 477: SetEvent(rio_event); ! 478: #endif ! 479: return(0); ! 480: } ! 481: ! 482: /************************************************************************/ ! 483: /************************************************************************/ ! 484: void outcom_thread(void *unused) ! 485: { ! 486: int i,top; ! 487: ulong l; ! 488: ! 489: while(rio_handle>=0) { ! 490: if(outbufbot==outbuftop) { ! 491: #ifdef __OS2__ ! 492: DosResetEventSem(rio_sem,&l); ! 493: DosWaitEventSem(rio_sem,10000); /* every 10 seconds */ ! 494: #else // Win32 ! 495: ResetEvent(rio_event); ! 496: WaitForSingleObject(rio_event,10000); ! 497: #endif ! 498: continue; } ! 499: top=outbuftop; ! 500: if(top<outbufbot) ! 501: i=RIO_OUTCOM_BUFLEN-outbufbot; ! 502: else ! 503: i=top-outbufbot; ! 504: #ifdef __OS2__ ! 505: i=write(rio_handle,outbuf+outbufbot,i); ! 506: #else // Win32 ! 507: WriteFile((HANDLE)rio_handle,outbuf+outbufbot,i,(DWORD *)&i,NULL); ! 508: #endif ! 509: if(i>0 && i<=RIO_OUTCOM_BUFLEN-outbufbot) ! 510: outbufbot+=i; ! 511: if(outbufbot==RIO_OUTCOM_BUFLEN) ! 512: outbufbot=0; } ! 513: _endthread(); ! 514: } ! 515: ! 516: /************************************************************************/ ! 517: /* Return number of chars in our output buffer */ ! 518: /************************************************************************/ ! 519: int outbufcnt(void) ! 520: { ! 521: if(outbuftop>=outbufbot) ! 522: return(outbuftop-outbufbot); ! 523: return(outbuftop+(RIO_OUTCOM_BUFLEN-outbufbot)); ! 524: } ! 525: ! 526: /************************************************************************/ ! 527: /************************************************************************/ ! 528: int rio_getstate(void) ! 529: { ! 530: #ifdef __OS2__ ! 531: uchar c; ! 532: ushort state=0,w; ! 533: getqueue_t getqueue; ! 534: ! 535: if(rio_abort && !rio_aborted) { ! 536: DosDevIOCtl(rio_handle ! 537: ,IOCTL_ASYNC, 0x68 /* Query # of chars in rx queue */ ! 538: ,NULL ! 539: ,0 ! 540: ,NULL ! 541: ,&getqueue ! 542: ,sizeof(getqueue) ! 543: ,NULL); ! 544: if(getqueue.cur && read(rio_handle,&c,1)==1) { ! 545: if(c==3) { /* ctrl-c */ ! 546: rio_aborted=1; ! 547: rioctl(IOFO); } ! 548: else ! 549: if(inbuftop<RIO_INCOM_BUFLEN) /* don't overflow input buffer */ ! 550: inbuf[inbuftop++]=c; } } ! 551: ! 552: if(rio_aborted) ! 553: state|=ABORT; ! 554: ! 555: #if 0 // just to see if things speed up ! 556: DosDevIOCtl(rio_handle ! 557: ,IOCTL_ASYNC, 0x6D /* Query COM Error */ ! 558: ,NULL ! 559: ,0 ! 560: ,NULL ! 561: ,&w ! 562: ,sizeof(short) ! 563: ,NULL); ! 564: state|=w&0xf; /* FERR|PERR|OVRR|RXLOST */ ! 565: #endif ! 566: ! 567: DosDevIOCtl(rio_handle ! 568: ,IOCTL_ASYNC, 0x67 /* Query Modem Input Signals */ ! 569: ,NULL ! 570: ,0 ! 571: ,NULL ! 572: ,&c ! 573: ,sizeof(char) ! 574: ,NULL); ! 575: state|=c&0xf0; /* DCD|RI|DSR|CTS */ ! 576: ! 577: #else // Win32 ! 578: ! 579: uchar c; ! 580: ushort state=0; ! 581: int i; ! 582: ulong l; ! 583: COMSTAT comstat; ! 584: ! 585: if(rio_abort && !rio_aborted) { ! 586: ClearCommError((HANDLE)rio_handle,&l,&comstat); ! 587: if(comstat.cbInQue) { ! 588: ReadFile((HANDLE)rio_handle,&c,1,(DWORD *)&i,NULL); ! 589: if(i==1) { ! 590: if(c==3) { /* Ctrl-C */ ! 591: rio_aborted=1; ! 592: rioctl(IOFO); } ! 593: else ! 594: if(inbuftop<RIO_INCOM_BUFLEN) /* don't overflow input buffer */ ! 595: inbuf[inbuftop++]=c; } } } ! 596: ! 597: GetCommModemStatus((HANDLE)rio_handle,(DWORD *)&state); /* DCD|RI|DSR|CTS */ ! 598: if(rio_aborted) ! 599: state|=ABORT; ! 600: ! 601: #endif ! 602: ! 603: return(state); ! 604: } ! 605: ! 606: ! 607: /************************************************************************/ ! 608: /************************************************************************/ ! 609: int rioctl(ushort action) ! 610: { ! 611: #ifdef __OS2__ ! 612: async_dcb_t async_dcb; ! 613: getqueue_t getqueue; ! 614: setline_t setline; ! 615: #else // Win32 ! 616: COMMPROP commprop; ! 617: COMSTAT comstat; ! 618: DCB dcb; ! 619: ulong l; ! 620: #endif ! 621: uchar c; ! 622: ushort mode,w; ! 623: clock_t start; ! 624: ! 625: switch(action) { ! 626: case GVERS: /* Get version */ ! 627: return(RIOLIB_VER); ! 628: case GUART: /* Get UART I/O address, not available */ ! 629: return(0xffff); ! 630: case GIRQN: /* Get IRQ number, not available */ ! 631: return((int)rio_handle); ! 632: case GBAUD: /* Get current bit rate */ ! 633: return(rio_getbaud()); ! 634: case RXBC: /* Get receive buffer count */ ! 635: #ifndef __OS2__ // Win32 ! 636: ClearCommError((HANDLE)rio_handle,&l,&comstat); ! 637: return(comstat.cbInQue+inbufcnt()); ! 638: #endif ! 639: /* Fall-through if OS/2 */ ! 640: case RXBS: /* Get receive buffer size */ ! 641: #ifdef __OS2__ ! 642: DosDevIOCtl(rio_handle ! 643: ,IOCTL_ASYNC, 0x68 /* Query # of chars in rx queue */ ! 644: ,NULL ! 645: ,0 ! 646: ,NULL ! 647: ,&getqueue ! 648: ,sizeof(getqueue) ! 649: ,NULL); ! 650: if(action==RXBC) ! 651: return(getqueue.cur+inbufcnt()); ! 652: /* RXBS */ ! 653: return(getqueue.max+RIO_INCOM_BUFLEN); ! 654: #else ! 655: GetCommProperties((HANDLE)rio_handle,&commprop); ! 656: return(commprop.dwCurrentRxQueue+RIO_INCOM_BUFLEN); ! 657: #endif ! 658: case TXBC: /* Get transmit buffer count */ ! 659: #ifndef __OS2__ // Win32 ! 660: ClearCommError((HANDLE)rio_handle,&l,&comstat); ! 661: return(comstat.cbOutQue+outbufcnt()); ! 662: #endif ! 663: /* Fall-through if OS/2 */ ! 664: case TXBS: /* Get transmit buffer size */ ! 665: case TXBF: /* Get transmit buffer free space */ ! 666: #ifdef __OS2__ ! 667: DosDevIOCtl(rio_handle ! 668: ,IOCTL_ASYNC, 0x69 /* Query # of chars in tx queue */ ! 669: ,NULL ! 670: ,0 ! 671: ,NULL ! 672: ,&getqueue ! 673: ,sizeof(getqueue) ! 674: ,NULL); ! 675: if(action==TXBC) ! 676: return(getqueue.cur+outbufcnt()); ! 677: else if(action==TXBS) ! 678: return(getqueue.max+RIO_OUTCOM_BUFLEN); ! 679: /* TXBF */ ! 680: return((getqueue.max-getqueue.cur)+(RIO_OUTCOM_BUFLEN-outbufcnt())); ! 681: #else ! 682: GetCommProperties((HANDLE)rio_handle,&commprop); ! 683: if(action==TXBS) ! 684: return(commprop.dwCurrentTxQueue+RIO_OUTCOM_BUFLEN); ! 685: /* TXBF */ ! 686: ClearCommError((HANDLE)rio_handle,&l,&comstat); ! 687: return((commprop.dwCurrentTxQueue-comstat.cbOutQue) ! 688: +(RIO_OUTCOM_BUFLEN-outbufcnt())); ! 689: #endif ! 690: case IOSTATE: ! 691: return(rio_getstate()); ! 692: case IOFI: /* Flush input buffer */ ! 693: case IOFO: /* Flush output buffer */ ! 694: case IOFB: /* Flush both buffers */ ! 695: #ifdef __OS2__ ! 696: c=0; ! 697: if((action&IOFI)==IOFI) { ! 698: DosDevIOCtl(rio_handle ! 699: ,IOCTL_GENERAL, DEV_FLUSHINPUT ! 700: ,&c ! 701: ,sizeof(char) ! 702: ,NULL ! 703: ,&w ! 704: ,sizeof(short) ! 705: ,NULL); ! 706: inbufbot=inbuftop=0; ! 707: } /* Clear our input buffer too */ ! 708: c=0; ! 709: if((action&IOFO)==IOFO) { ! 710: DosDevIOCtl(rio_handle ! 711: ,IOCTL_GENERAL, DEV_FLUSHOUTPUT ! 712: ,&c ! 713: ,sizeof(char) ! 714: ,NULL ! 715: ,&w ! 716: ,sizeof(short) ! 717: ,NULL); ! 718: outbufbot=outbuftop=0; ! 719: } /* Clear our output buffer too */ ! 720: #else // Win32 ! 721: l=0; ! 722: if((action&IOFI)==IOFI) ! 723: l|=(PURGE_RXABORT|PURGE_RXCLEAR); ! 724: if((action&IOFO)==IOFO) ! 725: l|=(PURGE_TXABORT|PURGE_TXCLEAR); ! 726: PurgeComm((HANDLE)rio_handle,l); ! 727: #endif ! 728: return(rio_getstate()); ! 729: case LFN81: ! 730: case LFE71: ! 731: #ifdef __OS2__ ! 732: setline.stop=0; /* 1 stop bit */ ! 733: if(action==LFN81) { ! 734: setline.data=8; ! 735: setline.parity=0; } /* No parity */ ! 736: else { ! 737: setline.data=7; ! 738: setline.parity=2; } /* Even parity */ ! 739: DosDevIOCtl(rio_handle ! 740: ,IOCTL_ASYNC, 0x42 /* Set Line Characteristics */ ! 741: ,&setline ! 742: ,sizeof(setline) ! 743: ,NULL ! 744: ,NULL ! 745: ,0 ! 746: ,NULL); ! 747: #else // Win32 ! 748: GetCommState((HANDLE)rio_handle,&dcb); ! 749: if(action==LFN81) { ! 750: dcb.Parity=NOPARITY; ! 751: dcb.ByteSize=8; ! 752: dcb.StopBits=ONESTOPBIT; } ! 753: else { ! 754: dcb.Parity=EVENPARITY; ! 755: dcb.ByteSize=7; ! 756: dcb.StopBits=ONESTOPBIT; } ! 757: SetCommState((HANDLE)rio_handle,&dcb); ! 758: #endif ! 759: return(0); ! 760: case FIFOCTL: ! 761: #ifdef __OS2__ ! 762: DosDevIOCtl(rio_handle ! 763: ,IOCTL_ASYNC, 0x73 /* Query Device Control Block (DCB) Parms */ ! 764: ,NULL ! 765: ,0 ! 766: ,NULL ! 767: ,&async_dcb ! 768: ,sizeof(async_dcb) ! 769: ,NULL); ! 770: ! 771: /* Extended Hardware Buffering (16550 FIFO) */ ! 772: if(async_dcb.flags3&(1<<4)) { /* Supported */ ! 773: c=0xc0; ! 774: if(async_dcb.flags3&(1<<7)) ! 775: c|=0x0c; ! 776: return(c); } ! 777: #else // Win32 ! 778: // Not supported under Win32? ! 779: #endif ! 780: return(0); ! 781: } ! 782: ! 783: if((action&0xff)<=IOCM) { /* Get/Set/Clear mode */ ! 784: mode=0; ! 785: ! 786: #ifdef __OS2__ ! 787: DosDevIOCtl(rio_handle ! 788: ,IOCTL_ASYNC, 0x73 /* Query Device Control Block (DCB) Parms */ ! 789: ,NULL ! 790: ,0 ! 791: ,NULL ! 792: ,&async_dcb ! 793: ,sizeof(async_dcb) ! 794: ,NULL); ! 795: if(async_dcb.flags1&(1<<3)) /* Output CTS handshaking */ ! 796: mode|=CTSCK; ! 797: if(async_dcb.flags2&(1<<0)) /* Automatic Xmit Control Flow Xon/Xoff */ ! 798: mode|=PAUSE; ! 799: if(async_dcb.flags2&(1<<7) /* RTS Input handshaking */ ! 800: && !(async_dcb.flags2&(1<<6))) ! 801: mode|=RTSCK; ! 802: if(rio_abort) ! 803: mode|=ABORT; ! 804: ! 805: if(action==IOMODE) ! 806: return(mode); ! 807: ! 808: if((action&0xff)==IOCM) /* Clear mode */ ! 809: mode&=~(action&0xff00); ! 810: else /* Set mode */ ! 811: mode|=(action&0xff00); ! 812: ! 813: if(mode&CTSCK) ! 814: async_dcb.flags1|=(1<<3); ! 815: else ! 816: async_dcb.flags1&=~(1<<3); ! 817: if(mode&PAUSE) { ! 818: async_dcb.flags2|=(1<<0); /* xmit flow control */ ! 819: async_dcb.xon_char=17; /* Ctrl-Q */ ! 820: async_dcb.xoff_char=19; } /* Ctrl-S */ ! 821: else ! 822: async_dcb.flags2&=~(1<<0); ! 823: if(mode&RTSCK) { ! 824: async_dcb.flags2|=(1<<7); ! 825: async_dcb.flags2&=~(1<<6); } ! 826: else ! 827: async_dcb.flags2&=~((1<<7)|(1<<6)); ! 828: if(mode&ABORT) ! 829: rio_abort=1; ! 830: else ! 831: rio_abort=0; ! 832: ! 833: DosDevIOCtl(rio_handle ! 834: ,IOCTL_ASYNC, 0x53 /* Set Device Control Block (DCB) Parms */ ! 835: ,&async_dcb ! 836: ,sizeof(async_dcb) ! 837: ,NULL ! 838: ,NULL ! 839: ,0 ! 840: ,NULL); ! 841: ! 842: #else // Win32 ! 843: ! 844: GetCommState((HANDLE)rio_handle,&dcb); ! 845: if(dcb.fOutxCtsFlow) ! 846: mode|=CTSCK; ! 847: if(dcb.fOutX) ! 848: mode|=PAUSE; ! 849: if(dcb.fRtsControl==RTS_CONTROL_HANDSHAKE) ! 850: mode|=RTSCK; ! 851: ! 852: if(rio_abort) ! 853: mode|=ABORT; ! 854: ! 855: if(action==IOMODE) ! 856: return(mode); ! 857: ! 858: if((action&0xff)==IOCM) /* Clear mode */ ! 859: mode&=~(action&0xff00); ! 860: else /* Set mode */ ! 861: mode|=(action&0xff00); ! 862: ! 863: if(mode&CTSCK) ! 864: dcb.fOutxCtsFlow=1; ! 865: else ! 866: dcb.fOutxCtsFlow=0; ! 867: if(mode&PAUSE) { ! 868: dcb.fOutX=1; ! 869: dcb.XonChar=17; /* Ctrl-Q */ ! 870: dcb.XoffChar=19; } /* Ctrl-S */ ! 871: else ! 872: dcb.fOutX=0; ! 873: if(mode&RTSCK) ! 874: dcb.fRtsControl=RTS_CONTROL_HANDSHAKE; ! 875: else ! 876: dcb.fRtsControl=RTS_CONTROL_ENABLE; ! 877: if(mode&ABORT) ! 878: rio_abort=1; ! 879: else ! 880: rio_abort=0; ! 881: ! 882: SetCommState((HANDLE)rio_handle,&dcb); ! 883: ! 884: #endif ! 885: ! 886: return(mode); } ! 887: ! 888: if((action&0xff)==IOSS) { /* Set state */ ! 889: ! 890: if(action&ABORT) ! 891: rio_aborted=1; ! 892: ! 893: #ifdef __OS2__ ! 894: if(action&PAUSE) ! 895: DosDevIOCtl(rio_handle ! 896: ,IOCTL_ASYNC, 0x47 /* Behave as if XOFF Received */ ! 897: ,NULL ! 898: ,0 ! 899: ,NULL ! 900: ,&w ! 901: ,sizeof(short) ! 902: ,NULL); ! 903: #else // Win32 ! 904: if(action&PAUSE) ! 905: EscapeCommFunction((HANDLE)rio_handle,SETXOFF); ! 906: #endif ! 907: ! 908: return(rio_getstate()); } ! 909: ! 910: if((action&0xff)==IOCS) { /* Clear state */ ! 911: ! 912: if(action&ABORT) ! 913: rio_aborted=0; ! 914: ! 915: #ifdef __OS2__ ! 916: if(action&PAUSE) ! 917: DosDevIOCtl(rio_handle ! 918: ,IOCTL_ASYNC, 0x48 /* Behave as if XON Received */ ! 919: ,NULL ! 920: ,0 ! 921: ,NULL ! 922: ,&w ! 923: ,sizeof(short) ! 924: ,NULL); ! 925: #else // Win32 ! 926: if(action&PAUSE) ! 927: EscapeCommFunction((HANDLE)rio_handle,SETXON); ! 928: #endif ! 929: return(rio_getstate()); } ! 930: ! 931: if((action&0xff)==TXSYNC) { /* Synchronize transmition */ ! 932: c=action>>8; /* Number of seconds */ ! 933: w=110+(c*1000); /* Number of milliseconds */ ! 934: start=clock(); ! 935: while(clock()-start<w) { ! 936: if(!outbufcnt()) { ! 937: #ifdef __OS2__ ! 938: DosDevIOCtl(rio_handle ! 939: ,IOCTL_ASYNC, 0x69 /* Query # of chars in tx queue */ ! 940: ,NULL ! 941: ,0 ! 942: ,NULL ! 943: ,&getqueue ! 944: ,sizeof(getqueue) ! 945: ,NULL); ! 946: if(getqueue.cur==0) /* Empty outbound queue */ ! 947: return(0); ! 948: #else // Win32 ! 949: ClearCommError((HANDLE)rio_handle,&l,&comstat); ! 950: if(comstat.cbOutQue==0) /* Empty outbound queue */ ! 951: return(0); ! 952: #endif ! 953: } ! 954: #ifdef __OS2__ ! 955: DosSleep(1); ! 956: #else // Win32 ! 957: Sleep(1); ! 958: #endif ! 959: } ! 960: return(1); } ! 961: ! 962: return(0); ! 963: } ! 964: ! 965: /* End of file */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.