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