Implemented flag FILE_FLAG_DELETE_ON_CLOSE.
[wine/multimedia.git] / misc / comm.c
blobcb5c8bc585b544831e2cb1b3908e569da29ad9aa
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>
17 * July 6, 1998. Fixes and comments by Valentijn Sessink
18 * <vsessink@ic.uva.nl> [V]
19 * I only quick-fixed an error for the output buffers. The thing is this: if a
20 * WinApp starts using serial ports, it calls OpenComm, asking it to open two
21 * buffers, cbInQueue and cbOutQueue size, to hold data to/from the serial
22 * ports. Wine OpenComm only returns "OK". Now the kernel buffer size for
23 * serial communication is only 4096 bytes large. Error: (App asks for
24 * a 104,000 bytes size buffer, Wine returns "OK", App asks "How many char's
25 * are in the buffer", Wine returns "4000" and App thinks "OK, another
26 * 100,000 chars left, good!")
27 * The solution below is a bad but working quickfix for the transmit buffer:
28 * the cbInQueue is saved in a variable; when the program asks how many chars
29 * there are in the buffer, GetCommError returns # in buffer PLUS
30 * the additional (cbOutQeueu - 4096), which leaves the application thinking
31 * "wow, almost full".
32 * Sorry for the rather chatty explanation - but I think comm.c needs to be
33 * redefined with real working buffers make it work; maybe these comments are
34 * of help.
35 * Oktober 98, Rein Klazes [RHK]
36 * A program that wants to monitor the modem status line (RLSD/DCD) may
37 * poll the modem status register in the commMask structure. I update the bit
38 * in GetCommError, waiting for an implementation of communication events.
42 #include "config.h"
44 #include <stdlib.h>
45 #include <termios.h>
46 #include <fcntl.h>
47 #include <string.h>
48 #ifdef HAVE_STRINGS_H
49 # include <strings.h>
50 #endif
51 #include <errno.h>
52 #include <ctype.h>
53 #include <sys/stat.h>
54 #ifdef HAVE_SYS_FILIO_H
55 # include <sys/filio.h>
56 #endif
57 #include <sys/ioctl.h>
58 #include <unistd.h>
60 #include "wine/winuser16.h"
61 #include "comm.h"
62 #ifdef HAVE_SYS_MODEM_H
63 # include <sys/modem.h>
64 #endif
65 #ifdef HAVE_SYS_STRTIO_H
66 # include <sys/strtio.h>
67 #endif
68 #include "heap.h"
69 #include "options.h"
70 #include "debug.h"
72 #ifndef TIOCINQ
73 #define TIOCINQ FIONREAD
74 #endif
75 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
77 * [RER] These are globals are wrong. They should be in DosDeviceStruct
78 * on a per port basis.
80 int commerror = 0, eventmask = 0;
83 * [V] If above globals are wrong, the one below will be wrong as well. It
84 * should probably be in the DosDeviceStruct on per port basis too.
86 int iGlobalOutQueueFiller;
88 #define SERIAL_XMIT_SIZE 4096
90 struct DosDeviceStruct COM[MAX_PORTS];
91 struct DosDeviceStruct LPT[MAX_PORTS];
92 /* pointers to unknown(==undocumented) comm structure */
93 LPCVOID *unknown[MAX_PORTS];
94 /* save terminal states */
95 static struct termios m_stat[MAX_PORTS];
97 void COMM_Init(void)
99 int x;
100 char option[10], temp[256], *btemp;
101 struct stat st;
103 for (x=0; x!=MAX_PORTS; x++) {
104 strcpy(option,"COMx");
105 option[3] = '1' + x;
106 option[4] = '\0';
108 PROFILE_GetWineIniString( "serialports", option, "*",
109 temp, sizeof(temp) );
110 if (!strcmp(temp, "*") || *temp == '\0')
111 COM[x].devicename = NULL;
112 else {
113 btemp = strchr(temp,',');
114 if (btemp != NULL) {
115 *btemp++ = '\0';
116 COM[x].baudrate = atoi(btemp);
117 } else {
118 COM[x].baudrate = -1;
120 stat(temp, &st);
121 if (!S_ISCHR(st.st_mode))
122 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
123 else
124 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
125 WARN(comm,"Can't malloc for device info!\n");
126 else {
127 COM[x].fd = 0;
128 strcpy(COM[x].devicename, temp);
130 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
133 strcpy(option, "LPTx");
134 option[3] = '1' + x;
135 option[4] = '\0';
137 PROFILE_GetWineIniString( "parallelports", option, "*",
138 temp, sizeof(temp) );
139 if (!strcmp(temp, "*") || *temp == '\0')
140 LPT[x].devicename = NULL;
141 else {
142 stat(temp, &st);
143 if (!S_ISCHR(st.st_mode))
144 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
145 else
146 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
147 WARN(comm,"Can't malloc for device info!\n");
148 else {
149 LPT[x].fd = 0;
150 strcpy(LPT[x].devicename, temp);
152 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
159 struct DosDeviceStruct *GetDeviceStruct(int fd)
161 int x;
163 for (x=0; x!=MAX_PORTS; x++) {
164 if (COM[x].fd == fd)
165 return &COM[x];
166 if (LPT[x].fd == fd)
167 return &LPT[x];
170 return NULL;
173 int GetCommPort(int fd)
175 int x;
177 for (x=0; x<MAX_PORTS; x++) {
178 if (COM[x].fd == fd)
179 return x;
182 return -1;
185 int ValidCOMPort(int x)
187 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
190 int ValidLPTPort(int x)
192 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
195 int WinError(void)
197 TRACE(comm, "errno = %d\n", errno);
198 switch (errno) {
199 default:
200 return CE_IOE;
204 /**************************************************************************
205 * BuildCommDCB (USER.213)
207 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
209 /* "COM1:9600,n,8,1" */
210 /* 012345 */
211 int port;
212 char *ptr, temp[256];
214 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
215 commerror = 0;
217 if (!lstrncmpi32A(device,"COM",3)) {
218 port = device[3] - '0';
221 if (port-- == 0) {
222 ERR(comm, "BUG ! COM0 can't exists!.\n");
223 commerror = IE_BADID;
226 if (!ValidCOMPort(port)) {
227 commerror = IE_BADID;
228 return -1;
231 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
233 if (!COM[port].fd) {
234 OpenComm(device, 0, 0);
236 lpdcb->Id = COM[port].fd;
238 if (!*(device+4))
239 return 0;
241 if (*(device+4) != ':')
242 return -1;
244 strcpy(temp,device+5);
245 ptr = strtok(temp, ", ");
247 if (COM[port].baudrate > 0)
248 lpdcb->BaudRate = COM[port].baudrate;
249 else
250 lpdcb->BaudRate = atoi(ptr);
251 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
253 ptr = strtok(NULL, ", ");
254 if (islower(*ptr))
255 *ptr = toupper(*ptr);
257 TRACE(comm,"parity (%c)\n", *ptr);
258 lpdcb->fParity = TRUE;
259 switch (*ptr) {
260 case 'N':
261 lpdcb->Parity = NOPARITY;
262 lpdcb->fParity = FALSE;
263 break;
264 case 'E':
265 lpdcb->Parity = EVENPARITY;
266 break;
267 case 'M':
268 lpdcb->Parity = MARKPARITY;
269 break;
270 case 'O':
271 lpdcb->Parity = ODDPARITY;
272 break;
273 default:
274 WARN(comm,"Unknown parity `%c'!\n", *ptr);
275 return -1;
278 ptr = strtok(NULL, ", ");
279 TRACE(comm, "charsize (%c)\n", *ptr);
280 lpdcb->ByteSize = *ptr - '0';
282 ptr = strtok(NULL, ", ");
283 TRACE(comm, "stopbits (%c)\n", *ptr);
284 switch (*ptr) {
285 case '1':
286 lpdcb->StopBits = ONESTOPBIT;
287 break;
288 case '2':
289 lpdcb->StopBits = TWOSTOPBITS;
290 break;
291 default:
292 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
293 return -1;
297 return 0;
300 /**************************************************************************
301 * BuildCommDCBA (KERNEL32.14)
303 BOOL32 WINAPI BuildCommDCB32A(LPCSTR device,LPDCB32 lpdcb)
305 return BuildCommDCBAndTimeouts32A(device,lpdcb,NULL);
308 /**************************************************************************
309 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
311 BOOL32 WINAPI BuildCommDCBAndTimeouts32A(LPCSTR device, LPDCB32 lpdcb,
312 LPCOMMTIMEOUTS lptimeouts)
314 int port;
315 char *ptr,*temp;
317 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
318 commerror = 0;
320 if (!lstrncmpi32A(device,"COM",3)) {
321 port=device[3]-'0';
322 if (port--==0) {
323 ERR(comm,"BUG! COM0 can't exists!.\n");
324 return FALSE;
326 if (!ValidCOMPort(port))
327 return FALSE;
328 if (*(device+4)!=':')
329 return FALSE;
330 temp=(LPSTR)(device+5);
331 } else
332 temp=(LPSTR)device;
334 memset(lpdcb, 0, sizeof(DCB32)); /* initialize */
336 lpdcb->DCBlength = sizeof(DCB32);
337 if (strchr(temp,',')) { /* old style */
338 DCB16 dcb16;
339 BOOL16 ret;
340 char last=temp[strlen(temp)-1];
342 ret=BuildCommDCB16(device,&dcb16);
343 if (!ret)
344 return FALSE;
345 lpdcb->BaudRate = dcb16.BaudRate;
346 lpdcb->ByteSize = dcb16.ByteSize;
347 lpdcb->fBinary = dcb16.fBinary;
348 lpdcb->Parity = dcb16.Parity;
349 lpdcb->fParity = dcb16.fParity;
350 lpdcb->fNull = dcb16.fNull;
351 lpdcb->StopBits = dcb16.StopBits;
352 if (last == 'x') {
353 lpdcb->fInX = TRUE;
354 lpdcb->fOutX = TRUE;
355 lpdcb->fOutxCtsFlow = FALSE;
356 lpdcb->fOutxDsrFlow = FALSE;
357 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
358 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
359 } else if (last=='p') {
360 lpdcb->fInX = FALSE;
361 lpdcb->fOutX = FALSE;
362 lpdcb->fOutxCtsFlow = TRUE;
363 lpdcb->fOutxDsrFlow = TRUE;
364 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
365 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
366 } else {
367 lpdcb->fInX = FALSE;
368 lpdcb->fOutX = FALSE;
369 lpdcb->fOutxCtsFlow = FALSE;
370 lpdcb->fOutxDsrFlow = FALSE;
371 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
372 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
374 lpdcb->XonChar = dcb16.XonChar;
375 lpdcb->XoffChar = dcb16.XoffChar;
376 lpdcb->ErrorChar= dcb16.PeChar;
377 lpdcb->fErrorChar= dcb16.fPeChar;
378 lpdcb->EofChar = dcb16.EofChar;
379 lpdcb->EvtChar = dcb16.EvtChar;
380 lpdcb->XonLim = dcb16.XonLim;
381 lpdcb->XoffLim = dcb16.XoffLim;
382 return TRUE;
384 ptr=strtok(temp," ");
385 while (ptr) {
386 DWORD flag,x;
388 flag=0;
389 if (!strncmp("baud=",ptr,5)) {
390 if (!sscanf(ptr+5,"%ld",&x))
391 WARN(comm,"Couldn't parse %s\n",ptr);
392 lpdcb->BaudRate = x;
393 flag=1;
395 if (!strncmp("stop=",ptr,5)) {
396 if (!sscanf(ptr+5,"%ld",&x))
397 WARN(comm,"Couldn't parse %s\n",ptr);
398 lpdcb->StopBits = x;
399 flag=1;
401 if (!strncmp("data=",ptr,5)) {
402 if (!sscanf(ptr+5,"%ld",&x))
403 WARN(comm,"Couldn't parse %s\n",ptr);
404 lpdcb->ByteSize = x;
405 flag=1;
407 if (!strncmp("parity=",ptr,7)) {
408 lpdcb->fParity = TRUE;
409 switch (ptr[8]) {
410 case 'N':case 'n':
411 lpdcb->fParity = FALSE;
412 lpdcb->Parity = NOPARITY;
413 break;
414 case 'E':case 'e':
415 lpdcb->Parity = EVENPARITY;
416 break;
417 case 'O':case 'o':
418 lpdcb->Parity = ODDPARITY;
419 break;
420 case 'M':case 'm':
421 lpdcb->Parity = MARKPARITY;
422 break;
424 flag=1;
426 if (!flag)
427 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
428 ptr=strtok(NULL," ");
430 if (lpdcb->BaudRate==110)
431 lpdcb->StopBits = 2;
432 return TRUE;
435 /**************************************************************************
436 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
438 BOOL32 WINAPI BuildCommDCBAndTimeouts32W( LPCWSTR devid, LPDCB32 lpdcb,
439 LPCOMMTIMEOUTS lptimeouts )
441 LPSTR devidA;
442 BOOL32 ret;
444 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
445 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
446 ret=BuildCommDCBAndTimeouts32A(devidA,lpdcb,lptimeouts);
447 HeapFree( GetProcessHeap(), 0, devidA );
448 return ret;
451 /**************************************************************************
452 * BuildCommDCBW (KERNEL32.17)
454 BOOL32 WINAPI BuildCommDCB32W(LPCWSTR devid,LPDCB32 lpdcb)
456 return BuildCommDCBAndTimeouts32W(devid,lpdcb,NULL);
459 /*****************************************************************************
460 * OpenComm (USER.200)
462 INT16 WINAPI OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
464 int port,fd;
466 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
467 commerror = 0;
469 if (!lstrncmpi32A(device,"COM",3)) {
470 port = device[3] - '0';
472 if (port-- == 0) {
473 ERR(comm, "BUG ! COM0 doesn't exist !\n");
474 commerror = IE_BADID;
477 /* to help GetCommError return left buffsize [V] */
478 iGlobalOutQueueFiller = (cbOutQueue - SERIAL_XMIT_SIZE);
479 if (iGlobalOutQueueFiller < 0) iGlobalOutQueueFiller = 0;
481 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
483 if (!ValidCOMPort(port)) {
484 commerror = IE_BADID;
485 return -1;
487 if (COM[port].fd) {
488 return COM[port].fd;
491 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
492 if (fd == -1) {
493 commerror = WinError();
494 return -1;
495 } else {
496 unknown[port] = SEGPTR_ALLOC(40);
497 bzero(unknown[port],40);
498 COM[port].fd = fd;
499 /* save terminal state */
500 tcgetattr(fd,&m_stat[port]);
501 return fd;
504 else
505 if (!lstrncmpi32A(device,"LPT",3)) {
506 port = device[3] - '0';
508 if (!ValidLPTPort(port)) {
509 commerror = IE_BADID;
510 return -1;
512 if (LPT[port].fd) {
513 commerror = IE_OPEN;
514 return -1;
517 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
518 if (fd == -1) {
519 commerror = WinError();
520 return -1;
521 } else {
522 LPT[port].fd = fd;
523 return fd;
526 return 0;
529 /*****************************************************************************
530 * CloseComm (USER.207)
532 INT16 WINAPI CloseComm(INT16 fd)
534 int port;
536 TRACE(comm,"fd %d\n", fd);
537 if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
538 SEGPTR_FREE(unknown[port]);
539 COM[port].fd = 0; /* my adaptation of RER's fix */
540 } else {
541 commerror = IE_BADID;
542 return -1;
545 /* reset modem lines */
546 tcsetattr(fd,TCSANOW,&m_stat[port]);
548 if (close(fd) == -1) {
549 commerror = WinError();
550 return -1;
551 } else {
552 commerror = 0;
553 return 0;
557 /*****************************************************************************
558 * SetCommBreak (USER.210)
560 INT16 WINAPI SetCommBreak16(INT16 fd)
562 struct DosDeviceStruct *ptr;
564 TRACE(comm,"fd=%d\n", fd);
565 if ((ptr = GetDeviceStruct(fd)) == NULL) {
566 commerror = IE_BADID;
567 return -1;
570 ptr->suspended = 1;
571 commerror = 0;
572 return 0;
575 /*****************************************************************************
576 * SetCommBreak (KERNEL32.449)
578 BOOL32 WINAPI SetCommBreak32(INT32 fd)
581 struct DosDeviceStruct *ptr;
583 TRACE(comm,"fd=%d\n", fd);
584 if ((ptr = GetDeviceStruct(fd)) == NULL) {
585 commerror = IE_BADID;
586 return FALSE;
589 ptr->suspended = 1;
590 commerror = 0;
591 return TRUE;
594 /*****************************************************************************
595 * ClearCommBreak (USER.211)
597 INT16 WINAPI ClearCommBreak16(INT16 fd)
599 struct DosDeviceStruct *ptr;
601 TRACE(comm,"fd=%d\n", fd);
602 if ((ptr = GetDeviceStruct(fd)) == NULL) {
603 commerror = IE_BADID;
604 return -1;
607 ptr->suspended = 0;
608 commerror = 0;
609 return 0;
612 /*****************************************************************************
613 * ClearCommBreak (KERNEL32.20)
615 BOOL32 WINAPI ClearCommBreak32(INT32 fd)
617 struct DosDeviceStruct *ptr;
619 TRACE(comm,"fd=%d\n", fd);
620 if ((ptr = GetDeviceStruct(fd)) == NULL) {
621 commerror = IE_BADID;
622 return FALSE;
625 ptr->suspended = 0;
626 commerror = 0;
627 return TRUE;
630 /*****************************************************************************
631 * EscapeCommFunction (USER.214)
633 LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
635 int max;
636 struct termios port;
638 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
639 if (tcgetattr(fd,&port) == -1) {
640 commerror=WinError();
641 return -1;
644 switch (nFunction) {
645 case RESETDEV:
646 break;
648 case GETMAXCOM:
649 for (max = MAX_PORTS;!COM[max].devicename;max--)
651 return max;
652 break;
654 case GETMAXLPT:
655 for (max = MAX_PORTS;!LPT[max].devicename;max--)
657 return 0x80 + max;
658 break;
660 #ifdef TIOCM_DTR
661 case CLRDTR:
662 port.c_cflag &= TIOCM_DTR;
663 break;
664 #endif
666 #ifdef TIOCM_RTS
667 case CLRRTS:
668 port.c_cflag &= TIOCM_RTS;
669 break;
670 #endif
672 #ifdef CRTSCTS
673 case SETDTR:
674 port.c_cflag |= CRTSCTS;
675 break;
677 case SETRTS:
678 port.c_cflag |= CRTSCTS;
679 break;
680 #endif
682 case SETXOFF:
683 port.c_iflag |= IXOFF;
684 break;
686 case SETXON:
687 port.c_iflag |= IXON;
688 break;
690 default:
691 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
692 fd, nFunction);
693 break;
696 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
697 commerror = WinError();
698 return -1;
699 } else {
700 commerror = 0;
701 return 0;
705 /*****************************************************************************
706 * EscapeCommFunction (KERNEL32.214)
708 BOOL32 WINAPI EscapeCommFunction32(INT32 fd,UINT32 nFunction)
710 struct termios port;
711 struct DosDeviceStruct *ptr;
713 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
714 if (tcgetattr(fd,&port) == -1) {
715 commerror=WinError();
716 return FALSE;
718 if ((ptr = GetDeviceStruct(fd)) == NULL) {
719 commerror = IE_BADID;
720 return FALSE;
723 switch (nFunction) {
724 case RESETDEV:
725 break;
727 #ifdef TIOCM_DTR
728 case CLRDTR:
729 port.c_cflag &= TIOCM_DTR;
730 break;
731 #endif
733 #ifdef TIOCM_RTS
734 case CLRRTS:
735 port.c_cflag &= TIOCM_RTS;
736 break;
737 #endif
739 #ifdef CRTSCTS
740 case SETDTR:
741 port.c_cflag |= CRTSCTS;
742 break;
744 case SETRTS:
745 port.c_cflag |= CRTSCTS;
746 break;
747 #endif
749 case SETXOFF:
750 port.c_iflag |= IXOFF;
751 break;
753 case SETXON:
754 port.c_iflag |= IXON;
755 break;
756 case SETBREAK:
757 ptr->suspended = 1;
758 break;
759 case CLRBREAK:
760 ptr->suspended = 0;
761 break;
762 default:
763 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
764 fd, nFunction);
765 break;
768 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
769 commerror = WinError();
770 return FALSE;
771 } else {
772 commerror = 0;
773 return TRUE;
777 /*****************************************************************************
778 * FlushComm (USER.215)
780 INT16 WINAPI FlushComm(INT16 fd,INT16 fnQueue)
782 int queue;
784 TRACE(comm,"fd=%d, queue=%d\n", fd, fnQueue);
785 switch (fnQueue) {
786 case 0: queue = TCOFLUSH;
787 break;
788 case 1: queue = TCIFLUSH;
789 break;
790 default:WARN(comm,"(fd=%d,fnQueue=%d):Unknown queue\n",
791 fd, fnQueue);
792 return -1;
794 if (tcflush(fd, queue)) {
795 commerror = WinError();
796 return -1;
797 } else {
798 commerror = 0;
799 return 0;
803 /********************************************************************
804 * PurgeComm (KERNEL32.557)
806 BOOL32 WINAPI PurgeComm( HANDLE32 hFile, DWORD flags)
808 FIXME(comm, "(%08x %08lx) unimplemented stub\n",
809 hFile, flags);
810 return 0;
813 /********************************************************************
814 * GetCommError (USER.203)
816 INT16 WINAPI GetCommError(INT16 fd,LPCOMSTAT lpStat)
818 int temperror;
819 unsigned long cnt;
820 int rc;
822 unsigned char *stol;
823 int act;
824 unsigned int mstat;
825 if ((act = GetCommPort(fd)) == -1) {
826 WARN(comm," fd %d not comm port\n",fd);
827 return CE_MODE;
829 stol = (unsigned char *)unknown[act] + COMM_MSR_OFFSET;
830 ioctl(fd,TIOCMGET,&mstat);
831 if( mstat&TIOCM_CAR )
832 *stol |= 0x80;
833 else
834 *stol &=0x7f;
836 if (lpStat) {
837 lpStat->status = 0;
839 rc = ioctl(fd, TIOCOUTQ, &cnt);
840 if (rc) WARN(comm, "Error !\n");
841 lpStat->cbOutQue = cnt + iGlobalOutQueueFiller;
843 rc = ioctl(fd, TIOCINQ, &cnt);
844 if (rc) WARN(comm, "Error !\n");
845 lpStat->cbInQue = cnt;
847 TRACE(comm, "fd %d, error %d, lpStat %d %d %d stol %x\n",
848 fd, commerror, lpStat->status, lpStat->cbInQue,
849 lpStat->cbOutQue, *stol);
851 else
852 TRACE(comm, "fd %d, error %d, lpStat NULL stol %x\n",
853 fd, commerror, *stol);
856 * [RER] I have no idea what the following is trying to accomplish.
857 * [RER] It is certainly not what the reference manual suggests.
859 temperror = commerror;
860 commerror = 0;
861 return(temperror);
864 /*****************************************************************************
865 * ClearCommError (KERNEL32.21)
867 BOOL32 WINAPI ClearCommError(INT32 fd,LPDWORD errors,LPCOMSTAT lpStat)
869 int temperror;
871 TRACE(comm, "fd %d (current error %d)\n",
872 fd, commerror);
873 temperror = commerror;
874 commerror = 0;
875 return TRUE;
878 /*****************************************************************************
879 * SetCommEventMask (USER.208)
881 SEGPTR WINAPI SetCommEventMask(INT16 fd,UINT16 fuEvtMask)
883 unsigned char *stol;
884 int act;
885 int repid;
886 unsigned int mstat;
887 TRACE(comm,"fd %d,mask %d\n",fd,fuEvtMask);
888 eventmask |= fuEvtMask;
889 if ((act = GetCommPort(fd)) == -1) {
890 WARN(comm," fd %d not comm port\n",act);
891 return SEGPTR_GET(NULL);
893 stol = (unsigned char *)unknown[act];
894 stol += COMM_MSR_OFFSET;
895 repid = ioctl(fd,TIOCMGET,&mstat);
896 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
897 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
898 else {*stol &=0x7f;}
899 TRACE(comm," modem dcd construct %x\n",*stol);
900 return SEGPTR_GET(unknown[act]);
903 /*****************************************************************************
904 * GetCommEventMask (USER.209)
906 UINT16 WINAPI GetCommEventMask(INT16 fd,UINT16 fnEvtClear)
908 int events = 0;
910 TRACE(comm, "fd %d, mask %d\n", fd, fnEvtClear);
913 * Determine if any characters are available
915 if (fnEvtClear & EV_RXCHAR)
917 int rc;
918 unsigned long cnt;
920 rc = ioctl(fd, TIOCINQ, &cnt);
921 if (cnt) events |= EV_RXCHAR;
923 TRACE(comm, "rxchar %ld\n", cnt);
927 * There are other events that need to be checked for
929 /* TODO */
931 TRACE(comm, "return events %d\n", events);
932 return events;
935 * [RER] The following was gibberish
937 #if 0
938 tempmask = eventmask;
939 eventmask &= ~fnEvtClear;
940 return eventmask;
941 #endif
944 /*****************************************************************************
945 * SetupComm (KERNEL32.676)
947 BOOL32 WINAPI SetupComm( HANDLE32 hFile, DWORD insize, DWORD outsize)
949 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
950 return FALSE;
953 /*****************************************************************************
954 * GetCommMask (KERNEL32.156)
956 BOOL32 WINAPI GetCommMask(HANDLE32 fd,LPDWORD evtmask)
958 TRACE(comm, "fd %d, mask %p\n", fd, evtmask);
959 *evtmask = eventmask;
960 return TRUE;
963 /*****************************************************************************
964 * SetCommMask (KERNEL32.451)
966 BOOL32 WINAPI SetCommMask(INT32 fd,DWORD evtmask)
968 TRACE(comm, "fd %d, mask %lx\n", fd, evtmask);
969 eventmask = evtmask;
970 return TRUE;
973 /*****************************************************************************
974 * SetCommState16 (USER.201)
976 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
978 struct termios port;
979 struct DosDeviceStruct *ptr;
981 TRACE(comm, "fd %d, ptr %p\n", lpdcb->Id, lpdcb);
982 if (tcgetattr(lpdcb->Id, &port) == -1) {
983 commerror = WinError();
984 return -1;
987 port.c_cc[VMIN] = 0;
988 port.c_cc[VTIME] = 1;
990 #ifdef IMAXBEL
991 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
992 #else
993 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
994 #endif
995 port.c_iflag |= (IGNBRK);
997 port.c_oflag &= ~(OPOST);
999 port.c_cflag &= ~(HUPCL);
1000 port.c_cflag |= CLOCAL | CREAD;
1002 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1003 port.c_lflag |= NOFLSH;
1005 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
1006 commerror = IE_BADID;
1007 return -1;
1009 if (ptr->baudrate > 0)
1010 lpdcb->BaudRate = ptr->baudrate;
1011 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
1012 #ifdef CBAUD
1013 port.c_cflag &= ~CBAUD;
1014 switch (lpdcb->BaudRate) {
1015 case 110:
1016 case CBR_110:
1017 port.c_cflag |= B110;
1018 break;
1019 case 300:
1020 case CBR_300:
1021 port.c_cflag |= B300;
1022 break;
1023 case 600:
1024 case CBR_600:
1025 port.c_cflag |= B600;
1026 break;
1027 case 1200:
1028 case CBR_1200:
1029 port.c_cflag |= B1200;
1030 break;
1031 case 2400:
1032 case CBR_2400:
1033 port.c_cflag |= B2400;
1034 break;
1035 case 4800:
1036 case CBR_4800:
1037 port.c_cflag |= B4800;
1038 break;
1039 case 9600:
1040 case CBR_9600:
1041 port.c_cflag |= B9600;
1042 break;
1043 case 19200:
1044 case CBR_19200:
1045 port.c_cflag |= B19200;
1046 break;
1047 case 38400:
1048 case CBR_38400:
1049 port.c_cflag |= B38400;
1050 break;
1051 #ifdef B57600
1052 case 57600:
1053 port.c_cflag |= B57600;
1054 break;
1055 #endif
1056 #ifdef B115200
1057 case 57601:
1058 port.c_cflag |= B115200;
1059 break;
1060 #endif
1061 default:
1062 commerror = IE_BAUDRATE;
1063 return -1;
1065 #elif !defined(__EMX__)
1066 switch (lpdcb->BaudRate) {
1067 case 110:
1068 case CBR_110:
1069 port.c_ospeed = B110;
1070 break;
1071 case 300:
1072 case CBR_300:
1073 port.c_ospeed = B300;
1074 break;
1075 case 600:
1076 case CBR_600:
1077 port.c_ospeed = B600;
1078 break;
1079 case 1200:
1080 case CBR_1200:
1081 port.c_ospeed = B1200;
1082 break;
1083 case 2400:
1084 case CBR_2400:
1085 port.c_ospeed = B2400;
1086 break;
1087 case 4800:
1088 case CBR_4800:
1089 port.c_ospeed = B4800;
1090 break;
1091 case 9600:
1092 case CBR_9600:
1093 port.c_ospeed = B9600;
1094 break;
1095 case 19200:
1096 case CBR_19200:
1097 port.c_ospeed = B19200;
1098 break;
1099 case 38400:
1100 case CBR_38400:
1101 port.c_ospeed = B38400;
1102 break;
1103 default:
1104 commerror = IE_BAUDRATE;
1105 return -1;
1107 port.c_ispeed = port.c_ospeed;
1108 #endif
1109 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1110 port.c_cflag &= ~CSIZE;
1111 switch (lpdcb->ByteSize) {
1112 case 5:
1113 port.c_cflag |= CS5;
1114 break;
1115 case 6:
1116 port.c_cflag |= CS6;
1117 break;
1118 case 7:
1119 port.c_cflag |= CS7;
1120 break;
1121 case 8:
1122 port.c_cflag |= CS8;
1123 break;
1124 default:
1125 commerror = IE_BYTESIZE;
1126 return -1;
1129 TRACE(comm,"parity %d\n",lpdcb->Parity);
1130 port.c_cflag &= ~(PARENB | PARODD);
1131 if (lpdcb->fParity)
1132 switch (lpdcb->Parity) {
1133 case NOPARITY:
1134 port.c_iflag &= ~INPCK;
1135 break;
1136 case ODDPARITY:
1137 port.c_cflag |= (PARENB | PARODD);
1138 port.c_iflag |= INPCK;
1139 break;
1140 case EVENPARITY:
1141 port.c_cflag |= PARENB;
1142 port.c_iflag |= INPCK;
1143 break;
1144 default:
1145 commerror = IE_BYTESIZE;
1146 return -1;
1150 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1152 switch (lpdcb->StopBits) {
1153 case ONESTOPBIT:
1154 port.c_cflag &= ~CSTOPB;
1155 break;
1156 case TWOSTOPBITS:
1157 port.c_cflag |= CSTOPB;
1158 break;
1159 default:
1160 commerror = IE_BYTESIZE;
1161 return -1;
1163 #ifdef CRTSCTS
1165 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1166 port.c_cflag |= CRTSCTS;
1168 if (lpdcb->fDtrDisable)
1169 port.c_cflag &= ~CRTSCTS;
1170 #endif
1171 if (lpdcb->fInX)
1172 port.c_iflag |= IXON;
1173 else
1174 port.c_iflag &= ~IXON;
1175 if (lpdcb->fOutX)
1176 port.c_iflag |= IXOFF;
1177 else
1178 port.c_iflag &= ~IXOFF;
1180 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
1181 commerror = WinError();
1182 return FALSE;
1183 } else {
1184 commerror = 0;
1185 return 0;
1189 /*****************************************************************************
1190 * SetCommState32 (KERNEL32.452)
1192 BOOL32 WINAPI SetCommState32(INT32 fd,LPDCB32 lpdcb)
1194 struct termios port;
1195 struct DosDeviceStruct *ptr;
1197 TRACE(comm,"fd %d, ptr %p\n",fd,lpdcb);
1198 if (tcgetattr(fd,&port) == -1) {
1199 commerror = WinError();
1200 return FALSE;
1203 port.c_cc[VMIN] = 0;
1204 port.c_cc[VTIME] = 1;
1206 #ifdef IMAXBEL
1207 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1208 #else
1209 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1210 #endif
1211 port.c_iflag |= (IGNBRK);
1213 port.c_oflag &= ~(OPOST);
1215 port.c_cflag &= ~(HUPCL);
1216 port.c_cflag |= CLOCAL | CREAD;
1218 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1219 port.c_lflag |= NOFLSH;
1221 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1222 commerror = IE_BADID;
1223 return FALSE;
1225 if (ptr->baudrate > 0)
1226 lpdcb->BaudRate = ptr->baudrate;
1227 TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1228 #ifdef CBAUD
1229 port.c_cflag &= ~CBAUD;
1230 switch (lpdcb->BaudRate) {
1231 case 110:
1232 case CBR_110:
1233 port.c_cflag |= B110;
1234 break;
1235 case 300:
1236 case CBR_300:
1237 port.c_cflag |= B300;
1238 break;
1239 case 600:
1240 case CBR_600:
1241 port.c_cflag |= B600;
1242 break;
1243 case 1200:
1244 case CBR_1200:
1245 port.c_cflag |= B1200;
1246 break;
1247 case 2400:
1248 case CBR_2400:
1249 port.c_cflag |= B2400;
1250 break;
1251 case 4800:
1252 case CBR_4800:
1253 port.c_cflag |= B4800;
1254 break;
1255 case 9600:
1256 case CBR_9600:
1257 port.c_cflag |= B9600;
1258 break;
1259 case 19200:
1260 case CBR_19200:
1261 port.c_cflag |= B19200;
1262 break;
1263 case 38400:
1264 case CBR_38400:
1265 port.c_cflag |= B38400;
1266 break;
1267 default:
1268 commerror = IE_BAUDRATE;
1269 return FALSE;
1271 #elif !defined(__EMX__)
1272 switch (lpdcb->BaudRate) {
1273 case 110:
1274 case CBR_110:
1275 port.c_ospeed = B110;
1276 break;
1277 case 300:
1278 case CBR_300:
1279 port.c_ospeed = B300;
1280 break;
1281 case 600:
1282 case CBR_600:
1283 port.c_ospeed = B600;
1284 break;
1285 case 1200:
1286 case CBR_1200:
1287 port.c_ospeed = B1200;
1288 break;
1289 case 2400:
1290 case CBR_2400:
1291 port.c_ospeed = B2400;
1292 break;
1293 case 4800:
1294 case CBR_4800:
1295 port.c_ospeed = B4800;
1296 break;
1297 case 9600:
1298 case CBR_9600:
1299 port.c_ospeed = B9600;
1300 break;
1301 case 19200:
1302 case CBR_19200:
1303 port.c_ospeed = B19200;
1304 break;
1305 case 38400:
1306 case CBR_38400:
1307 port.c_ospeed = B38400;
1308 break;
1309 default:
1310 commerror = IE_BAUDRATE;
1311 return FALSE;
1313 port.c_ispeed = port.c_ospeed;
1314 #endif
1315 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1316 port.c_cflag &= ~CSIZE;
1317 switch (lpdcb->ByteSize) {
1318 case 5:
1319 port.c_cflag |= CS5;
1320 break;
1321 case 6:
1322 port.c_cflag |= CS6;
1323 break;
1324 case 7:
1325 port.c_cflag |= CS7;
1326 break;
1327 case 8:
1328 port.c_cflag |= CS8;
1329 break;
1330 default:
1331 commerror = IE_BYTESIZE;
1332 return FALSE;
1335 TRACE(comm,"parity %d\n",lpdcb->Parity);
1336 port.c_cflag &= ~(PARENB | PARODD);
1337 if (lpdcb->fParity)
1338 switch (lpdcb->Parity) {
1339 case NOPARITY:
1340 port.c_iflag &= ~INPCK;
1341 break;
1342 case ODDPARITY:
1343 port.c_cflag |= (PARENB | PARODD);
1344 port.c_iflag |= INPCK;
1345 break;
1346 case EVENPARITY:
1347 port.c_cflag |= PARENB;
1348 port.c_iflag |= INPCK;
1349 break;
1350 default:
1351 commerror = IE_BYTESIZE;
1352 return FALSE;
1356 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1357 switch (lpdcb->StopBits) {
1358 case ONESTOPBIT:
1359 port.c_cflag &= ~CSTOPB;
1360 break;
1361 case TWOSTOPBITS:
1362 port.c_cflag |= CSTOPB;
1363 break;
1364 default:
1365 commerror = IE_BYTESIZE;
1366 return FALSE;
1368 #ifdef CRTSCTS
1369 if ( lpdcb->fOutxCtsFlow ||
1370 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1371 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1373 port.c_cflag |= CRTSCTS;
1374 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1375 port.c_cflag &= ~CRTSCTS;
1377 #endif
1378 if (lpdcb->fInX)
1379 port.c_iflag |= IXON;
1380 else
1381 port.c_iflag &= ~IXON;
1382 if (lpdcb->fOutX)
1383 port.c_iflag |= IXOFF;
1384 else
1385 port.c_iflag &= ~IXOFF;
1387 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1388 commerror = WinError();
1389 return FALSE;
1390 } else {
1391 commerror = 0;
1392 return TRUE;
1397 /*****************************************************************************
1398 * GetCommState (USER.202)
1400 INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
1402 struct termios port;
1404 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1405 if (tcgetattr(fd, &port) == -1) {
1406 commerror = WinError();
1407 return -1;
1409 lpdcb->Id = fd;
1410 #ifndef __EMX__
1411 #ifdef CBAUD
1412 switch (port.c_cflag & CBAUD) {
1413 #else
1414 switch (port.c_ospeed) {
1415 #endif
1416 case B110:
1417 lpdcb->BaudRate = 110;
1418 break;
1419 case B300:
1420 lpdcb->BaudRate = 300;
1421 break;
1422 case B600:
1423 lpdcb->BaudRate = 600;
1424 break;
1425 case B1200:
1426 lpdcb->BaudRate = 1200;
1427 break;
1428 case B2400:
1429 lpdcb->BaudRate = 2400;
1430 break;
1431 case B4800:
1432 lpdcb->BaudRate = 4800;
1433 break;
1434 case B9600:
1435 lpdcb->BaudRate = 9600;
1436 break;
1437 case B19200:
1438 lpdcb->BaudRate = 19200;
1439 break;
1440 case B38400:
1441 lpdcb->BaudRate = 38400;
1442 break;
1443 #ifdef B57600
1444 case B57600:
1445 lpdcb->BaudRate = 57600;
1446 break;
1447 #endif
1448 #ifdef B115200
1449 case B115200:
1450 lpdcb->BaudRate = 57601;
1451 break;
1452 #endif
1454 #endif
1455 switch (port.c_cflag & CSIZE) {
1456 case CS5:
1457 lpdcb->ByteSize = 5;
1458 break;
1459 case CS6:
1460 lpdcb->ByteSize = 6;
1461 break;
1462 case CS7:
1463 lpdcb->ByteSize = 7;
1464 break;
1465 case CS8:
1466 lpdcb->ByteSize = 8;
1467 break;
1470 switch (port.c_cflag & (PARENB | PARODD)) {
1471 case 0:
1472 lpdcb->fParity = FALSE;
1473 lpdcb->Parity = NOPARITY;
1474 break;
1475 case PARENB:
1476 lpdcb->fParity = TRUE;
1477 lpdcb->Parity = EVENPARITY;
1478 break;
1479 case (PARENB | PARODD):
1480 lpdcb->fParity = TRUE;
1481 lpdcb->Parity = ODDPARITY;
1482 break;
1485 if (port.c_cflag & CSTOPB)
1486 lpdcb->StopBits = TWOSTOPBITS;
1487 else
1488 lpdcb->StopBits = ONESTOPBIT;
1490 lpdcb->RlsTimeout = 50;
1491 lpdcb->CtsTimeout = 50;
1492 lpdcb->DsrTimeout = 50;
1493 lpdcb->fNull = 0;
1494 lpdcb->fChEvt = 0;
1495 lpdcb->fBinary = 1;
1496 lpdcb->fDtrDisable = 0;
1498 #ifdef CRTSCTS
1500 if (port.c_cflag & CRTSCTS) {
1501 lpdcb->fDtrflow = 1;
1502 lpdcb->fRtsflow = 1;
1503 lpdcb->fOutxCtsFlow = 1;
1504 lpdcb->fOutxDsrFlow = 1;
1505 } else
1506 #endif
1507 lpdcb->fDtrDisable = 1;
1509 if (port.c_iflag & IXON)
1510 lpdcb->fInX = 1;
1511 else
1512 lpdcb->fInX = 0;
1514 if (port.c_iflag & IXOFF)
1515 lpdcb->fOutX = 1;
1516 else
1517 lpdcb->fOutX = 0;
1519 lpdcb->XonChar =
1520 lpdcb->XoffChar =
1522 lpdcb->XonLim = 10;
1523 lpdcb->XoffLim = 10;
1525 commerror = 0;
1526 return 0;
1529 /*****************************************************************************
1530 * GetCommState (KERNEL32.159)
1532 BOOL32 WINAPI GetCommState32(INT32 fd, LPDCB32 lpdcb)
1534 struct termios port;
1536 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1537 if (GetDeviceStruct(fd) == NULL) return FALSE;
1538 if (tcgetattr(fd, &port) == -1) {
1539 commerror = WinError();
1540 return FALSE;
1542 #ifndef __EMX__
1543 #ifdef CBAUD
1544 switch (port.c_cflag & CBAUD) {
1545 #else
1546 switch (port.c_ospeed) {
1547 #endif
1548 case B110:
1549 lpdcb->BaudRate = 110;
1550 break;
1551 case B300:
1552 lpdcb->BaudRate = 300;
1553 break;
1554 case B600:
1555 lpdcb->BaudRate = 600;
1556 break;
1557 case B1200:
1558 lpdcb->BaudRate = 1200;
1559 break;
1560 case B2400:
1561 lpdcb->BaudRate = 2400;
1562 break;
1563 case B4800:
1564 lpdcb->BaudRate = 4800;
1565 break;
1566 case B9600:
1567 lpdcb->BaudRate = 9600;
1568 break;
1569 case B19200:
1570 lpdcb->BaudRate = 19200;
1571 break;
1572 case B38400:
1573 lpdcb->BaudRate = 38400;
1574 break;
1576 #endif
1577 switch (port.c_cflag & CSIZE) {
1578 case CS5:
1579 lpdcb->ByteSize = 5;
1580 break;
1581 case CS6:
1582 lpdcb->ByteSize = 6;
1583 break;
1584 case CS7:
1585 lpdcb->ByteSize = 7;
1586 break;
1587 case CS8:
1588 lpdcb->ByteSize = 8;
1589 break;
1592 switch (port.c_cflag & (PARENB | PARODD)) {
1593 case 0:
1594 lpdcb->fParity = FALSE;
1595 lpdcb->Parity = NOPARITY;
1596 break;
1597 case PARENB:
1598 lpdcb->fParity = TRUE;
1599 lpdcb->Parity = EVENPARITY;
1600 break;
1601 case (PARENB | PARODD):
1602 lpdcb->fParity = TRUE;
1603 lpdcb->Parity = ODDPARITY;
1604 break;
1607 if (port.c_cflag & CSTOPB)
1608 lpdcb->StopBits = TWOSTOPBITS;
1609 else
1610 lpdcb->StopBits = ONESTOPBIT;
1612 lpdcb->fNull = 0;
1613 lpdcb->fBinary = 1;
1615 #ifdef CRTSCTS
1617 if (port.c_cflag & CRTSCTS) {
1618 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1619 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1620 lpdcb->fOutxCtsFlow = 1;
1621 lpdcb->fOutxDsrFlow = 1;
1622 } else
1623 #endif
1625 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1626 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1628 if (port.c_iflag & IXON)
1629 lpdcb->fInX = 1;
1630 else
1631 lpdcb->fInX = 0;
1633 if (port.c_iflag & IXOFF)
1634 lpdcb->fOutX = 1;
1635 else
1636 lpdcb->fOutX = 0;
1638 lpdcb->XonChar =
1639 lpdcb->XoffChar =
1641 lpdcb->XonLim = 10;
1642 lpdcb->XoffLim = 10;
1644 commerror = 0;
1645 return TRUE;
1648 /*****************************************************************************
1649 * TransmitCommChar (USER.206)
1651 INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
1653 struct DosDeviceStruct *ptr;
1655 TRACE(comm, "fd %d, data %d \n", fd, chTransmit);
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 (write(fd, (void *) &chTransmit, 1) == -1) {
1667 commerror = WinError();
1668 return -1;
1669 } else {
1670 commerror = 0;
1671 return 0;
1675 /*****************************************************************************
1676 * TransmitCommChar (KERNEL32.535)
1678 BOOL32 WINAPI TransmitCommChar32(INT32 fd,CHAR chTransmit)
1680 struct DosDeviceStruct *ptr;
1682 TRACE(comm,"(%d,'%c')\n",fd,chTransmit);
1683 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1684 commerror = IE_BADID;
1685 return FALSE;
1688 if (ptr->suspended) {
1689 commerror = IE_HARDWARE;
1690 return FALSE;
1692 if (write(fd, (void *) &chTransmit, 1) == -1) {
1693 commerror = WinError();
1694 return FALSE;
1695 } else {
1696 commerror = 0;
1697 return TRUE;
1701 /*****************************************************************************
1702 * UngetCommChar (USER.212)
1704 INT16 WINAPI UngetCommChar(INT16 fd,CHAR chUnget)
1706 struct DosDeviceStruct *ptr;
1708 TRACE(comm,"fd %d (char %d)\n", fd, chUnget);
1709 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1710 commerror = IE_BADID;
1711 return -1;
1714 if (ptr->suspended) {
1715 commerror = IE_HARDWARE;
1716 return -1;
1719 ptr->unget = 1;
1720 ptr->unget_byte = chUnget;
1721 commerror = 0;
1722 return 0;
1725 /*****************************************************************************
1726 * ReadComm (USER.204)
1728 INT16 WINAPI ReadComm(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1730 int status, length;
1731 struct DosDeviceStruct *ptr;
1733 TRACE(comm, "fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1734 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1735 commerror = IE_BADID;
1736 return -1;
1739 if (ptr->suspended) {
1740 commerror = IE_HARDWARE;
1741 return -1;
1744 if (ptr->unget) {
1745 *lpvBuf = ptr->unget_byte;
1746 lpvBuf++;
1747 ptr->unget = 0;
1749 length = 1;
1750 } else
1751 length = 0;
1753 status = read(fd, (void *) lpvBuf, cbRead);
1755 if (status == -1) {
1756 if (errno != EAGAIN) {
1757 commerror = WinError();
1758 return -1 - length;
1759 } else {
1760 commerror = 0;
1761 return length;
1763 } else {
1764 TRACE(comm,"%.*s\n", length+status, lpvBuf);
1765 commerror = 0;
1766 return length + status;
1770 /*****************************************************************************
1771 * WriteComm (USER.205)
1773 INT16 WINAPI WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1775 int length;
1776 struct DosDeviceStruct *ptr;
1778 TRACE(comm,"fd %d, ptr %p, length %d\n",
1779 fd, lpvBuf, cbWrite);
1780 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1781 commerror = IE_BADID;
1782 return -1;
1785 if (ptr->suspended) {
1786 commerror = IE_HARDWARE;
1787 return -1;
1790 TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
1791 length = write(fd, (void *) lpvBuf, cbWrite);
1793 if (length == -1) {
1794 commerror = WinError();
1795 return -1;
1796 } else {
1797 commerror = 0;
1798 return length;
1803 /*****************************************************************************
1804 * GetCommTimeouts (KERNEL32.160)
1806 BOOL32 WINAPI GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts)
1808 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1809 return TRUE;
1812 /*****************************************************************************
1813 * SetCommTimeouts (KERNEL32.453)
1815 BOOL32 WINAPI SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
1816 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1817 return TRUE;
1820 /***********************************************************************
1821 * EnableCommNotification (USER.246)
1823 BOOL16 WINAPI EnableCommNotification( INT16 fd, HWND16 hwnd,
1824 INT16 cbWriteNotify, INT16 cbOutQueue )
1826 FIXME(comm, "(%d, %x, %d, %d):stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
1827 return TRUE;
1830 /***********************************************************************
1831 * GetCommModemStatus (KERNEL32.285)
1833 BOOL32 WINAPI GetCommModemStatus(HANDLE32 hFile,LPDWORD lpModemStat )
1835 FIXME(comm, "(%d %p)\n",hFile,lpModemStat );
1836 return TRUE;
1838 /***********************************************************************
1839 * WaitCommEvent (KERNEL32.719)
1841 BOOL32 WINAPI WaitCommEvent(HANDLE32 hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
1843 FIXME(comm, "(%d %p %p )\n",hFile, eventmask,overlapped);
1844 return TRUE;