Release 980301
[wine/hacks.git] / misc / comm.c
blobd41899478f01193a616111fcbbc7599da6f241d1
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
5 * FIXME: use HFILEs instead of unixfds
6 * the win32 functions here get HFILEs already.
8 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
9 * - ptr->fd wasn't getting cleared on close.
10 * - GetCommEventMask() and GetCommError() didn't do much of anything.
11 * IMHO, they are still wrong, but they at least implement the RXCHAR
12 * event and return I/O queue sizes, which makes the app I'm interested
13 * in (analog devices EZKIT DSP development system) work.
15 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
16 * <lawson_whitney@juno.com>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <termios.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <sys/stat.h>
27 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__svr4__)
28 #include <sys/filio.h>
29 #endif
30 #include <sys/ioctl.h>
31 #include <unistd.h>
33 #include "windows.h"
34 #include "comm.h"
35 #include "heap.h"
36 #include "options.h"
37 #include "debug.h"
39 #ifndef TIOCINQ
40 #define TIOCINQ FIONREAD
41 #endif
42 #define msr 35 /* offset in unknown structure commMask */
44 * [RER] These are globals are wrong. They should be in DosDeviceStruct
45 * on a per port basis.
47 int commerror = 0, eventmask = 0;
49 struct DosDeviceStruct COM[MAX_PORTS];
50 struct DosDeviceStruct LPT[MAX_PORTS];
51 LPCVOID *unknown[MAX_PORTS];
53 void COMM_Init(void)
55 int x;
56 char option[10], temp[256], *btemp;
57 struct stat st;
59 for (x=0; x!=MAX_PORTS; x++) {
60 strcpy(option,"COMx");
61 option[3] = '1' + x;
62 option[4] = '\0';
64 PROFILE_GetWineIniString( "serialports", option, "*",
65 temp, sizeof(temp) );
66 if (!strcmp(temp, "*") || *temp == '\0')
67 COM[x].devicename = NULL;
68 else {
69 btemp = strchr(temp,',');
70 if (btemp != NULL) {
71 *btemp++ = '\0';
72 COM[x].baudrate = atoi(btemp);
73 } else {
74 COM[x].baudrate = -1;
76 stat(temp, &st);
77 if (!S_ISCHR(st.st_mode))
78 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
79 else
80 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
81 fprintf(stderr,"comm: can't malloc for device info!\n");
82 else {
83 COM[x].fd = 0;
84 strcpy(COM[x].devicename, temp);
86 dprintf_info(comm,
87 "Comm_Init: %s = %s\n", option, COM[x].devicename);
90 strcpy(option, "LPTx");
91 option[3] = '1' + x;
92 option[4] = '\0';
94 PROFILE_GetWineIniString( "parallelports", option, "*",
95 temp, sizeof(temp) );
96 if (!strcmp(temp, "*") || *temp == '\0')
97 LPT[x].devicename = NULL;
98 else {
99 stat(temp, &st);
100 if (!S_ISCHR(st.st_mode))
101 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
102 else
103 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
104 fprintf(stderr,"comm: can't malloc for device info!\n");
105 else {
106 LPT[x].fd = 0;
107 strcpy(LPT[x].devicename, temp);
109 dprintf_info(comm,
110 "Comm_Init: %s = %s\n", option, LPT[x].devicename);
117 struct DosDeviceStruct *GetDeviceStruct(int fd)
119 int x;
121 for (x=0; x!=MAX_PORTS; x++) {
122 if (COM[x].fd == fd)
123 return &COM[x];
124 if (LPT[x].fd == fd)
125 return &LPT[x];
128 return NULL;
131 int GetCommPort(int fd)
133 int x;
135 for (x=0; x<MAX_PORTS; x++) {
136 if (COM[x].fd == fd)
137 return x;
140 return -1;
143 int ValidCOMPort(int x)
145 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
148 int ValidLPTPort(int x)
150 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
153 int WinError(void)
155 dprintf_info(comm, "WinError: errno = %d\n", errno);
156 switch (errno) {
157 default:
158 return CE_IOE;
162 /**************************************************************************
163 * BuildCommDCB (USER.213)
165 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
167 /* "COM1:9600,n,8,1" */
168 /* 012345 */
169 int port;
170 char *ptr, temp[256];
172 dprintf_info(comm,
173 "BuildCommDCB: (%s), ptr %p\n", device, lpdcb);
174 commerror = 0;
176 if (!lstrncmpi32A(device,"COM",3)) {
177 port = device[3] - '0';
180 if (port-- == 0) {
181 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
182 commerror = IE_BADID;
185 if (!ValidCOMPort(port)) {
186 commerror = IE_BADID;
187 return -1;
190 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
192 if (!COM[port].fd) {
193 OpenComm(device, 0, 0);
195 lpdcb->Id = COM[port].fd;
197 if (!*(device+4))
198 return 0;
200 if (*(device+4) != ':')
201 return -1;
203 strcpy(temp,device+5);
204 ptr = strtok(temp, ", ");
206 if (COM[port].baudrate > 0)
207 lpdcb->BaudRate = COM[port].baudrate;
208 else
209 lpdcb->BaudRate = atoi(ptr);
210 dprintf_info(comm,"BuildCommDCB: baudrate (%d)\n", lpdcb->BaudRate);
212 ptr = strtok(NULL, ", ");
213 if (islower(*ptr))
214 *ptr = toupper(*ptr);
216 dprintf_info(comm,"BuildCommDCB: parity (%c)\n", *ptr);
217 lpdcb->fParity = 1;
218 switch (*ptr) {
219 case 'N':
220 lpdcb->Parity = NOPARITY;
221 lpdcb->fParity = 0;
222 break;
223 case 'E':
224 lpdcb->Parity = EVENPARITY;
225 break;
226 case 'M':
227 lpdcb->Parity = MARKPARITY;
228 break;
229 case 'O':
230 lpdcb->Parity = ODDPARITY;
231 break;
232 default:
233 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
234 return -1;
237 ptr = strtok(NULL, ", ");
238 dprintf_info(comm, "BuildCommDCB: charsize (%c)\n", *ptr);
239 lpdcb->ByteSize = *ptr - '0';
241 ptr = strtok(NULL, ", ");
242 dprintf_info(comm, "BuildCommDCB: stopbits (%c)\n", *ptr);
243 switch (*ptr) {
244 case '1':
245 lpdcb->StopBits = ONESTOPBIT;
246 break;
247 case '2':
248 lpdcb->StopBits = TWOSTOPBITS;
249 break;
250 default:
251 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
252 return -1;
256 return 0;
259 /**************************************************************************
260 * BuildCommDCBA (KERNEL32.14)
262 BOOL32 WINAPI BuildCommDCB32A(LPCSTR device,LPDCB32 lpdcb)
264 return BuildCommDCBAndTimeouts32A(device,lpdcb,NULL);
267 /**************************************************************************
268 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
270 BOOL32 WINAPI BuildCommDCBAndTimeouts32A(LPCSTR device, LPDCB32 lpdcb,
271 LPCOMMTIMEOUTS lptimeouts)
273 int port;
274 char *ptr,*temp;
276 dprintf_info(comm,"BuildCommDCBAndTimeouts32A(%s,%p,%p)\n",device,lpdcb,lptimeouts);
277 commerror = 0;
279 if (!lstrncmpi32A(device,"COM",3)) {
280 port=device[3]-'0';
281 if (port--==0) {
282 fprintf(stderr,"comm:BUG! COM0 can't exists!.\n");
283 return FALSE;
285 if (!ValidCOMPort(port))
286 return FALSE;
287 if (*(device+4)!=':')
288 return FALSE;
289 temp=(LPSTR)(device+5);
290 } else
291 temp=(LPSTR)device;
293 memset(lpdcb, 0, sizeof(DCB32)); /* initialize */
295 lpdcb->DCBlength = sizeof(DCB32);
296 if (strchr(temp,',')) { /* old style */
297 DCB16 dcb16;
298 BOOL16 ret;
299 char last=temp[strlen(temp)-1];
301 ret=BuildCommDCB16(device,&dcb16);
302 if (!ret)
303 return FALSE;
304 lpdcb->BaudRate = dcb16.BaudRate;
305 lpdcb->ByteSize = dcb16.ByteSize;
306 lpdcb->fBinary = dcb16.fBinary;
307 lpdcb->Parity = dcb16.Parity;
308 lpdcb->fParity = dcb16.fParity;
309 lpdcb->fNull = dcb16.fNull;
310 lpdcb->StopBits = dcb16.StopBits;
311 if (last == 'x') {
312 lpdcb->fInX = TRUE;
313 lpdcb->fOutX = TRUE;
314 lpdcb->fOutxCtsFlow = FALSE;
315 lpdcb->fOutxDsrFlow = FALSE;
316 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
317 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
318 } else if (last=='p') {
319 lpdcb->fInX = FALSE;
320 lpdcb->fOutX = FALSE;
321 lpdcb->fOutxCtsFlow = TRUE;
322 lpdcb->fOutxDsrFlow = TRUE;
323 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
324 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
325 } else {
326 lpdcb->fInX = FALSE;
327 lpdcb->fOutX = FALSE;
328 lpdcb->fOutxCtsFlow = FALSE;
329 lpdcb->fOutxDsrFlow = FALSE;
330 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
331 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
333 lpdcb->XonChar = dcb16.XonChar;
334 lpdcb->XoffChar = dcb16.XoffChar;
335 lpdcb->ErrorChar= dcb16.PeChar;
336 lpdcb->fErrorChar= dcb16.fPeChar;
337 lpdcb->EofChar = dcb16.EofChar;
338 lpdcb->EvtChar = dcb16.EvtChar;
339 lpdcb->XonLim = dcb16.XonLim;
340 lpdcb->XoffLim = dcb16.XoffLim;
341 return TRUE;
343 ptr=strtok(temp," ");
344 while (ptr) {
345 DWORD flag,x;
347 flag=0;
348 if (!strncmp("baud=",ptr,5)) {
349 if (!sscanf(ptr+5,"%ld",&x))
350 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
351 lpdcb->BaudRate = x;
352 flag=1;
354 if (!strncmp("stop=",ptr,5)) {
355 if (!sscanf(ptr+5,"%ld",&x))
356 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
357 lpdcb->StopBits = x;
358 flag=1;
360 if (!strncmp("data=",ptr,5)) {
361 if (!sscanf(ptr+5,"%ld",&x))
362 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
363 lpdcb->ByteSize = x;
364 flag=1;
366 if (!strncmp("parity=",ptr,7)) {
367 lpdcb->fParity = TRUE;
368 switch (ptr[8]) {
369 case 'N':case 'n':
370 lpdcb->fParity = FALSE;
371 lpdcb->Parity = NOPARITY;
372 break;
373 case 'E':case 'e':
374 lpdcb->Parity = EVENPARITY;
375 break;
376 case 'O':case 'o':
377 lpdcb->Parity = ODDPARITY;
378 break;
379 case 'M':case 'm':
380 lpdcb->Parity = MARKPARITY;
381 break;
383 flag=1;
385 if (!flag)
386 fprintf(stderr,"BuildCommDCB32A: Unhandled specifier '%s', please report.\n",ptr);
387 ptr=strtok(NULL," ");
389 if (lpdcb->BaudRate==110)
390 lpdcb->StopBits = 2;
391 return TRUE;
394 /**************************************************************************
395 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
397 BOOL32 WINAPI BuildCommDCBAndTimeouts32W( LPCWSTR devid, LPDCB32 lpdcb,
398 LPCOMMTIMEOUTS lptimeouts )
400 LPSTR devidA;
401 BOOL32 ret;
403 dprintf_info(comm,"BuildCommDCBAndTimeouts32W(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
404 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
405 ret=BuildCommDCBAndTimeouts32A(devidA,lpdcb,lptimeouts);
406 HeapFree( GetProcessHeap(), 0, devidA );
407 return ret;
410 /**************************************************************************
411 * BuildCommDCBW (KERNEL32.17)
413 BOOL32 WINAPI BuildCommDCB32W(LPCWSTR devid,LPDCB32 lpdcb)
415 return BuildCommDCBAndTimeouts32W(devid,lpdcb,NULL);
418 /*****************************************************************************
419 * OpenComm (USER.200)
421 INT16 WINAPI OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
423 int port,fd;
425 dprintf_info(comm,
426 "OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
427 commerror = 0;
429 if (!lstrncmpi32A(device,"COM",3)) {
430 port = device[3] - '0';
432 if (port-- == 0) {
433 fprintf(stderr, "comm: BUG ! COM0 doesn't exist !\n");
434 commerror = IE_BADID;
437 dprintf_info(comm,
438 "OpenComm: %s = %s\n", device, COM[port].devicename);
440 if (!ValidCOMPort(port)) {
441 commerror = IE_BADID;
442 return -1;
444 if (COM[port].fd) {
445 return COM[port].fd;
448 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
449 if (fd == -1) {
450 commerror = WinError();
451 return -1;
452 } else {
453 unknown[port] = SEGPTR_ALLOC(40);
454 bzero(unknown[port],40);
455 COM[port].fd = fd;
456 return fd;
459 else
460 if (!lstrncmpi32A(device,"LPT",3)) {
461 port = device[3] - '0';
463 if (!ValidLPTPort(port)) {
464 commerror = IE_BADID;
465 return -1;
467 if (LPT[port].fd) {
468 commerror = IE_OPEN;
469 return -1;
472 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
473 if (fd == -1) {
474 commerror = WinError();
475 return -1;
476 } else {
477 LPT[port].fd = fd;
478 return fd;
481 return 0;
484 /*****************************************************************************
485 * CloseComm (USER.207)
487 INT16 WINAPI CloseComm(INT16 fd)
489 int port;
490 dprintf_info(comm,"CloseComm: fd %d\n", fd);
491 if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
492 SEGPTR_FREE(unknown[port]);
493 COM[port].fd = 0; /* my adaptation of RER's fix */
494 } else {
495 commerror = IE_BADID;
496 return -1;
499 if (close(fd) == -1) {
500 commerror = WinError();
501 return -1;
502 } else {
503 commerror = 0;
504 return 0;
508 /*****************************************************************************
509 * SetCommBreak (USER.210)
511 INT16 WINAPI SetCommBreak16(INT16 fd)
513 struct DosDeviceStruct *ptr;
515 dprintf_info(comm,"SetCommBreak: fd: %d\n", fd);
516 if ((ptr = GetDeviceStruct(fd)) == NULL) {
517 commerror = IE_BADID;
518 return -1;
521 ptr->suspended = 1;
522 commerror = 0;
523 return 0;
526 /*****************************************************************************
527 * SetCommBreak (KERNEL32.449)
529 BOOL32 WINAPI SetCommBreak32(INT32 fd)
532 struct DosDeviceStruct *ptr;
534 dprintf_info(comm,"SetCommBreak: fd: %d\n", fd);
535 if ((ptr = GetDeviceStruct(fd)) == NULL) {
536 commerror = IE_BADID;
537 return FALSE;
540 ptr->suspended = 1;
541 commerror = 0;
542 return TRUE;
545 /*****************************************************************************
546 * ClearCommBreak (USER.211)
548 INT16 WINAPI ClearCommBreak16(INT16 fd)
550 struct DosDeviceStruct *ptr;
552 dprintf_info(comm,"ClearCommBreak: fd: %d\n", fd);
553 if ((ptr = GetDeviceStruct(fd)) == NULL) {
554 commerror = IE_BADID;
555 return -1;
558 ptr->suspended = 0;
559 commerror = 0;
560 return 0;
563 /*****************************************************************************
564 * ClearCommBreak (KERNEL32.20)
566 BOOL32 WINAPI ClearCommBreak32(INT32 fd)
568 struct DosDeviceStruct *ptr;
570 dprintf_info(comm,"ClearCommBreak: fd: %d\n", fd);
571 if ((ptr = GetDeviceStruct(fd)) == NULL) {
572 commerror = IE_BADID;
573 return FALSE;
576 ptr->suspended = 0;
577 commerror = 0;
578 return TRUE;
581 /*****************************************************************************
582 * EscapeCommFunction (USER.214)
584 LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
586 int max;
587 struct termios port;
589 dprintf_info(comm,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
590 if (tcgetattr(fd,&port) == -1) {
591 commerror=WinError();
592 return -1;
595 switch (nFunction) {
596 case RESETDEV:
597 break;
599 case GETMAXCOM:
600 for (max = MAX_PORTS;!COM[max].devicename;max--)
602 return max;
603 break;
605 case GETMAXLPT:
606 for (max = MAX_PORTS;!LPT[max].devicename;max--)
608 return 0x80 + max;
609 break;
611 #ifdef TIOCM_DTR
612 case CLRDTR:
613 port.c_cflag &= TIOCM_DTR;
614 break;
615 #endif
617 #ifdef TIOCM_RTS
618 case CLRRTS:
619 port.c_cflag &= TIOCM_RTS;
620 break;
621 #endif
623 #ifdef CRTSCTS
624 case SETDTR:
625 port.c_cflag |= CRTSCTS;
626 break;
628 case SETRTS:
629 port.c_cflag |= CRTSCTS;
630 break;
631 #endif
633 case SETXOFF:
634 port.c_iflag |= IXOFF;
635 break;
637 case SETXON:
638 port.c_iflag |= IXON;
639 break;
641 default:
642 fprintf(stderr,
643 "EscapeCommFunction fd: %d, unknown function: %d\n",
644 fd, nFunction);
645 break;
648 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
649 commerror = WinError();
650 return -1;
651 } else {
652 commerror = 0;
653 return 0;
657 /*****************************************************************************
658 * EscapeCommFunction (KERNEL32.214)
660 BOOL32 WINAPI EscapeCommFunction32(INT32 fd,UINT32 nFunction)
662 struct termios port;
663 struct DosDeviceStruct *ptr;
665 dprintf_info(comm,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
666 if (tcgetattr(fd,&port) == -1) {
667 commerror=WinError();
668 return FALSE;
670 if ((ptr = GetDeviceStruct(fd)) == NULL) {
671 commerror = IE_BADID;
672 return FALSE;
675 switch (nFunction) {
676 case RESETDEV:
677 break;
679 #ifdef TIOCM_DTR
680 case CLRDTR:
681 port.c_cflag &= TIOCM_DTR;
682 break;
683 #endif
685 #ifdef TIOCM_RTS
686 case CLRRTS:
687 port.c_cflag &= TIOCM_RTS;
688 break;
689 #endif
691 #ifdef CRTSCTS
692 case SETDTR:
693 port.c_cflag |= CRTSCTS;
694 break;
696 case SETRTS:
697 port.c_cflag |= CRTSCTS;
698 break;
699 #endif
701 case SETXOFF:
702 port.c_iflag |= IXOFF;
703 break;
705 case SETXON:
706 port.c_iflag |= IXON;
707 break;
708 case SETBREAK:
709 ptr->suspended = 1;
710 break;
711 case CLRBREAK:
712 ptr->suspended = 0;
713 break;
714 default:
715 fprintf(stderr,
716 "EscapeCommFunction32 fd: %d, unknown function: %d\n",
717 fd, nFunction);
718 break;
721 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
722 commerror = WinError();
723 return FALSE;
724 } else {
725 commerror = 0;
726 return TRUE;
730 /*****************************************************************************
731 * FlushComm (USER.215)
733 INT16 WINAPI FlushComm(INT16 fd,INT16 fnQueue)
735 int queue;
737 dprintf_info(comm,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
738 switch (fnQueue) {
739 case 0: queue = TCOFLUSH;
740 break;
741 case 1: queue = TCIFLUSH;
742 break;
743 default:fprintf(stderr,
744 "FlushComm fd: %d, UNKNOWN queue: %d\n",
745 fd, fnQueue);
746 return -1;
748 if (tcflush(fd, queue)) {
749 commerror = WinError();
750 return -1;
751 } else {
752 commerror = 0;
753 return 0;
757 /********************************************************************
758 * PurgeComm (KERNEL32.557)
760 BOOL32 WINAPI PurgeComm( HANDLE32 hFile, DWORD flags)
762 dprintf_fixme(comm, "PurgeComm(%08x %08lx) unimplemented stub\n",
763 hFile, flags);
764 return 0;
767 /********************************************************************
768 * GetCommError (USER.203)
770 INT16 WINAPI GetCommError(INT16 fd,LPCOMSTAT lpStat)
772 int temperror;
773 unsigned long cnt;
774 int rc;
776 if (lpStat) {
777 lpStat->status = 0;
779 rc = ioctl(fd, TIOCOUTQ, &cnt);
780 if (rc) fprintf(stderr, "Error !\n");
781 lpStat->cbOutQue = cnt;
783 rc = ioctl(fd, TIOCINQ, &cnt);
784 if (rc) fprintf(stderr, "Error !\n");
785 lpStat->cbInQue = cnt;
787 dprintf_info(comm,
788 "GetCommError: fd %d, error %d, lpStat %d %d %d\n",
789 fd, commerror, lpStat->status, lpStat->cbInQue,
790 lpStat->cbOutQue);
792 else
793 dprintf_info(comm,
794 "GetCommError: fd %d, error %d, lpStat NULL\n",
795 fd, commerror);
798 * [RER] I have no idea what the following is trying to accomplish.
799 * [RER] It is certainly not what the reference manual suggests.
801 temperror = commerror;
802 commerror = 0;
803 return(temperror);
806 /*****************************************************************************
807 * ClearCommError (KERNEL32.21)
809 BOOL32 WINAPI ClearCommError(INT32 fd,LPDWORD errors,LPCOMSTAT lpStat)
811 int temperror;
813 dprintf_info(comm, "ClearCommError: fd %d (current error %d)\n",
814 fd, commerror);
815 temperror = commerror;
816 commerror = 0;
817 return TRUE;
820 /*****************************************************************************
821 * SetCommEventMask (USER.208)
823 SEGPTR WINAPI SetCommEventMask(INT16 fd,UINT16 fuEvtMask)
825 unsigned char *stol;
826 int act;
827 int repid;
828 unsigned int mstat;
829 dprintf_info(comm,"SetCommEventMask:fd %d,mask %d\n",fd,fuEvtMask);
830 eventmask |= fuEvtMask;
831 if ((act = GetCommPort(fd)) == -1) {
832 dprintf_warn(comm," fd %d not comm port\n",act);
833 return NULL;}
834 stol = unknown[act];
835 stol += msr;
836 repid = ioctl(fd,TIOCMGET,&mstat);
837 dprintf_info(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
838 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
839 else {*stol &=0x7f;}
840 dprintf_info(comm," modem dcd construct %x\n",*stol);
841 return SEGPTR_GET(unknown[act]);
844 /*****************************************************************************
845 * GetCommEventMask (USER.209)
847 UINT16 WINAPI GetCommEventMask(INT16 fd,UINT16 fnEvtClear)
849 int events = 0;
851 dprintf_info(comm,
852 "GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
855 * Determine if any characters are available
857 if (fnEvtClear & EV_RXCHAR)
859 int rc;
860 unsigned long cnt;
862 rc = ioctl(fd, TIOCINQ, &cnt);
863 if (cnt) events |= EV_RXCHAR;
865 dprintf_info(comm,
866 "GetCommEventMask: rxchar %ld\n", cnt);
870 * There are other events that need to be checked for
872 /* TODO */
874 dprintf_info(comm,
875 "GetCommEventMask: return events %d\n", events);
876 return events;
879 * [RER] The following was gibberish
881 #if 0
882 tempmask = eventmask;
883 eventmask &= ~fnEvtClear;
884 return eventmask;
885 #endif
888 /*****************************************************************************
889 * SetupComm (KERNEL32.676)
891 BOOL32 WINAPI SetupComm( HANDLE32 hFile, DWORD insize, DWORD outsize)
893 dprintf_fixme(comm, "SetupComm: insize %ld outsize %ld unimplemented stub\n", insize, outsize);
894 return FALSE;
897 /*****************************************************************************
898 * GetCommMask (KERNEL32.156)
900 BOOL32 WINAPI GetCommMask(INT32 fd,LPDWORD evtmask)
902 dprintf_info(comm,
903 "GetCommMask: fd %d, mask %p\n", fd, evtmask);
904 *evtmask = eventmask;
905 return TRUE;
908 /*****************************************************************************
909 * SetCommMask (KERNEL32.451)
911 BOOL32 WINAPI SetCommMask(INT32 fd,DWORD evtmask)
913 dprintf_info(comm,
914 "SetCommMask: fd %d, mask %lx\n", fd, evtmask);
915 eventmask = evtmask;
916 return TRUE;
919 /*****************************************************************************
920 * SetCommState16 (USER.201)
922 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
924 struct termios port;
925 struct DosDeviceStruct *ptr;
927 dprintf_info(comm,
928 "SetCommState16: fd %d, ptr %p\n", lpdcb->Id, lpdcb);
929 if (tcgetattr(lpdcb->Id, &port) == -1) {
930 commerror = WinError();
931 return -1;
934 port.c_cc[VMIN] = 0;
935 port.c_cc[VTIME] = 1;
937 #ifdef IMAXBEL
938 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
939 #else
940 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
941 #endif
942 port.c_iflag |= (IGNBRK);
944 port.c_oflag &= ~(OPOST);
946 port.c_cflag &= ~(HUPCL);
947 port.c_cflag |= CLOCAL | CREAD;
949 port.c_lflag &= ~(ICANON|ECHO|ISIG);
950 port.c_lflag |= NOFLSH;
952 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
953 commerror = IE_BADID;
954 return -1;
956 if (ptr->baudrate > 0)
957 lpdcb->BaudRate = ptr->baudrate;
958 dprintf_info(comm,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
959 #ifdef CBAUD
960 port.c_cflag &= ~CBAUD;
961 switch (lpdcb->BaudRate) {
962 case 110:
963 case CBR_110:
964 port.c_cflag |= B110;
965 break;
966 case 300:
967 case CBR_300:
968 port.c_cflag |= B300;
969 break;
970 case 600:
971 case CBR_600:
972 port.c_cflag |= B600;
973 break;
974 case 1200:
975 case CBR_1200:
976 port.c_cflag |= B1200;
977 break;
978 case 2400:
979 case CBR_2400:
980 port.c_cflag |= B2400;
981 break;
982 case 4800:
983 case CBR_4800:
984 port.c_cflag |= B4800;
985 break;
986 case 9600:
987 case CBR_9600:
988 port.c_cflag |= B9600;
989 break;
990 case 19200:
991 case CBR_19200:
992 port.c_cflag |= B19200;
993 break;
994 case 38400:
995 case CBR_38400:
996 port.c_cflag |= B38400;
997 break;
998 case 57600:
999 port.c_cflag |= B57600;
1000 break;
1001 case 57601:
1002 port.c_cflag |= B115200;
1003 break;
1004 default:
1005 commerror = IE_BAUDRATE;
1006 return -1;
1008 #elif !defined(__EMX__)
1009 switch (lpdcb->BaudRate) {
1010 case 110:
1011 case CBR_110:
1012 port.c_ospeed = B110;
1013 break;
1014 case 300:
1015 case CBR_300:
1016 port.c_ospeed = B300;
1017 break;
1018 case 600:
1019 case CBR_600:
1020 port.c_ospeed = B600;
1021 break;
1022 case 1200:
1023 case CBR_1200:
1024 port.c_ospeed = B1200;
1025 break;
1026 case 2400:
1027 case CBR_2400:
1028 port.c_ospeed = B2400;
1029 break;
1030 case 4800:
1031 case CBR_4800:
1032 port.c_ospeed = B4800;
1033 break;
1034 case 9600:
1035 case CBR_9600:
1036 port.c_ospeed = B9600;
1037 break;
1038 case 19200:
1039 case CBR_19200:
1040 port.c_ospeed = B19200;
1041 break;
1042 case 38400:
1043 case CBR_38400:
1044 port.c_ospeed = B38400;
1045 break;
1046 default:
1047 commerror = IE_BAUDRATE;
1048 return -1;
1050 port.c_ispeed = port.c_ospeed;
1051 #endif
1052 dprintf_info(comm,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
1053 port.c_cflag &= ~CSIZE;
1054 switch (lpdcb->ByteSize) {
1055 case 5:
1056 port.c_cflag |= CS5;
1057 break;
1058 case 6:
1059 port.c_cflag |= CS6;
1060 break;
1061 case 7:
1062 port.c_cflag |= CS7;
1063 break;
1064 case 8:
1065 port.c_cflag |= CS8;
1066 break;
1067 default:
1068 commerror = IE_BYTESIZE;
1069 return -1;
1072 dprintf_info(comm,"SetCommState: parity %d\n",lpdcb->Parity);
1073 port.c_cflag &= ~(PARENB | PARODD);
1074 if (lpdcb->fParity)
1075 switch (lpdcb->Parity) {
1076 case NOPARITY:
1077 port.c_iflag &= ~INPCK;
1078 break;
1079 case ODDPARITY:
1080 port.c_cflag |= (PARENB | PARODD);
1081 port.c_iflag |= INPCK;
1082 break;
1083 case EVENPARITY:
1084 port.c_cflag |= PARENB;
1085 port.c_iflag |= INPCK;
1086 break;
1087 default:
1088 commerror = IE_BYTESIZE;
1089 return -1;
1093 dprintf_info(comm,"SetCommState: stopbits %d\n",lpdcb->StopBits);
1095 switch (lpdcb->StopBits) {
1096 case ONESTOPBIT:
1097 port.c_cflag &= ~CSTOPB;
1098 break;
1099 case TWOSTOPBITS:
1100 port.c_cflag |= CSTOPB;
1101 break;
1102 default:
1103 commerror = IE_BYTESIZE;
1104 return -1;
1106 #ifdef CRTSCTS
1108 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1109 port.c_cflag |= CRTSCTS;
1111 if (lpdcb->fDtrDisable)
1112 port.c_cflag &= ~CRTSCTS;
1113 #endif
1114 if (lpdcb->fInX)
1115 port.c_iflag |= IXON;
1116 else
1117 port.c_iflag &= ~IXON;
1118 if (lpdcb->fOutX)
1119 port.c_iflag |= IXOFF;
1120 else
1121 port.c_iflag &= ~IXOFF;
1123 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
1124 commerror = WinError();
1125 return FALSE;
1126 } else {
1127 commerror = 0;
1128 return 0;
1132 /*****************************************************************************
1133 * SetCommState32 (KERNEL32.452)
1135 BOOL32 WINAPI SetCommState32(INT32 fd,LPDCB32 lpdcb)
1137 struct termios port;
1138 struct DosDeviceStruct *ptr;
1140 dprintf_info(comm,"SetCommState32: fd %d, ptr %p\n",fd,lpdcb);
1141 if (tcgetattr(fd,&port) == -1) {
1142 commerror = WinError();
1143 return FALSE;
1146 port.c_cc[VMIN] = 0;
1147 port.c_cc[VTIME] = 1;
1149 #ifdef IMAXBEL
1150 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1151 #else
1152 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1153 #endif
1154 port.c_iflag |= (IGNBRK);
1156 port.c_oflag &= ~(OPOST);
1158 port.c_cflag &= ~(HUPCL);
1159 port.c_cflag |= CLOCAL | CREAD;
1161 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1162 port.c_lflag |= NOFLSH;
1164 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1165 commerror = IE_BADID;
1166 return FALSE;
1168 if (ptr->baudrate > 0)
1169 lpdcb->BaudRate = ptr->baudrate;
1170 dprintf_info(comm,"SetCommState: baudrate %ld\n",lpdcb->BaudRate);
1171 #ifdef CBAUD
1172 port.c_cflag &= ~CBAUD;
1173 switch (lpdcb->BaudRate) {
1174 case 110:
1175 case CBR_110:
1176 port.c_cflag |= B110;
1177 break;
1178 case 300:
1179 case CBR_300:
1180 port.c_cflag |= B300;
1181 break;
1182 case 600:
1183 case CBR_600:
1184 port.c_cflag |= B600;
1185 break;
1186 case 1200:
1187 case CBR_1200:
1188 port.c_cflag |= B1200;
1189 break;
1190 case 2400:
1191 case CBR_2400:
1192 port.c_cflag |= B2400;
1193 break;
1194 case 4800:
1195 case CBR_4800:
1196 port.c_cflag |= B4800;
1197 break;
1198 case 9600:
1199 case CBR_9600:
1200 port.c_cflag |= B9600;
1201 break;
1202 case 19200:
1203 case CBR_19200:
1204 port.c_cflag |= B19200;
1205 break;
1206 case 38400:
1207 case CBR_38400:
1208 port.c_cflag |= B38400;
1209 break;
1210 default:
1211 commerror = IE_BAUDRATE;
1212 return FALSE;
1214 #elif !defined(__EMX__)
1215 switch (lpdcb->BaudRate) {
1216 case 110:
1217 case CBR_110:
1218 port.c_ospeed = B110;
1219 break;
1220 case 300:
1221 case CBR_300:
1222 port.c_ospeed = B300;
1223 break;
1224 case 600:
1225 case CBR_600:
1226 port.c_ospeed = B600;
1227 break;
1228 case 1200:
1229 case CBR_1200:
1230 port.c_ospeed = B1200;
1231 break;
1232 case 2400:
1233 case CBR_2400:
1234 port.c_ospeed = B2400;
1235 break;
1236 case 4800:
1237 case CBR_4800:
1238 port.c_ospeed = B4800;
1239 break;
1240 case 9600:
1241 case CBR_9600:
1242 port.c_ospeed = B9600;
1243 break;
1244 case 19200:
1245 case CBR_19200:
1246 port.c_ospeed = B19200;
1247 break;
1248 case 38400:
1249 case CBR_38400:
1250 port.c_ospeed = B38400;
1251 break;
1252 default:
1253 commerror = IE_BAUDRATE;
1254 return FALSE;
1256 port.c_ispeed = port.c_ospeed;
1257 #endif
1258 dprintf_info(comm,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
1259 port.c_cflag &= ~CSIZE;
1260 switch (lpdcb->ByteSize) {
1261 case 5:
1262 port.c_cflag |= CS5;
1263 break;
1264 case 6:
1265 port.c_cflag |= CS6;
1266 break;
1267 case 7:
1268 port.c_cflag |= CS7;
1269 break;
1270 case 8:
1271 port.c_cflag |= CS8;
1272 break;
1273 default:
1274 commerror = IE_BYTESIZE;
1275 return FALSE;
1278 dprintf_info(comm,"SetCommState: parity %d\n",lpdcb->Parity);
1279 port.c_cflag &= ~(PARENB | PARODD);
1280 if (lpdcb->fParity)
1281 switch (lpdcb->Parity) {
1282 case NOPARITY:
1283 port.c_iflag &= ~INPCK;
1284 break;
1285 case ODDPARITY:
1286 port.c_cflag |= (PARENB | PARODD);
1287 port.c_iflag |= INPCK;
1288 break;
1289 case EVENPARITY:
1290 port.c_cflag |= PARENB;
1291 port.c_iflag |= INPCK;
1292 break;
1293 default:
1294 commerror = IE_BYTESIZE;
1295 return FALSE;
1299 dprintf_info(comm,"SetCommState: stopbits %d\n",lpdcb->StopBits);
1300 switch (lpdcb->StopBits) {
1301 case ONESTOPBIT:
1302 port.c_cflag &= ~CSTOPB;
1303 break;
1304 case TWOSTOPBITS:
1305 port.c_cflag |= CSTOPB;
1306 break;
1307 default:
1308 commerror = IE_BYTESIZE;
1309 return FALSE;
1311 #ifdef CRTSCTS
1312 if ( lpdcb->fOutxCtsFlow ||
1313 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1314 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1316 port.c_cflag |= CRTSCTS;
1317 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1318 port.c_cflag &= ~CRTSCTS;
1320 #endif
1321 if (lpdcb->fInX)
1322 port.c_iflag |= IXON;
1323 else
1324 port.c_iflag &= ~IXON;
1325 if (lpdcb->fOutX)
1326 port.c_iflag |= IXOFF;
1327 else
1328 port.c_iflag &= ~IXOFF;
1330 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1331 commerror = WinError();
1332 return FALSE;
1333 } else {
1334 commerror = 0;
1335 return TRUE;
1340 /*****************************************************************************
1341 * GetCommState (USER.202)
1343 INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
1345 struct termios port;
1347 dprintf_info(comm,"GetCommState16: fd %d, ptr %p\n", fd, lpdcb);
1348 if (tcgetattr(fd, &port) == -1) {
1349 commerror = WinError();
1350 return -1;
1352 lpdcb->Id = fd;
1353 #ifndef __EMX__
1354 #ifdef CBAUD
1355 switch (port.c_cflag & CBAUD) {
1356 #else
1357 switch (port.c_ospeed) {
1358 #endif
1359 case B110:
1360 lpdcb->BaudRate = 110;
1361 break;
1362 case B300:
1363 lpdcb->BaudRate = 300;
1364 break;
1365 case B600:
1366 lpdcb->BaudRate = 600;
1367 break;
1368 case B1200:
1369 lpdcb->BaudRate = 1200;
1370 break;
1371 case B2400:
1372 lpdcb->BaudRate = 2400;
1373 break;
1374 case B4800:
1375 lpdcb->BaudRate = 4800;
1376 break;
1377 case B9600:
1378 lpdcb->BaudRate = 9600;
1379 break;
1380 case B19200:
1381 lpdcb->BaudRate = 19200;
1382 break;
1383 case B38400:
1384 lpdcb->BaudRate = 38400;
1385 break;
1386 case B57600:
1387 lpdcb->BaudRate = 57600;
1388 break;
1389 case B115200:
1390 lpdcb->BaudRate = 57601;
1391 break;
1393 #endif
1394 switch (port.c_cflag & CSIZE) {
1395 case CS5:
1396 lpdcb->ByteSize = 5;
1397 break;
1398 case CS6:
1399 lpdcb->ByteSize = 6;
1400 break;
1401 case CS7:
1402 lpdcb->ByteSize = 7;
1403 break;
1404 case CS8:
1405 lpdcb->ByteSize = 8;
1406 break;
1409 switch (port.c_cflag & ~(PARENB | PARODD)) {
1410 case 0:
1411 lpdcb->fParity = NOPARITY;
1412 break;
1413 case PARENB:
1414 lpdcb->fParity = EVENPARITY;
1415 break;
1416 case (PARENB | PARODD):
1417 lpdcb->fParity = ODDPARITY;
1418 break;
1421 if (port.c_cflag & CSTOPB)
1422 lpdcb->StopBits = TWOSTOPBITS;
1423 else
1424 lpdcb->StopBits = ONESTOPBIT;
1426 lpdcb->RlsTimeout = 50;
1427 lpdcb->CtsTimeout = 50;
1428 lpdcb->DsrTimeout = 50;
1429 lpdcb->fNull = 0;
1430 lpdcb->fChEvt = 0;
1431 lpdcb->fBinary = 1;
1432 lpdcb->fDtrDisable = 0;
1434 #ifdef CRTSCTS
1436 if (port.c_cflag & CRTSCTS) {
1437 lpdcb->fDtrflow = 1;
1438 lpdcb->fRtsflow = 1;
1439 lpdcb->fOutxCtsFlow = 1;
1440 lpdcb->fOutxDsrFlow = 1;
1441 } else
1442 #endif
1443 lpdcb->fDtrDisable = 1;
1445 if (port.c_iflag & IXON)
1446 lpdcb->fInX = 1;
1447 else
1448 lpdcb->fInX = 0;
1450 if (port.c_iflag & IXOFF)
1451 lpdcb->fOutX = 1;
1452 else
1453 lpdcb->fOutX = 0;
1455 lpdcb->XonChar =
1456 lpdcb->XoffChar =
1458 lpdcb->XonLim = 10;
1459 lpdcb->XoffLim = 10;
1461 commerror = 0;
1462 return 0;
1465 /*****************************************************************************
1466 * GetCommState (KERNEL32.159)
1468 BOOL32 WINAPI GetCommState32(INT32 fd, LPDCB32 lpdcb)
1470 struct termios port;
1472 dprintf_info(comm,"GetCommState32: fd %d, ptr %p\n", fd, lpdcb);
1473 if (GetDeviceStruct(fd) == NULL) return FALSE;
1474 if (tcgetattr(fd, &port) == -1) {
1475 commerror = WinError();
1476 return FALSE;
1478 #ifndef __EMX__
1479 #ifdef CBAUD
1480 switch (port.c_cflag & CBAUD) {
1481 #else
1482 switch (port.c_ospeed) {
1483 #endif
1484 case B110:
1485 lpdcb->BaudRate = 110;
1486 break;
1487 case B300:
1488 lpdcb->BaudRate = 300;
1489 break;
1490 case B600:
1491 lpdcb->BaudRate = 600;
1492 break;
1493 case B1200:
1494 lpdcb->BaudRate = 1200;
1495 break;
1496 case B2400:
1497 lpdcb->BaudRate = 2400;
1498 break;
1499 case B4800:
1500 lpdcb->BaudRate = 4800;
1501 break;
1502 case B9600:
1503 lpdcb->BaudRate = 9600;
1504 break;
1505 case B19200:
1506 lpdcb->BaudRate = 19200;
1507 break;
1508 case B38400:
1509 lpdcb->BaudRate = 38400;
1510 break;
1512 #endif
1513 switch (port.c_cflag & CSIZE) {
1514 case CS5:
1515 lpdcb->ByteSize = 5;
1516 break;
1517 case CS6:
1518 lpdcb->ByteSize = 6;
1519 break;
1520 case CS7:
1521 lpdcb->ByteSize = 7;
1522 break;
1523 case CS8:
1524 lpdcb->ByteSize = 8;
1525 break;
1528 switch (port.c_cflag & ~(PARENB | PARODD)) {
1529 case 0:
1530 lpdcb->fParity = NOPARITY;
1531 break;
1532 case PARENB:
1533 lpdcb->fParity = EVENPARITY;
1534 break;
1535 case (PARENB | PARODD):
1536 lpdcb->fParity = ODDPARITY;
1537 break;
1540 if (port.c_cflag & CSTOPB)
1541 lpdcb->StopBits = TWOSTOPBITS;
1542 else
1543 lpdcb->StopBits = ONESTOPBIT;
1545 lpdcb->fNull = 0;
1546 lpdcb->fBinary = 1;
1548 #ifdef CRTSCTS
1550 if (port.c_cflag & CRTSCTS) {
1551 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1552 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1553 lpdcb->fOutxCtsFlow = 1;
1554 lpdcb->fOutxDsrFlow = 1;
1555 } else
1556 #endif
1558 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1559 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1561 if (port.c_iflag & IXON)
1562 lpdcb->fInX = 1;
1563 else
1564 lpdcb->fInX = 0;
1566 if (port.c_iflag & IXOFF)
1567 lpdcb->fOutX = 1;
1568 else
1569 lpdcb->fOutX = 0;
1571 lpdcb->XonChar =
1572 lpdcb->XoffChar =
1574 lpdcb->XonLim = 10;
1575 lpdcb->XoffLim = 10;
1577 commerror = 0;
1578 return TRUE;
1581 /*****************************************************************************
1582 * TransmitCommChar (USER.206)
1584 INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
1586 struct DosDeviceStruct *ptr;
1588 dprintf_info(comm,
1589 "TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
1590 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1591 commerror = IE_BADID;
1592 return -1;
1595 if (ptr->suspended) {
1596 commerror = IE_HARDWARE;
1597 return -1;
1600 if (write(fd, (void *) &chTransmit, 1) == -1) {
1601 commerror = WinError();
1602 return -1;
1603 } else {
1604 commerror = 0;
1605 return 0;
1609 /*****************************************************************************
1610 * TransmitCommChar (KERNEL32.535)
1612 BOOL32 WINAPI TransmitCommChar32(INT32 fd,CHAR chTransmit)
1614 struct DosDeviceStruct *ptr;
1616 dprintf_info(comm,"TransmitCommChar32(%d,'%c')\n",fd,chTransmit);
1617 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1618 commerror = IE_BADID;
1619 return FALSE;
1622 if (ptr->suspended) {
1623 commerror = IE_HARDWARE;
1624 return FALSE;
1626 if (write(fd, (void *) &chTransmit, 1) == -1) {
1627 commerror = WinError();
1628 return FALSE;
1629 } else {
1630 commerror = 0;
1631 return TRUE;
1635 /*****************************************************************************
1636 * UngetCommChar (USER.212)
1638 INT16 WINAPI UngetCommChar(INT16 fd,CHAR chUnget)
1640 struct DosDeviceStruct *ptr;
1642 dprintf_info(comm,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
1643 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1644 commerror = IE_BADID;
1645 return -1;
1648 if (ptr->suspended) {
1649 commerror = IE_HARDWARE;
1650 return -1;
1653 ptr->unget = 1;
1654 ptr->unget_byte = chUnget;
1655 commerror = 0;
1656 return 0;
1659 /*****************************************************************************
1660 * ReadComm (USER.204)
1662 INT16 WINAPI ReadComm(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1664 int status, length;
1665 struct DosDeviceStruct *ptr;
1667 dprintf_info(comm,
1668 "ReadComm: fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1669 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1670 commerror = IE_BADID;
1671 return -1;
1674 if (ptr->suspended) {
1675 commerror = IE_HARDWARE;
1676 return -1;
1679 if (ptr->unget) {
1680 *lpvBuf = ptr->unget_byte;
1681 lpvBuf++;
1682 ptr->unget = 0;
1684 length = 1;
1685 } else
1686 length = 0;
1688 status = read(fd, (void *) lpvBuf, cbRead);
1690 if (status == -1) {
1691 if (errno != EAGAIN) {
1692 commerror = WinError();
1693 return -1 - length;
1694 } else {
1695 commerror = 0;
1696 return length;
1698 } else {
1699 dprintf_info(comm,"%*s\n", length+status, lpvBuf);
1700 commerror = 0;
1701 return length + status;
1705 /*****************************************************************************
1706 * WriteComm (USER.205)
1708 INT16 WINAPI WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1710 int length;
1711 struct DosDeviceStruct *ptr;
1713 dprintf_info(comm,"WriteComm: fd %d, ptr %p, length %d\n",
1714 fd, lpvBuf, cbWrite);
1715 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1716 commerror = IE_BADID;
1717 return -1;
1720 if (ptr->suspended) {
1721 commerror = IE_HARDWARE;
1722 return -1;
1725 dprintf_info(comm,"%*s\n", cbWrite, lpvBuf );
1726 length = write(fd, (void *) lpvBuf, cbWrite);
1728 if (length == -1) {
1729 commerror = WinError();
1730 return -1;
1731 } else {
1732 commerror = 0;
1733 return length;
1738 /*****************************************************************************
1739 * GetCommTimeouts (KERNEL32.160)
1741 BOOL32 WINAPI GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts)
1743 fprintf(stderr,"GetCommTimeouts(%x,%p), empty stub.\n",
1744 fd,lptimeouts
1746 return TRUE;
1749 /*****************************************************************************
1750 * SetCommTimeouts (KERNEL32.453)
1752 BOOL32 WINAPI SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
1753 fprintf(stderr,"SetCommTimeouts(%x,%p), empty stub.\n",
1754 fd,lptimeouts
1756 return TRUE;
1759 /***********************************************************************
1760 * EnableCommNotification (USER.246)
1762 BOOL16 WINAPI EnableCommNotification( INT16 fd, HWND16 hwnd,
1763 INT16 cbWriteNotify, INT16 cbOutQueue )
1765 fprintf(stderr, "EnableCommNotification(%d, %x, %d, %d), empty stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
1766 return TRUE;