Release 980413
[wine.git] / misc / comm.c
blob169d7332811949a63682b7bffce1d694a80ec1bb
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 "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <termios.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <sys/stat.h>
29 #ifdef HAVE_SYS_FILIO_H
30 # include <sys/filio.h>
31 #endif
32 #include <sys/ioctl.h>
33 #include <unistd.h>
35 #include "windows.h"
36 #include "comm.h"
37 #include "heap.h"
38 #include "options.h"
39 #include "debug.h"
41 #ifndef TIOCINQ
42 #define TIOCINQ FIONREAD
43 #endif
44 #define msr 35 /* offset in unknown structure commMask */
46 * [RER] These are globals are wrong. They should be in DosDeviceStruct
47 * on a per port basis.
49 int commerror = 0, eventmask = 0;
51 struct DosDeviceStruct COM[MAX_PORTS];
52 struct DosDeviceStruct LPT[MAX_PORTS];
53 LPCVOID *unknown[MAX_PORTS];
55 void COMM_Init(void)
57 int x;
58 char option[10], temp[256], *btemp;
59 struct stat st;
61 for (x=0; x!=MAX_PORTS; x++) {
62 strcpy(option,"COMx");
63 option[3] = '1' + x;
64 option[4] = '\0';
66 PROFILE_GetWineIniString( "serialports", option, "*",
67 temp, sizeof(temp) );
68 if (!strcmp(temp, "*") || *temp == '\0')
69 COM[x].devicename = NULL;
70 else {
71 btemp = strchr(temp,',');
72 if (btemp != NULL) {
73 *btemp++ = '\0';
74 COM[x].baudrate = atoi(btemp);
75 } else {
76 COM[x].baudrate = -1;
78 stat(temp, &st);
79 if (!S_ISCHR(st.st_mode))
80 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
81 else
82 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
83 fprintf(stderr,"comm: can't malloc for device info!\n");
84 else {
85 COM[x].fd = 0;
86 strcpy(COM[x].devicename, temp);
88 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
91 strcpy(option, "LPTx");
92 option[3] = '1' + x;
93 option[4] = '\0';
95 PROFILE_GetWineIniString( "parallelports", option, "*",
96 temp, sizeof(temp) );
97 if (!strcmp(temp, "*") || *temp == '\0')
98 LPT[x].devicename = NULL;
99 else {
100 stat(temp, &st);
101 if (!S_ISCHR(st.st_mode))
102 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
103 else
104 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
105 fprintf(stderr,"comm: can't malloc for device info!\n");
106 else {
107 LPT[x].fd = 0;
108 strcpy(LPT[x].devicename, temp);
110 TRACE(comm, "%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 TRACE(comm, "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 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
173 commerror = 0;
175 if (!lstrncmpi32A(device,"COM",3)) {
176 port = device[3] - '0';
179 if (port-- == 0) {
180 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
181 commerror = IE_BADID;
184 if (!ValidCOMPort(port)) {
185 commerror = IE_BADID;
186 return -1;
189 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
191 if (!COM[port].fd) {
192 OpenComm(device, 0, 0);
194 lpdcb->Id = COM[port].fd;
196 if (!*(device+4))
197 return 0;
199 if (*(device+4) != ':')
200 return -1;
202 strcpy(temp,device+5);
203 ptr = strtok(temp, ", ");
205 if (COM[port].baudrate > 0)
206 lpdcb->BaudRate = COM[port].baudrate;
207 else
208 lpdcb->BaudRate = atoi(ptr);
209 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
211 ptr = strtok(NULL, ", ");
212 if (islower(*ptr))
213 *ptr = toupper(*ptr);
215 TRACE(comm,"parity (%c)\n", *ptr);
216 lpdcb->fParity = 1;
217 switch (*ptr) {
218 case 'N':
219 lpdcb->Parity = NOPARITY;
220 lpdcb->fParity = 0;
221 break;
222 case 'E':
223 lpdcb->Parity = EVENPARITY;
224 break;
225 case 'M':
226 lpdcb->Parity = MARKPARITY;
227 break;
228 case 'O':
229 lpdcb->Parity = ODDPARITY;
230 break;
231 default:
232 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
233 return -1;
236 ptr = strtok(NULL, ", ");
237 TRACE(comm, "charsize (%c)\n", *ptr);
238 lpdcb->ByteSize = *ptr - '0';
240 ptr = strtok(NULL, ", ");
241 TRACE(comm, "stopbits (%c)\n", *ptr);
242 switch (*ptr) {
243 case '1':
244 lpdcb->StopBits = ONESTOPBIT;
245 break;
246 case '2':
247 lpdcb->StopBits = TWOSTOPBITS;
248 break;
249 default:
250 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
251 return -1;
255 return 0;
258 /**************************************************************************
259 * BuildCommDCBA (KERNEL32.14)
261 BOOL32 WINAPI BuildCommDCB32A(LPCSTR device,LPDCB32 lpdcb)
263 return BuildCommDCBAndTimeouts32A(device,lpdcb,NULL);
266 /**************************************************************************
267 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
269 BOOL32 WINAPI BuildCommDCBAndTimeouts32A(LPCSTR device, LPDCB32 lpdcb,
270 LPCOMMTIMEOUTS lptimeouts)
272 int port;
273 char *ptr,*temp;
275 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
276 commerror = 0;
278 if (!lstrncmpi32A(device,"COM",3)) {
279 port=device[3]-'0';
280 if (port--==0) {
281 fprintf(stderr,"comm:BUG! COM0 can't exists!.\n");
282 return FALSE;
284 if (!ValidCOMPort(port))
285 return FALSE;
286 if (*(device+4)!=':')
287 return FALSE;
288 temp=(LPSTR)(device+5);
289 } else
290 temp=(LPSTR)device;
292 memset(lpdcb, 0, sizeof(DCB32)); /* initialize */
294 lpdcb->DCBlength = sizeof(DCB32);
295 if (strchr(temp,',')) { /* old style */
296 DCB16 dcb16;
297 BOOL16 ret;
298 char last=temp[strlen(temp)-1];
300 ret=BuildCommDCB16(device,&dcb16);
301 if (!ret)
302 return FALSE;
303 lpdcb->BaudRate = dcb16.BaudRate;
304 lpdcb->ByteSize = dcb16.ByteSize;
305 lpdcb->fBinary = dcb16.fBinary;
306 lpdcb->Parity = dcb16.Parity;
307 lpdcb->fParity = dcb16.fParity;
308 lpdcb->fNull = dcb16.fNull;
309 lpdcb->StopBits = dcb16.StopBits;
310 if (last == 'x') {
311 lpdcb->fInX = TRUE;
312 lpdcb->fOutX = TRUE;
313 lpdcb->fOutxCtsFlow = FALSE;
314 lpdcb->fOutxDsrFlow = FALSE;
315 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
316 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
317 } else if (last=='p') {
318 lpdcb->fInX = FALSE;
319 lpdcb->fOutX = FALSE;
320 lpdcb->fOutxCtsFlow = TRUE;
321 lpdcb->fOutxDsrFlow = TRUE;
322 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
323 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
324 } else {
325 lpdcb->fInX = FALSE;
326 lpdcb->fOutX = FALSE;
327 lpdcb->fOutxCtsFlow = FALSE;
328 lpdcb->fOutxDsrFlow = FALSE;
329 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
330 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
332 lpdcb->XonChar = dcb16.XonChar;
333 lpdcb->XoffChar = dcb16.XoffChar;
334 lpdcb->ErrorChar= dcb16.PeChar;
335 lpdcb->fErrorChar= dcb16.fPeChar;
336 lpdcb->EofChar = dcb16.EofChar;
337 lpdcb->EvtChar = dcb16.EvtChar;
338 lpdcb->XonLim = dcb16.XonLim;
339 lpdcb->XoffLim = dcb16.XoffLim;
340 return TRUE;
342 ptr=strtok(temp," ");
343 while (ptr) {
344 DWORD flag,x;
346 flag=0;
347 if (!strncmp("baud=",ptr,5)) {
348 if (!sscanf(ptr+5,"%ld",&x))
349 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
350 lpdcb->BaudRate = x;
351 flag=1;
353 if (!strncmp("stop=",ptr,5)) {
354 if (!sscanf(ptr+5,"%ld",&x))
355 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
356 lpdcb->StopBits = x;
357 flag=1;
359 if (!strncmp("data=",ptr,5)) {
360 if (!sscanf(ptr+5,"%ld",&x))
361 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
362 lpdcb->ByteSize = x;
363 flag=1;
365 if (!strncmp("parity=",ptr,7)) {
366 lpdcb->fParity = TRUE;
367 switch (ptr[8]) {
368 case 'N':case 'n':
369 lpdcb->fParity = FALSE;
370 lpdcb->Parity = NOPARITY;
371 break;
372 case 'E':case 'e':
373 lpdcb->Parity = EVENPARITY;
374 break;
375 case 'O':case 'o':
376 lpdcb->Parity = ODDPARITY;
377 break;
378 case 'M':case 'm':
379 lpdcb->Parity = MARKPARITY;
380 break;
382 flag=1;
384 if (!flag)
385 fprintf(stderr,"BuildCommDCB32A: Unhandled specifier '%s', please report.\n",ptr);
386 ptr=strtok(NULL," ");
388 if (lpdcb->BaudRate==110)
389 lpdcb->StopBits = 2;
390 return TRUE;
393 /**************************************************************************
394 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
396 BOOL32 WINAPI BuildCommDCBAndTimeouts32W( LPCWSTR devid, LPDCB32 lpdcb,
397 LPCOMMTIMEOUTS lptimeouts )
399 LPSTR devidA;
400 BOOL32 ret;
402 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
403 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
404 ret=BuildCommDCBAndTimeouts32A(devidA,lpdcb,lptimeouts);
405 HeapFree( GetProcessHeap(), 0, devidA );
406 return ret;
409 /**************************************************************************
410 * BuildCommDCBW (KERNEL32.17)
412 BOOL32 WINAPI BuildCommDCB32W(LPCWSTR devid,LPDCB32 lpdcb)
414 return BuildCommDCBAndTimeouts32W(devid,lpdcb,NULL);
417 /*****************************************************************************
418 * OpenComm (USER.200)
420 INT16 WINAPI OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
422 int port,fd;
424 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
425 commerror = 0;
427 if (!lstrncmpi32A(device,"COM",3)) {
428 port = device[3] - '0';
430 if (port-- == 0) {
431 fprintf(stderr, "comm: BUG ! COM0 doesn't exist !\n");
432 commerror = IE_BADID;
435 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
437 if (!ValidCOMPort(port)) {
438 commerror = IE_BADID;
439 return -1;
441 if (COM[port].fd) {
442 return COM[port].fd;
445 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
446 if (fd == -1) {
447 commerror = WinError();
448 return -1;
449 } else {
450 unknown[port] = SEGPTR_ALLOC(40);
451 bzero(unknown[port],40);
452 COM[port].fd = fd;
453 return fd;
456 else
457 if (!lstrncmpi32A(device,"LPT",3)) {
458 port = device[3] - '0';
460 if (!ValidLPTPort(port)) {
461 commerror = IE_BADID;
462 return -1;
464 if (LPT[port].fd) {
465 commerror = IE_OPEN;
466 return -1;
469 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
470 if (fd == -1) {
471 commerror = WinError();
472 return -1;
473 } else {
474 LPT[port].fd = fd;
475 return fd;
478 return 0;
481 /*****************************************************************************
482 * CloseComm (USER.207)
484 INT16 WINAPI CloseComm(INT16 fd)
486 int port;
487 TRACE(comm,"fd %d\n", fd);
488 if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
489 SEGPTR_FREE(unknown[port]);
490 COM[port].fd = 0; /* my adaptation of RER's fix */
491 } else {
492 commerror = IE_BADID;
493 return -1;
496 if (close(fd) == -1) {
497 commerror = WinError();
498 return -1;
499 } else {
500 commerror = 0;
501 return 0;
505 /*****************************************************************************
506 * SetCommBreak (USER.210)
508 INT16 WINAPI SetCommBreak16(INT16 fd)
510 struct DosDeviceStruct *ptr;
512 TRACE(comm,"fd=%d\n", fd);
513 if ((ptr = GetDeviceStruct(fd)) == NULL) {
514 commerror = IE_BADID;
515 return -1;
518 ptr->suspended = 1;
519 commerror = 0;
520 return 0;
523 /*****************************************************************************
524 * SetCommBreak (KERNEL32.449)
526 BOOL32 WINAPI SetCommBreak32(INT32 fd)
529 struct DosDeviceStruct *ptr;
531 TRACE(comm,"fd=%d\n", fd);
532 if ((ptr = GetDeviceStruct(fd)) == NULL) {
533 commerror = IE_BADID;
534 return FALSE;
537 ptr->suspended = 1;
538 commerror = 0;
539 return TRUE;
542 /*****************************************************************************
543 * ClearCommBreak (USER.211)
545 INT16 WINAPI ClearCommBreak16(INT16 fd)
547 struct DosDeviceStruct *ptr;
549 TRACE(comm,"fd=%d\n", fd);
550 if ((ptr = GetDeviceStruct(fd)) == NULL) {
551 commerror = IE_BADID;
552 return -1;
555 ptr->suspended = 0;
556 commerror = 0;
557 return 0;
560 /*****************************************************************************
561 * ClearCommBreak (KERNEL32.20)
563 BOOL32 WINAPI ClearCommBreak32(INT32 fd)
565 struct DosDeviceStruct *ptr;
567 TRACE(comm,"fd=%d\n", fd);
568 if ((ptr = GetDeviceStruct(fd)) == NULL) {
569 commerror = IE_BADID;
570 return FALSE;
573 ptr->suspended = 0;
574 commerror = 0;
575 return TRUE;
578 /*****************************************************************************
579 * EscapeCommFunction (USER.214)
581 LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
583 int max;
584 struct termios port;
586 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
587 if (tcgetattr(fd,&port) == -1) {
588 commerror=WinError();
589 return -1;
592 switch (nFunction) {
593 case RESETDEV:
594 break;
596 case GETMAXCOM:
597 for (max = MAX_PORTS;!COM[max].devicename;max--)
599 return max;
600 break;
602 case GETMAXLPT:
603 for (max = MAX_PORTS;!LPT[max].devicename;max--)
605 return 0x80 + max;
606 break;
608 #ifdef TIOCM_DTR
609 case CLRDTR:
610 port.c_cflag &= TIOCM_DTR;
611 break;
612 #endif
614 #ifdef TIOCM_RTS
615 case CLRRTS:
616 port.c_cflag &= TIOCM_RTS;
617 break;
618 #endif
620 #ifdef CRTSCTS
621 case SETDTR:
622 port.c_cflag |= CRTSCTS;
623 break;
625 case SETRTS:
626 port.c_cflag |= CRTSCTS;
627 break;
628 #endif
630 case SETXOFF:
631 port.c_iflag |= IXOFF;
632 break;
634 case SETXON:
635 port.c_iflag |= IXON;
636 break;
638 default:
639 fprintf(stderr,
640 "EscapeCommFunction fd: %d, unknown function: %d\n",
641 fd, nFunction);
642 break;
645 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
646 commerror = WinError();
647 return -1;
648 } else {
649 commerror = 0;
650 return 0;
654 /*****************************************************************************
655 * EscapeCommFunction (KERNEL32.214)
657 BOOL32 WINAPI EscapeCommFunction32(INT32 fd,UINT32 nFunction)
659 struct termios port;
660 struct DosDeviceStruct *ptr;
662 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
663 if (tcgetattr(fd,&port) == -1) {
664 commerror=WinError();
665 return FALSE;
667 if ((ptr = GetDeviceStruct(fd)) == NULL) {
668 commerror = IE_BADID;
669 return FALSE;
672 switch (nFunction) {
673 case RESETDEV:
674 break;
676 #ifdef TIOCM_DTR
677 case CLRDTR:
678 port.c_cflag &= TIOCM_DTR;
679 break;
680 #endif
682 #ifdef TIOCM_RTS
683 case CLRRTS:
684 port.c_cflag &= TIOCM_RTS;
685 break;
686 #endif
688 #ifdef CRTSCTS
689 case SETDTR:
690 port.c_cflag |= CRTSCTS;
691 break;
693 case SETRTS:
694 port.c_cflag |= CRTSCTS;
695 break;
696 #endif
698 case SETXOFF:
699 port.c_iflag |= IXOFF;
700 break;
702 case SETXON:
703 port.c_iflag |= IXON;
704 break;
705 case SETBREAK:
706 ptr->suspended = 1;
707 break;
708 case CLRBREAK:
709 ptr->suspended = 0;
710 break;
711 default:
712 fprintf(stderr,
713 "EscapeCommFunction32 fd: %d, unknown function: %d\n",
714 fd, nFunction);
715 break;
718 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
719 commerror = WinError();
720 return FALSE;
721 } else {
722 commerror = 0;
723 return TRUE;
727 /*****************************************************************************
728 * FlushComm (USER.215)
730 INT16 WINAPI FlushComm(INT16 fd,INT16 fnQueue)
732 int queue;
734 TRACE(comm,"fd=%d, queue=%d\n", fd, fnQueue);
735 switch (fnQueue) {
736 case 0: queue = TCOFLUSH;
737 break;
738 case 1: queue = TCIFLUSH;
739 break;
740 default:fprintf(stderr,
741 "FlushComm fd: %d, UNKNOWN queue: %d\n",
742 fd, fnQueue);
743 return -1;
745 if (tcflush(fd, queue)) {
746 commerror = WinError();
747 return -1;
748 } else {
749 commerror = 0;
750 return 0;
754 /********************************************************************
755 * PurgeComm (KERNEL32.557)
757 BOOL32 WINAPI PurgeComm( HANDLE32 hFile, DWORD flags)
759 FIXME(comm, "(%08x %08lx) unimplemented stub\n",
760 hFile, flags);
761 return 0;
764 /********************************************************************
765 * GetCommError (USER.203)
767 INT16 WINAPI GetCommError(INT16 fd,LPCOMSTAT lpStat)
769 int temperror;
770 unsigned long cnt;
771 int rc;
773 if (lpStat) {
774 lpStat->status = 0;
776 rc = ioctl(fd, TIOCOUTQ, &cnt);
777 if (rc) fprintf(stderr, "Error !\n");
778 lpStat->cbOutQue = cnt;
780 rc = ioctl(fd, TIOCINQ, &cnt);
781 if (rc) fprintf(stderr, "Error !\n");
782 lpStat->cbInQue = cnt;
784 TRACE(comm, "fd %d, error %d, lpStat %d %d %d\n",
785 fd, commerror, lpStat->status, lpStat->cbInQue,
786 lpStat->cbOutQue);
788 else
789 TRACE(comm, "fd %d, error %d, lpStat NULL\n",
790 fd, commerror);
793 * [RER] I have no idea what the following is trying to accomplish.
794 * [RER] It is certainly not what the reference manual suggests.
796 temperror = commerror;
797 commerror = 0;
798 return(temperror);
801 /*****************************************************************************
802 * ClearCommError (KERNEL32.21)
804 BOOL32 WINAPI ClearCommError(INT32 fd,LPDWORD errors,LPCOMSTAT lpStat)
806 int temperror;
808 TRACE(comm, "fd %d (current error %d)\n",
809 fd, commerror);
810 temperror = commerror;
811 commerror = 0;
812 return TRUE;
815 /*****************************************************************************
816 * SetCommEventMask (USER.208)
818 SEGPTR WINAPI SetCommEventMask(INT16 fd,UINT16 fuEvtMask)
820 unsigned char *stol;
821 int act;
822 int repid;
823 unsigned int mstat;
824 TRACE(comm,"fd %d,mask %d\n",fd,fuEvtMask);
825 eventmask |= fuEvtMask;
826 if ((act = GetCommPort(fd)) == -1) {
827 WARN(comm," fd %d not comm port\n",act);
828 return NULL;}
829 stol = unknown[act];
830 stol += msr;
831 repid = ioctl(fd,TIOCMGET,&mstat);
832 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
833 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
834 else {*stol &=0x7f;}
835 TRACE(comm," modem dcd construct %x\n",*stol);
836 return SEGPTR_GET(unknown[act]);
839 /*****************************************************************************
840 * GetCommEventMask (USER.209)
842 UINT16 WINAPI GetCommEventMask(INT16 fd,UINT16 fnEvtClear)
844 int events = 0;
846 TRACE(comm, "fd %d, mask %d\n", fd, fnEvtClear);
849 * Determine if any characters are available
851 if (fnEvtClear & EV_RXCHAR)
853 int rc;
854 unsigned long cnt;
856 rc = ioctl(fd, TIOCINQ, &cnt);
857 if (cnt) events |= EV_RXCHAR;
859 TRACE(comm, "rxchar %ld\n", cnt);
863 * There are other events that need to be checked for
865 /* TODO */
867 TRACE(comm, "return events %d\n", events);
868 return events;
871 * [RER] The following was gibberish
873 #if 0
874 tempmask = eventmask;
875 eventmask &= ~fnEvtClear;
876 return eventmask;
877 #endif
880 /*****************************************************************************
881 * SetupComm (KERNEL32.676)
883 BOOL32 WINAPI SetupComm( HANDLE32 hFile, DWORD insize, DWORD outsize)
885 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
886 return FALSE;
889 /*****************************************************************************
890 * GetCommMask (KERNEL32.156)
892 BOOL32 WINAPI GetCommMask(INT32 fd,LPDWORD evtmask)
894 TRACE(comm, "fd %d, mask %p\n", fd, evtmask);
895 *evtmask = eventmask;
896 return TRUE;
899 /*****************************************************************************
900 * SetCommMask (KERNEL32.451)
902 BOOL32 WINAPI SetCommMask(INT32 fd,DWORD evtmask)
904 TRACE(comm, "fd %d, mask %lx\n", fd, evtmask);
905 eventmask = evtmask;
906 return TRUE;
909 /*****************************************************************************
910 * SetCommState16 (USER.201)
912 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
914 struct termios port;
915 struct DosDeviceStruct *ptr;
917 TRACE(comm, "fd %d, ptr %p\n", lpdcb->Id, lpdcb);
918 if (tcgetattr(lpdcb->Id, &port) == -1) {
919 commerror = WinError();
920 return -1;
923 port.c_cc[VMIN] = 0;
924 port.c_cc[VTIME] = 1;
926 #ifdef IMAXBEL
927 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
928 #else
929 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
930 #endif
931 port.c_iflag |= (IGNBRK);
933 port.c_oflag &= ~(OPOST);
935 port.c_cflag &= ~(HUPCL);
936 port.c_cflag |= CLOCAL | CREAD;
938 port.c_lflag &= ~(ICANON|ECHO|ISIG);
939 port.c_lflag |= NOFLSH;
941 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
942 commerror = IE_BADID;
943 return -1;
945 if (ptr->baudrate > 0)
946 lpdcb->BaudRate = ptr->baudrate;
947 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
948 #ifdef CBAUD
949 port.c_cflag &= ~CBAUD;
950 switch (lpdcb->BaudRate) {
951 case 110:
952 case CBR_110:
953 port.c_cflag |= B110;
954 break;
955 case 300:
956 case CBR_300:
957 port.c_cflag |= B300;
958 break;
959 case 600:
960 case CBR_600:
961 port.c_cflag |= B600;
962 break;
963 case 1200:
964 case CBR_1200:
965 port.c_cflag |= B1200;
966 break;
967 case 2400:
968 case CBR_2400:
969 port.c_cflag |= B2400;
970 break;
971 case 4800:
972 case CBR_4800:
973 port.c_cflag |= B4800;
974 break;
975 case 9600:
976 case CBR_9600:
977 port.c_cflag |= B9600;
978 break;
979 case 19200:
980 case CBR_19200:
981 port.c_cflag |= B19200;
982 break;
983 case 38400:
984 case CBR_38400:
985 port.c_cflag |= B38400;
986 break;
987 case 57600:
988 port.c_cflag |= B57600;
989 break;
990 case 57601:
991 port.c_cflag |= B115200;
992 break;
993 default:
994 commerror = IE_BAUDRATE;
995 return -1;
997 #elif !defined(__EMX__)
998 switch (lpdcb->BaudRate) {
999 case 110:
1000 case CBR_110:
1001 port.c_ospeed = B110;
1002 break;
1003 case 300:
1004 case CBR_300:
1005 port.c_ospeed = B300;
1006 break;
1007 case 600:
1008 case CBR_600:
1009 port.c_ospeed = B600;
1010 break;
1011 case 1200:
1012 case CBR_1200:
1013 port.c_ospeed = B1200;
1014 break;
1015 case 2400:
1016 case CBR_2400:
1017 port.c_ospeed = B2400;
1018 break;
1019 case 4800:
1020 case CBR_4800:
1021 port.c_ospeed = B4800;
1022 break;
1023 case 9600:
1024 case CBR_9600:
1025 port.c_ospeed = B9600;
1026 break;
1027 case 19200:
1028 case CBR_19200:
1029 port.c_ospeed = B19200;
1030 break;
1031 case 38400:
1032 case CBR_38400:
1033 port.c_ospeed = B38400;
1034 break;
1035 default:
1036 commerror = IE_BAUDRATE;
1037 return -1;
1039 port.c_ispeed = port.c_ospeed;
1040 #endif
1041 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1042 port.c_cflag &= ~CSIZE;
1043 switch (lpdcb->ByteSize) {
1044 case 5:
1045 port.c_cflag |= CS5;
1046 break;
1047 case 6:
1048 port.c_cflag |= CS6;
1049 break;
1050 case 7:
1051 port.c_cflag |= CS7;
1052 break;
1053 case 8:
1054 port.c_cflag |= CS8;
1055 break;
1056 default:
1057 commerror = IE_BYTESIZE;
1058 return -1;
1061 TRACE(comm,"parity %d\n",lpdcb->Parity);
1062 port.c_cflag &= ~(PARENB | PARODD);
1063 if (lpdcb->fParity)
1064 switch (lpdcb->Parity) {
1065 case NOPARITY:
1066 port.c_iflag &= ~INPCK;
1067 break;
1068 case ODDPARITY:
1069 port.c_cflag |= (PARENB | PARODD);
1070 port.c_iflag |= INPCK;
1071 break;
1072 case EVENPARITY:
1073 port.c_cflag |= PARENB;
1074 port.c_iflag |= INPCK;
1075 break;
1076 default:
1077 commerror = IE_BYTESIZE;
1078 return -1;
1082 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1084 switch (lpdcb->StopBits) {
1085 case ONESTOPBIT:
1086 port.c_cflag &= ~CSTOPB;
1087 break;
1088 case TWOSTOPBITS:
1089 port.c_cflag |= CSTOPB;
1090 break;
1091 default:
1092 commerror = IE_BYTESIZE;
1093 return -1;
1095 #ifdef CRTSCTS
1097 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1098 port.c_cflag |= CRTSCTS;
1100 if (lpdcb->fDtrDisable)
1101 port.c_cflag &= ~CRTSCTS;
1102 #endif
1103 if (lpdcb->fInX)
1104 port.c_iflag |= IXON;
1105 else
1106 port.c_iflag &= ~IXON;
1107 if (lpdcb->fOutX)
1108 port.c_iflag |= IXOFF;
1109 else
1110 port.c_iflag &= ~IXOFF;
1112 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
1113 commerror = WinError();
1114 return FALSE;
1115 } else {
1116 commerror = 0;
1117 return 0;
1121 /*****************************************************************************
1122 * SetCommState32 (KERNEL32.452)
1124 BOOL32 WINAPI SetCommState32(INT32 fd,LPDCB32 lpdcb)
1126 struct termios port;
1127 struct DosDeviceStruct *ptr;
1129 TRACE(comm,"fd %d, ptr %p\n",fd,lpdcb);
1130 if (tcgetattr(fd,&port) == -1) {
1131 commerror = WinError();
1132 return FALSE;
1135 port.c_cc[VMIN] = 0;
1136 port.c_cc[VTIME] = 1;
1138 #ifdef IMAXBEL
1139 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1140 #else
1141 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1142 #endif
1143 port.c_iflag |= (IGNBRK);
1145 port.c_oflag &= ~(OPOST);
1147 port.c_cflag &= ~(HUPCL);
1148 port.c_cflag |= CLOCAL | CREAD;
1150 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1151 port.c_lflag |= NOFLSH;
1153 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1154 commerror = IE_BADID;
1155 return FALSE;
1157 if (ptr->baudrate > 0)
1158 lpdcb->BaudRate = ptr->baudrate;
1159 TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1160 #ifdef CBAUD
1161 port.c_cflag &= ~CBAUD;
1162 switch (lpdcb->BaudRate) {
1163 case 110:
1164 case CBR_110:
1165 port.c_cflag |= B110;
1166 break;
1167 case 300:
1168 case CBR_300:
1169 port.c_cflag |= B300;
1170 break;
1171 case 600:
1172 case CBR_600:
1173 port.c_cflag |= B600;
1174 break;
1175 case 1200:
1176 case CBR_1200:
1177 port.c_cflag |= B1200;
1178 break;
1179 case 2400:
1180 case CBR_2400:
1181 port.c_cflag |= B2400;
1182 break;
1183 case 4800:
1184 case CBR_4800:
1185 port.c_cflag |= B4800;
1186 break;
1187 case 9600:
1188 case CBR_9600:
1189 port.c_cflag |= B9600;
1190 break;
1191 case 19200:
1192 case CBR_19200:
1193 port.c_cflag |= B19200;
1194 break;
1195 case 38400:
1196 case CBR_38400:
1197 port.c_cflag |= B38400;
1198 break;
1199 default:
1200 commerror = IE_BAUDRATE;
1201 return FALSE;
1203 #elif !defined(__EMX__)
1204 switch (lpdcb->BaudRate) {
1205 case 110:
1206 case CBR_110:
1207 port.c_ospeed = B110;
1208 break;
1209 case 300:
1210 case CBR_300:
1211 port.c_ospeed = B300;
1212 break;
1213 case 600:
1214 case CBR_600:
1215 port.c_ospeed = B600;
1216 break;
1217 case 1200:
1218 case CBR_1200:
1219 port.c_ospeed = B1200;
1220 break;
1221 case 2400:
1222 case CBR_2400:
1223 port.c_ospeed = B2400;
1224 break;
1225 case 4800:
1226 case CBR_4800:
1227 port.c_ospeed = B4800;
1228 break;
1229 case 9600:
1230 case CBR_9600:
1231 port.c_ospeed = B9600;
1232 break;
1233 case 19200:
1234 case CBR_19200:
1235 port.c_ospeed = B19200;
1236 break;
1237 case 38400:
1238 case CBR_38400:
1239 port.c_ospeed = B38400;
1240 break;
1241 default:
1242 commerror = IE_BAUDRATE;
1243 return FALSE;
1245 port.c_ispeed = port.c_ospeed;
1246 #endif
1247 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1248 port.c_cflag &= ~CSIZE;
1249 switch (lpdcb->ByteSize) {
1250 case 5:
1251 port.c_cflag |= CS5;
1252 break;
1253 case 6:
1254 port.c_cflag |= CS6;
1255 break;
1256 case 7:
1257 port.c_cflag |= CS7;
1258 break;
1259 case 8:
1260 port.c_cflag |= CS8;
1261 break;
1262 default:
1263 commerror = IE_BYTESIZE;
1264 return FALSE;
1267 TRACE(comm,"parity %d\n",lpdcb->Parity);
1268 port.c_cflag &= ~(PARENB | PARODD);
1269 if (lpdcb->fParity)
1270 switch (lpdcb->Parity) {
1271 case NOPARITY:
1272 port.c_iflag &= ~INPCK;
1273 break;
1274 case ODDPARITY:
1275 port.c_cflag |= (PARENB | PARODD);
1276 port.c_iflag |= INPCK;
1277 break;
1278 case EVENPARITY:
1279 port.c_cflag |= PARENB;
1280 port.c_iflag |= INPCK;
1281 break;
1282 default:
1283 commerror = IE_BYTESIZE;
1284 return FALSE;
1288 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1289 switch (lpdcb->StopBits) {
1290 case ONESTOPBIT:
1291 port.c_cflag &= ~CSTOPB;
1292 break;
1293 case TWOSTOPBITS:
1294 port.c_cflag |= CSTOPB;
1295 break;
1296 default:
1297 commerror = IE_BYTESIZE;
1298 return FALSE;
1300 #ifdef CRTSCTS
1301 if ( lpdcb->fOutxCtsFlow ||
1302 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1303 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1305 port.c_cflag |= CRTSCTS;
1306 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1307 port.c_cflag &= ~CRTSCTS;
1309 #endif
1310 if (lpdcb->fInX)
1311 port.c_iflag |= IXON;
1312 else
1313 port.c_iflag &= ~IXON;
1314 if (lpdcb->fOutX)
1315 port.c_iflag |= IXOFF;
1316 else
1317 port.c_iflag &= ~IXOFF;
1319 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1320 commerror = WinError();
1321 return FALSE;
1322 } else {
1323 commerror = 0;
1324 return TRUE;
1329 /*****************************************************************************
1330 * GetCommState (USER.202)
1332 INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
1334 struct termios port;
1336 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1337 if (tcgetattr(fd, &port) == -1) {
1338 commerror = WinError();
1339 return -1;
1341 lpdcb->Id = fd;
1342 #ifndef __EMX__
1343 #ifdef CBAUD
1344 switch (port.c_cflag & CBAUD) {
1345 #else
1346 switch (port.c_ospeed) {
1347 #endif
1348 case B110:
1349 lpdcb->BaudRate = 110;
1350 break;
1351 case B300:
1352 lpdcb->BaudRate = 300;
1353 break;
1354 case B600:
1355 lpdcb->BaudRate = 600;
1356 break;
1357 case B1200:
1358 lpdcb->BaudRate = 1200;
1359 break;
1360 case B2400:
1361 lpdcb->BaudRate = 2400;
1362 break;
1363 case B4800:
1364 lpdcb->BaudRate = 4800;
1365 break;
1366 case B9600:
1367 lpdcb->BaudRate = 9600;
1368 break;
1369 case B19200:
1370 lpdcb->BaudRate = 19200;
1371 break;
1372 case B38400:
1373 lpdcb->BaudRate = 38400;
1374 break;
1375 case B57600:
1376 lpdcb->BaudRate = 57600;
1377 break;
1378 case B115200:
1379 lpdcb->BaudRate = 57601;
1380 break;
1382 #endif
1383 switch (port.c_cflag & CSIZE) {
1384 case CS5:
1385 lpdcb->ByteSize = 5;
1386 break;
1387 case CS6:
1388 lpdcb->ByteSize = 6;
1389 break;
1390 case CS7:
1391 lpdcb->ByteSize = 7;
1392 break;
1393 case CS8:
1394 lpdcb->ByteSize = 8;
1395 break;
1398 switch (port.c_cflag & ~(PARENB | PARODD)) {
1399 case 0:
1400 lpdcb->fParity = NOPARITY;
1401 break;
1402 case PARENB:
1403 lpdcb->fParity = EVENPARITY;
1404 break;
1405 case (PARENB | PARODD):
1406 lpdcb->fParity = ODDPARITY;
1407 break;
1410 if (port.c_cflag & CSTOPB)
1411 lpdcb->StopBits = TWOSTOPBITS;
1412 else
1413 lpdcb->StopBits = ONESTOPBIT;
1415 lpdcb->RlsTimeout = 50;
1416 lpdcb->CtsTimeout = 50;
1417 lpdcb->DsrTimeout = 50;
1418 lpdcb->fNull = 0;
1419 lpdcb->fChEvt = 0;
1420 lpdcb->fBinary = 1;
1421 lpdcb->fDtrDisable = 0;
1423 #ifdef CRTSCTS
1425 if (port.c_cflag & CRTSCTS) {
1426 lpdcb->fDtrflow = 1;
1427 lpdcb->fRtsflow = 1;
1428 lpdcb->fOutxCtsFlow = 1;
1429 lpdcb->fOutxDsrFlow = 1;
1430 } else
1431 #endif
1432 lpdcb->fDtrDisable = 1;
1434 if (port.c_iflag & IXON)
1435 lpdcb->fInX = 1;
1436 else
1437 lpdcb->fInX = 0;
1439 if (port.c_iflag & IXOFF)
1440 lpdcb->fOutX = 1;
1441 else
1442 lpdcb->fOutX = 0;
1444 lpdcb->XonChar =
1445 lpdcb->XoffChar =
1447 lpdcb->XonLim = 10;
1448 lpdcb->XoffLim = 10;
1450 commerror = 0;
1451 return 0;
1454 /*****************************************************************************
1455 * GetCommState (KERNEL32.159)
1457 BOOL32 WINAPI GetCommState32(INT32 fd, LPDCB32 lpdcb)
1459 struct termios port;
1461 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1462 if (GetDeviceStruct(fd) == NULL) return FALSE;
1463 if (tcgetattr(fd, &port) == -1) {
1464 commerror = WinError();
1465 return FALSE;
1467 #ifndef __EMX__
1468 #ifdef CBAUD
1469 switch (port.c_cflag & CBAUD) {
1470 #else
1471 switch (port.c_ospeed) {
1472 #endif
1473 case B110:
1474 lpdcb->BaudRate = 110;
1475 break;
1476 case B300:
1477 lpdcb->BaudRate = 300;
1478 break;
1479 case B600:
1480 lpdcb->BaudRate = 600;
1481 break;
1482 case B1200:
1483 lpdcb->BaudRate = 1200;
1484 break;
1485 case B2400:
1486 lpdcb->BaudRate = 2400;
1487 break;
1488 case B4800:
1489 lpdcb->BaudRate = 4800;
1490 break;
1491 case B9600:
1492 lpdcb->BaudRate = 9600;
1493 break;
1494 case B19200:
1495 lpdcb->BaudRate = 19200;
1496 break;
1497 case B38400:
1498 lpdcb->BaudRate = 38400;
1499 break;
1501 #endif
1502 switch (port.c_cflag & CSIZE) {
1503 case CS5:
1504 lpdcb->ByteSize = 5;
1505 break;
1506 case CS6:
1507 lpdcb->ByteSize = 6;
1508 break;
1509 case CS7:
1510 lpdcb->ByteSize = 7;
1511 break;
1512 case CS8:
1513 lpdcb->ByteSize = 8;
1514 break;
1517 switch (port.c_cflag & ~(PARENB | PARODD)) {
1518 case 0:
1519 lpdcb->fParity = NOPARITY;
1520 break;
1521 case PARENB:
1522 lpdcb->fParity = EVENPARITY;
1523 break;
1524 case (PARENB | PARODD):
1525 lpdcb->fParity = ODDPARITY;
1526 break;
1529 if (port.c_cflag & CSTOPB)
1530 lpdcb->StopBits = TWOSTOPBITS;
1531 else
1532 lpdcb->StopBits = ONESTOPBIT;
1534 lpdcb->fNull = 0;
1535 lpdcb->fBinary = 1;
1537 #ifdef CRTSCTS
1539 if (port.c_cflag & CRTSCTS) {
1540 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1541 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1542 lpdcb->fOutxCtsFlow = 1;
1543 lpdcb->fOutxDsrFlow = 1;
1544 } else
1545 #endif
1547 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1548 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1550 if (port.c_iflag & IXON)
1551 lpdcb->fInX = 1;
1552 else
1553 lpdcb->fInX = 0;
1555 if (port.c_iflag & IXOFF)
1556 lpdcb->fOutX = 1;
1557 else
1558 lpdcb->fOutX = 0;
1560 lpdcb->XonChar =
1561 lpdcb->XoffChar =
1563 lpdcb->XonLim = 10;
1564 lpdcb->XoffLim = 10;
1566 commerror = 0;
1567 return TRUE;
1570 /*****************************************************************************
1571 * TransmitCommChar (USER.206)
1573 INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
1575 struct DosDeviceStruct *ptr;
1577 TRACE(comm, "fd %d, data %d \n", fd, chTransmit);
1578 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1579 commerror = IE_BADID;
1580 return -1;
1583 if (ptr->suspended) {
1584 commerror = IE_HARDWARE;
1585 return -1;
1588 if (write(fd, (void *) &chTransmit, 1) == -1) {
1589 commerror = WinError();
1590 return -1;
1591 } else {
1592 commerror = 0;
1593 return 0;
1597 /*****************************************************************************
1598 * TransmitCommChar (KERNEL32.535)
1600 BOOL32 WINAPI TransmitCommChar32(INT32 fd,CHAR chTransmit)
1602 struct DosDeviceStruct *ptr;
1604 TRACE(comm,"(%d,'%c')\n",fd,chTransmit);
1605 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1606 commerror = IE_BADID;
1607 return FALSE;
1610 if (ptr->suspended) {
1611 commerror = IE_HARDWARE;
1612 return FALSE;
1614 if (write(fd, (void *) &chTransmit, 1) == -1) {
1615 commerror = WinError();
1616 return FALSE;
1617 } else {
1618 commerror = 0;
1619 return TRUE;
1623 /*****************************************************************************
1624 * UngetCommChar (USER.212)
1626 INT16 WINAPI UngetCommChar(INT16 fd,CHAR chUnget)
1628 struct DosDeviceStruct *ptr;
1630 TRACE(comm,"fd %d (char %d)\n", fd, chUnget);
1631 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1632 commerror = IE_BADID;
1633 return -1;
1636 if (ptr->suspended) {
1637 commerror = IE_HARDWARE;
1638 return -1;
1641 ptr->unget = 1;
1642 ptr->unget_byte = chUnget;
1643 commerror = 0;
1644 return 0;
1647 /*****************************************************************************
1648 * ReadComm (USER.204)
1650 INT16 WINAPI ReadComm(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1652 int status, length;
1653 struct DosDeviceStruct *ptr;
1655 TRACE(comm, "fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1656 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1657 commerror = IE_BADID;
1658 return -1;
1661 if (ptr->suspended) {
1662 commerror = IE_HARDWARE;
1663 return -1;
1666 if (ptr->unget) {
1667 *lpvBuf = ptr->unget_byte;
1668 lpvBuf++;
1669 ptr->unget = 0;
1671 length = 1;
1672 } else
1673 length = 0;
1675 status = read(fd, (void *) lpvBuf, cbRead);
1677 if (status == -1) {
1678 if (errno != EAGAIN) {
1679 commerror = WinError();
1680 return -1 - length;
1681 } else {
1682 commerror = 0;
1683 return length;
1685 } else {
1686 TRACE(comm,"%*s\n", length+status, lpvBuf);
1687 commerror = 0;
1688 return length + status;
1692 /*****************************************************************************
1693 * WriteComm (USER.205)
1695 INT16 WINAPI WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1697 int length;
1698 struct DosDeviceStruct *ptr;
1700 TRACE(comm,"fd %d, ptr %p, length %d\n",
1701 fd, lpvBuf, cbWrite);
1702 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1703 commerror = IE_BADID;
1704 return -1;
1707 if (ptr->suspended) {
1708 commerror = IE_HARDWARE;
1709 return -1;
1712 TRACE(comm,"%*s\n", cbWrite, lpvBuf );
1713 length = write(fd, (void *) lpvBuf, cbWrite);
1715 if (length == -1) {
1716 commerror = WinError();
1717 return -1;
1718 } else {
1719 commerror = 0;
1720 return length;
1725 /*****************************************************************************
1726 * GetCommTimeouts (KERNEL32.160)
1728 BOOL32 WINAPI GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts)
1730 fprintf(stderr,"GetCommTimeouts(%x,%p), empty stub.\n",
1731 fd,lptimeouts
1733 return TRUE;
1736 /*****************************************************************************
1737 * SetCommTimeouts (KERNEL32.453)
1739 BOOL32 WINAPI SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
1740 fprintf(stderr,"SetCommTimeouts(%x,%p), empty stub.\n",
1741 fd,lptimeouts
1743 return TRUE;
1746 /***********************************************************************
1747 * EnableCommNotification (USER.246)
1749 BOOL16 WINAPI EnableCommNotification( INT16 fd, HWND16 hwnd,
1750 INT16 cbWriteNotify, INT16 cbOutQueue )
1752 fprintf(stderr, "EnableCommNotification(%d, %x, %d, %d), empty stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
1753 return TRUE;