Basic support for WIN32 serial communications API.
[wine/wine-kai.git] / misc / comm.c
blob886d9e43a418f3442c61c33f005fbd0661b4f949
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 #include "server/request.h"
73 #include "server.h"
74 #include "process.h"
75 #include "winerror.h"
77 #ifndef TIOCINQ
78 #define TIOCINQ FIONREAD
79 #endif
80 #define COMM_MSR_OFFSET 35 /* see knowledge base Q101417 */
82 * [RER] These are globals are wrong. They should be in DosDeviceStruct
83 * on a per port basis.
85 int commerror = 0, eventmask = 0;
88 * [V] If above globals are wrong, the one below will be wrong as well. It
89 * should probably be in the DosDeviceStruct on per port basis too.
91 int iGlobalOutQueueFiller;
93 #define SERIAL_XMIT_SIZE 4096
95 struct DosDeviceStruct COM[MAX_PORTS];
96 struct DosDeviceStruct LPT[MAX_PORTS];
97 /* pointers to unknown(==undocumented) comm structure */
98 LPCVOID *unknown[MAX_PORTS];
99 /* save terminal states */
100 static struct termios m_stat[MAX_PORTS];
102 void COMM_Init(void)
104 int x;
105 char option[10], temp[256], *btemp;
106 struct stat st;
108 for (x=0; x!=MAX_PORTS; x++) {
109 strcpy(option,"COMx");
110 option[3] = '1' + x;
111 option[4] = '\0';
113 PROFILE_GetWineIniString( "serialports", option, "*",
114 temp, sizeof(temp) );
115 if (!strcmp(temp, "*") || *temp == '\0')
116 COM[x].devicename = NULL;
117 else {
118 btemp = strchr(temp,',');
119 if (btemp != NULL) {
120 *btemp++ = '\0';
121 COM[x].baudrate = atoi(btemp);
122 } else {
123 COM[x].baudrate = -1;
125 stat(temp, &st);
126 if (!S_ISCHR(st.st_mode))
127 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
128 else
129 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
130 WARN(comm,"Can't malloc for device info!\n");
131 else {
132 COM[x].fd = 0;
133 strcpy(COM[x].devicename, temp);
135 TRACE(comm, "%s = %s\n", option, COM[x].devicename);
138 strcpy(option, "LPTx");
139 option[3] = '1' + x;
140 option[4] = '\0';
142 PROFILE_GetWineIniString( "parallelports", option, "*",
143 temp, sizeof(temp) );
144 if (!strcmp(temp, "*") || *temp == '\0')
145 LPT[x].devicename = NULL;
146 else {
147 stat(temp, &st);
148 if (!S_ISCHR(st.st_mode))
149 WARN(comm,"Can't use `%s' as %s !\n", temp, option);
150 else
151 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
152 WARN(comm,"Can't malloc for device info!\n");
153 else {
154 LPT[x].fd = 0;
155 strcpy(LPT[x].devicename, temp);
157 TRACE(comm, "%s = %s\n", option, LPT[x].devicename);
164 struct DosDeviceStruct *GetDeviceStruct(int fd)
166 int x;
168 for (x=0; x!=MAX_PORTS; x++) {
169 if (COM[x].fd == fd)
170 return &COM[x];
171 if (LPT[x].fd == fd)
172 return &LPT[x];
175 return NULL;
178 int GetCommPort(int fd)
180 int x;
182 for (x=0; x<MAX_PORTS; x++) {
183 if (COM[x].fd == fd)
184 return x;
187 return -1;
190 int ValidCOMPort(int x)
192 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
195 int ValidLPTPort(int x)
197 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
200 int WinError(void)
202 TRACE(comm, "errno = %d\n", errno);
203 switch (errno) {
204 default:
205 return CE_IOE;
209 /**************************************************************************
210 * BuildCommDCB (USER.213)
212 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
214 /* "COM1:9600,n,8,1" */
215 /* 012345 */
216 int port;
217 char *ptr, temp[256];
219 TRACE(comm, "(%s), ptr %p\n", device, lpdcb);
220 commerror = 0;
222 if (!lstrncmpiA(device,"COM",3)) {
223 port = device[3] - '0';
226 if (port-- == 0) {
227 ERR(comm, "BUG ! COM0 can't exists!.\n");
228 commerror = IE_BADID;
231 if (!ValidCOMPort(port)) {
232 commerror = IE_BADID;
233 return -1;
236 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
238 if (!COM[port].fd) {
239 OpenComm16(device, 0, 0);
241 lpdcb->Id = COM[port].fd;
243 if (!*(device+4))
244 return 0;
246 if (*(device+4) != ':')
247 return -1;
249 strcpy(temp,device+5);
250 ptr = strtok(temp, ", ");
252 if (COM[port].baudrate > 0)
253 lpdcb->BaudRate = COM[port].baudrate;
254 else
255 lpdcb->BaudRate = atoi(ptr);
256 TRACE(comm,"baudrate (%d)\n", lpdcb->BaudRate);
258 ptr = strtok(NULL, ", ");
259 if (islower(*ptr))
260 *ptr = toupper(*ptr);
262 TRACE(comm,"parity (%c)\n", *ptr);
263 lpdcb->fParity = TRUE;
264 switch (*ptr) {
265 case 'N':
266 lpdcb->Parity = NOPARITY;
267 lpdcb->fParity = FALSE;
268 break;
269 case 'E':
270 lpdcb->Parity = EVENPARITY;
271 break;
272 case 'M':
273 lpdcb->Parity = MARKPARITY;
274 break;
275 case 'O':
276 lpdcb->Parity = ODDPARITY;
277 break;
278 default:
279 WARN(comm,"Unknown parity `%c'!\n", *ptr);
280 return -1;
283 ptr = strtok(NULL, ", ");
284 TRACE(comm, "charsize (%c)\n", *ptr);
285 lpdcb->ByteSize = *ptr - '0';
287 ptr = strtok(NULL, ", ");
288 TRACE(comm, "stopbits (%c)\n", *ptr);
289 switch (*ptr) {
290 case '1':
291 lpdcb->StopBits = ONESTOPBIT;
292 break;
293 case '2':
294 lpdcb->StopBits = TWOSTOPBITS;
295 break;
296 default:
297 WARN(comm,"Unknown # of stopbits `%c'!\n", *ptr);
298 return -1;
302 return 0;
305 /**************************************************************************
306 * BuildCommDCBA (KERNEL32.14)
308 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
310 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
313 /**************************************************************************
314 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
316 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
317 LPCOMMTIMEOUTS lptimeouts)
319 int port;
320 char *ptr,*temp;
322 TRACE(comm,"(%s,%p,%p)\n",device,lpdcb,lptimeouts);
323 commerror = 0;
325 if (!lstrncmpiA(device,"COM",3)) {
326 port=device[3]-'0';
327 if (port--==0) {
328 ERR(comm,"BUG! COM0 can't exists!.\n");
329 return FALSE;
331 if (!ValidCOMPort(port))
332 return FALSE;
333 if (*(device+4)!=':')
334 return FALSE;
335 temp=(LPSTR)(device+5);
336 } else
337 temp=(LPSTR)device;
339 memset(lpdcb, 0, sizeof(DCB)); /* initialize */
341 lpdcb->DCBlength = sizeof(DCB);
342 if (strchr(temp,',')) { /* old style */
343 DCB16 dcb16;
344 BOOL16 ret;
345 char last=temp[strlen(temp)-1];
347 ret=BuildCommDCB16(device,&dcb16);
348 if (!ret)
349 return FALSE;
350 lpdcb->BaudRate = dcb16.BaudRate;
351 lpdcb->ByteSize = dcb16.ByteSize;
352 lpdcb->fBinary = dcb16.fBinary;
353 lpdcb->Parity = dcb16.Parity;
354 lpdcb->fParity = dcb16.fParity;
355 lpdcb->fNull = dcb16.fNull;
356 lpdcb->StopBits = dcb16.StopBits;
357 if (last == 'x') {
358 lpdcb->fInX = TRUE;
359 lpdcb->fOutX = TRUE;
360 lpdcb->fOutxCtsFlow = FALSE;
361 lpdcb->fOutxDsrFlow = FALSE;
362 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
363 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
364 } else if (last=='p') {
365 lpdcb->fInX = FALSE;
366 lpdcb->fOutX = FALSE;
367 lpdcb->fOutxCtsFlow = TRUE;
368 lpdcb->fOutxDsrFlow = TRUE;
369 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
370 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
371 } else {
372 lpdcb->fInX = FALSE;
373 lpdcb->fOutX = FALSE;
374 lpdcb->fOutxCtsFlow = FALSE;
375 lpdcb->fOutxDsrFlow = FALSE;
376 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
377 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
379 lpdcb->XonChar = dcb16.XonChar;
380 lpdcb->XoffChar = dcb16.XoffChar;
381 lpdcb->ErrorChar= dcb16.PeChar;
382 lpdcb->fErrorChar= dcb16.fPeChar;
383 lpdcb->EofChar = dcb16.EofChar;
384 lpdcb->EvtChar = dcb16.EvtChar;
385 lpdcb->XonLim = dcb16.XonLim;
386 lpdcb->XoffLim = dcb16.XoffLim;
387 return TRUE;
389 ptr=strtok(temp," ");
390 while (ptr) {
391 DWORD flag,x;
393 flag=0;
394 if (!strncmp("baud=",ptr,5)) {
395 if (!sscanf(ptr+5,"%ld",&x))
396 WARN(comm,"Couldn't parse %s\n",ptr);
397 lpdcb->BaudRate = x;
398 flag=1;
400 if (!strncmp("stop=",ptr,5)) {
401 if (!sscanf(ptr+5,"%ld",&x))
402 WARN(comm,"Couldn't parse %s\n",ptr);
403 lpdcb->StopBits = x;
404 flag=1;
406 if (!strncmp("data=",ptr,5)) {
407 if (!sscanf(ptr+5,"%ld",&x))
408 WARN(comm,"Couldn't parse %s\n",ptr);
409 lpdcb->ByteSize = x;
410 flag=1;
412 if (!strncmp("parity=",ptr,7)) {
413 lpdcb->fParity = TRUE;
414 switch (ptr[8]) {
415 case 'N':case 'n':
416 lpdcb->fParity = FALSE;
417 lpdcb->Parity = NOPARITY;
418 break;
419 case 'E':case 'e':
420 lpdcb->Parity = EVENPARITY;
421 break;
422 case 'O':case 'o':
423 lpdcb->Parity = ODDPARITY;
424 break;
425 case 'M':case 'm':
426 lpdcb->Parity = MARKPARITY;
427 break;
429 flag=1;
431 if (!flag)
432 ERR(comm,"Unhandled specifier '%s', please report.\n",ptr);
433 ptr=strtok(NULL," ");
435 if (lpdcb->BaudRate==110)
436 lpdcb->StopBits = 2;
437 return TRUE;
440 /**************************************************************************
441 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
443 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
444 LPCOMMTIMEOUTS lptimeouts )
446 LPSTR devidA;
447 BOOL ret;
449 TRACE(comm,"(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
450 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
451 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
452 HeapFree( GetProcessHeap(), 0, devidA );
453 return ret;
456 /**************************************************************************
457 * BuildCommDCBW (KERNEL32.17)
459 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
461 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
464 /*****************************************************************************
465 * OpenComm (USER.200)
467 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
469 int port,fd;
471 TRACE(comm, "%s, %d, %d\n", device, cbInQueue, cbOutQueue);
472 commerror = 0;
474 if (!lstrncmpiA(device,"COM",3)) {
475 port = device[3] - '0';
477 if (port-- == 0) {
478 ERR(comm, "BUG ! COM0 doesn't exist !\n");
479 commerror = IE_BADID;
482 /* to help GetCommError return left buffsize [V] */
483 iGlobalOutQueueFiller = (cbOutQueue - SERIAL_XMIT_SIZE);
484 if (iGlobalOutQueueFiller < 0) iGlobalOutQueueFiller = 0;
486 TRACE(comm, "%s = %s\n", device, COM[port].devicename);
488 if (!ValidCOMPort(port)) {
489 commerror = IE_BADID;
490 return -1;
492 if (COM[port].fd) {
493 return COM[port].fd;
496 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
497 if (fd == -1) {
498 commerror = WinError();
499 return -1;
500 } else {
501 unknown[port] = SEGPTR_ALLOC(40);
502 bzero(unknown[port],40);
503 COM[port].fd = fd;
504 /* save terminal state */
505 tcgetattr(fd,&m_stat[port]);
506 return fd;
509 else
510 if (!lstrncmpiA(device,"LPT",3)) {
511 port = device[3] - '0';
513 if (!ValidLPTPort(port)) {
514 commerror = IE_BADID;
515 return -1;
517 if (LPT[port].fd) {
518 commerror = IE_OPEN;
519 return -1;
522 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
523 if (fd == -1) {
524 commerror = WinError();
525 return -1;
526 } else {
527 LPT[port].fd = fd;
528 return fd;
531 return 0;
534 /*****************************************************************************
535 * CloseComm (USER.207)
537 INT16 WINAPI CloseComm16(INT16 fd)
539 int port;
541 TRACE(comm,"fd %d\n", fd);
542 if ((port = GetCommPort(fd)) !=-1) { /* [LW] */
543 SEGPTR_FREE(unknown[port]);
544 COM[port].fd = 0; /* my adaptation of RER's fix */
545 } else {
546 commerror = IE_BADID;
547 return -1;
550 /* reset modem lines */
551 tcsetattr(fd,TCSANOW,&m_stat[port]);
553 if (close(fd) == -1) {
554 commerror = WinError();
555 return -1;
556 } else {
557 commerror = 0;
558 return 0;
562 /*****************************************************************************
563 * SetCommBreak (USER.210)
565 INT16 WINAPI SetCommBreak16(INT16 fd)
567 struct DosDeviceStruct *ptr;
569 TRACE(comm,"fd=%d\n", fd);
570 if ((ptr = GetDeviceStruct(fd)) == NULL) {
571 commerror = IE_BADID;
572 return -1;
575 ptr->suspended = 1;
576 commerror = 0;
577 return 0;
580 /*****************************************************************************
581 * SetCommBreak (KERNEL32.449)
583 BOOL WINAPI SetCommBreak(INT fd)
586 struct DosDeviceStruct *ptr;
588 TRACE(comm,"fd=%d\n", fd);
589 if ((ptr = GetDeviceStruct(fd)) == NULL) {
590 commerror = IE_BADID;
591 return FALSE;
594 ptr->suspended = 1;
595 commerror = 0;
596 return TRUE;
599 /*****************************************************************************
600 * ClearCommBreak (USER.211)
602 INT16 WINAPI ClearCommBreak16(INT16 fd)
604 struct DosDeviceStruct *ptr;
606 TRACE(comm,"fd=%d\n", fd);
607 if ((ptr = GetDeviceStruct(fd)) == NULL) {
608 commerror = IE_BADID;
609 return -1;
612 ptr->suspended = 0;
613 commerror = 0;
614 return 0;
617 /*****************************************************************************
618 * ClearCommBreak (KERNEL32.20)
620 BOOL WINAPI ClearCommBreak(INT fd)
622 struct DosDeviceStruct *ptr;
624 TRACE(comm,"fd=%d\n", fd);
625 if ((ptr = GetDeviceStruct(fd)) == NULL) {
626 commerror = IE_BADID;
627 return FALSE;
630 ptr->suspended = 0;
631 commerror = 0;
632 return TRUE;
635 /*****************************************************************************
636 * EscapeCommFunction (USER.214)
638 LONG WINAPI EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
640 int max;
641 struct termios port;
643 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
644 if (tcgetattr(fd,&port) == -1) {
645 commerror=WinError();
646 return -1;
649 switch (nFunction) {
650 case RESETDEV:
651 break;
653 case GETMAXCOM:
654 for (max = MAX_PORTS;!COM[max].devicename;max--)
656 return max;
657 break;
659 case GETMAXLPT:
660 for (max = MAX_PORTS;!LPT[max].devicename;max--)
662 return 0x80 + max;
663 break;
665 #ifdef TIOCM_DTR
666 case CLRDTR:
667 port.c_cflag &= TIOCM_DTR;
668 break;
669 #endif
671 #ifdef TIOCM_RTS
672 case CLRRTS:
673 port.c_cflag &= TIOCM_RTS;
674 break;
675 #endif
677 #ifdef CRTSCTS
678 case SETDTR:
679 port.c_cflag |= CRTSCTS;
680 break;
682 case SETRTS:
683 port.c_cflag |= CRTSCTS;
684 break;
685 #endif
687 case SETXOFF:
688 port.c_iflag |= IXOFF;
689 break;
691 case SETXON:
692 port.c_iflag |= IXON;
693 break;
695 default:
696 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
697 fd, nFunction);
698 break;
701 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
702 commerror = WinError();
703 return -1;
704 } else {
705 commerror = 0;
706 return 0;
710 /*****************************************************************************
711 * EscapeCommFunction (KERNEL32.214)
713 BOOL WINAPI EscapeCommFunction(INT fd,UINT nFunction)
715 struct termios port;
716 struct DosDeviceStruct *ptr;
718 TRACE(comm,"fd=%d, function=%d\n", fd, nFunction);
719 if (tcgetattr(fd,&port) == -1) {
720 commerror=WinError();
721 return FALSE;
723 if ((ptr = GetDeviceStruct(fd)) == NULL) {
724 commerror = IE_BADID;
725 return FALSE;
728 switch (nFunction) {
729 case RESETDEV:
730 break;
732 #ifdef TIOCM_DTR
733 case CLRDTR:
734 port.c_cflag &= TIOCM_DTR;
735 break;
736 #endif
738 #ifdef TIOCM_RTS
739 case CLRRTS:
740 port.c_cflag &= TIOCM_RTS;
741 break;
742 #endif
744 #ifdef CRTSCTS
745 case SETDTR:
746 port.c_cflag |= CRTSCTS;
747 break;
749 case SETRTS:
750 port.c_cflag |= CRTSCTS;
751 break;
752 #endif
754 case SETXOFF:
755 port.c_iflag |= IXOFF;
756 break;
758 case SETXON:
759 port.c_iflag |= IXON;
760 break;
761 case SETBREAK:
762 ptr->suspended = 1;
763 break;
764 case CLRBREAK:
765 ptr->suspended = 0;
766 break;
767 default:
768 WARN(comm,"(fd=%d,nFunction=%d): Unknown function\n",
769 fd, nFunction);
770 break;
773 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
774 commerror = WinError();
775 return FALSE;
776 } else {
777 commerror = 0;
778 return TRUE;
782 /*****************************************************************************
783 * FlushComm (USER.215)
785 INT16 WINAPI FlushComm16(INT16 fd,INT16 fnQueue)
787 int queue;
789 TRACE(comm,"fd=%d, queue=%d\n", fd, fnQueue);
790 switch (fnQueue) {
791 case 0: queue = TCOFLUSH;
792 break;
793 case 1: queue = TCIFLUSH;
794 break;
795 default:WARN(comm,"(fd=%d,fnQueue=%d):Unknown queue\n",
796 fd, fnQueue);
797 return -1;
799 if (tcflush(fd, queue)) {
800 commerror = WinError();
801 return -1;
802 } else {
803 commerror = 0;
804 return 0;
808 /********************************************************************
809 * PurgeComm (KERNEL32.557)
811 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
813 int fd;
814 struct get_write_fd_request req;
816 TRACE(comm,"handle %d, flags %lx\n", handle, flags);
818 req.handle = handle;
819 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
820 CLIENT_WaitReply( NULL, &fd, 0 );
822 if(fd<0)
823 return FALSE;
826 ** not exactly sure how these are different
827 ** Perhaps if we had our own internal queues, one flushes them
828 ** and the other flushes the kernel's buffers.
830 if(flags&PURGE_TXABORT)
832 tcflush(fd,TCOFLUSH);
834 if(flags&PURGE_RXABORT)
836 tcflush(fd,TCIFLUSH);
838 if(flags&PURGE_TXCLEAR)
840 tcflush(fd,TCOFLUSH);
842 if(flags&PURGE_RXCLEAR)
844 tcflush(fd,TCIFLUSH);
847 return 1;
850 /********************************************************************
851 * GetCommError (USER.203)
853 INT16 WINAPI GetCommError16(INT16 fd,LPCOMSTAT16 lpStat)
855 int temperror;
856 unsigned long cnt;
857 int rc;
859 unsigned char *stol;
860 int act;
861 unsigned int mstat;
862 if ((act = GetCommPort(fd)) == -1) {
863 WARN(comm," fd %d not comm port\n",fd);
864 return CE_MODE;
866 stol = (unsigned char *)unknown[act] + COMM_MSR_OFFSET;
867 ioctl(fd,TIOCMGET,&mstat);
868 if( mstat&TIOCM_CAR )
869 *stol |= 0x80;
870 else
871 *stol &=0x7f;
873 if (lpStat) {
874 lpStat->status = 0;
876 rc = ioctl(fd, TIOCOUTQ, &cnt);
877 if (rc) WARN(comm, "Error !\n");
878 lpStat->cbOutQue = cnt + iGlobalOutQueueFiller;
880 rc = ioctl(fd, TIOCINQ, &cnt);
881 if (rc) WARN(comm, "Error !\n");
882 lpStat->cbInQue = cnt;
884 TRACE(comm, "fd %d, error %d, lpStat %d %d %d stol %x\n",
885 fd, commerror, lpStat->status, lpStat->cbInQue,
886 lpStat->cbOutQue, *stol);
888 else
889 TRACE(comm, "fd %d, error %d, lpStat NULL stol %x\n",
890 fd, commerror, *stol);
893 * [RER] I have no idea what the following is trying to accomplish.
894 * [RER] It is certainly not what the reference manual suggests.
896 temperror = commerror;
897 commerror = 0;
898 return(temperror);
901 /*****************************************************************************
902 * COMM_Handle2fd
903 * returns a file descriptor for reading from or writing to
904 * mode is GENERIC_READ or GENERIC_WRITE. Make sure to close
905 * the handle afterwards!
907 int COMM_Handle2fd(HANDLE handle, int mode) {
908 struct get_read_fd_request r_req;
909 struct get_write_fd_request w_req;
910 int fd;
912 w_req.handle = r_req.handle = handle;
914 switch(mode) {
915 case GENERIC_WRITE:
916 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &w_req, sizeof(w_req) );
917 break;
918 case GENERIC_READ:
919 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &r_req, sizeof(r_req) );
920 break;
921 default:
922 ERR(comm,"COMM_Handle2fd: Don't know what type of fd is required.\n");
923 return -1;
925 CLIENT_WaitReply( NULL, &fd, 0 );
927 return fd;
930 /*****************************************************************************
931 * ClearCommError (KERNEL32.21)
933 BOOL WINAPI ClearCommError(INT handle,LPDWORD errors,LPCOMSTAT lpStat)
935 int fd;
937 fd=COMM_Handle2fd(handle,GENERIC_READ);
938 if(0>fd)
940 return FALSE;
943 if (lpStat)
945 lpStat->status = 0;
947 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
948 WARN(comm, "ioctl returned error\n");
950 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
951 WARN(comm, "ioctl returned error\n");
954 close(fd);
956 TRACE(comm,"handle %d cbInQue = %ld cbOutQue = %ld\n",
957 handle,
958 lpStat->cbInQue,
959 lpStat->cbOutQue);
961 if(errors)
962 *errors = 0;
965 ** After an asynchronous write opperation, the
966 ** app will call ClearCommError to see if the
967 ** results are ready yet. It waits for ERROR_IO_PENDING
969 commerror = ERROR_IO_PENDING;
971 return TRUE;
974 /*****************************************************************************
975 * SetCommEventMask (USER.208)
977 SEGPTR WINAPI SetCommEventMask16(INT16 fd,UINT16 fuEvtMask)
979 unsigned char *stol;
980 int act;
981 int repid;
982 unsigned int mstat;
983 TRACE(comm,"fd %d,mask %d\n",fd,fuEvtMask);
984 eventmask |= fuEvtMask;
985 if ((act = GetCommPort(fd)) == -1) {
986 WARN(comm," fd %d not comm port\n",act);
987 return SEGPTR_GET(NULL);
989 stol = (unsigned char *)unknown[act];
990 stol += COMM_MSR_OFFSET;
991 repid = ioctl(fd,TIOCMGET,&mstat);
992 TRACE(comm, " ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[act]);
993 if ((mstat&TIOCM_CAR)) {*stol |= 0x80;}
994 else {*stol &=0x7f;}
995 TRACE(comm," modem dcd construct %x\n",*stol);
996 return SEGPTR_GET(unknown[act]);
999 /*****************************************************************************
1000 * GetCommEventMask (USER.209)
1002 UINT16 WINAPI GetCommEventMask16(INT16 fd,UINT16 fnEvtClear)
1004 int events = 0;
1006 TRACE(comm, "fd %d, mask %d\n", fd, fnEvtClear);
1009 * Determine if any characters are available
1011 if (fnEvtClear & EV_RXCHAR)
1013 int rc;
1014 unsigned long cnt;
1016 rc = ioctl(fd, TIOCINQ, &cnt);
1017 if (cnt) events |= EV_RXCHAR;
1019 TRACE(comm, "rxchar %ld\n", cnt);
1023 * There are other events that need to be checked for
1025 /* TODO */
1027 TRACE(comm, "return events %d\n", events);
1028 return events;
1031 * [RER] The following was gibberish
1033 #if 0
1034 tempmask = eventmask;
1035 eventmask &= ~fnEvtClear;
1036 return eventmask;
1037 #endif
1040 /*****************************************************************************
1041 * SetupComm (KERNEL32.676)
1043 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1045 int fd;
1047 FIXME(comm, "insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1048 fd=COMM_Handle2fd(handle,GENERIC_WRITE);
1049 if(0>fd)
1051 return FALSE;
1053 close(fd);
1054 return TRUE;
1057 /*****************************************************************************
1058 * GetCommMask (KERNEL32.156)
1060 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1062 int fd;
1064 TRACE(comm, "handle %d, mask %p\n", handle, evtmask);
1065 if(0>(fd=COMM_Handle2fd(handle,GENERIC_READ)))
1067 return FALSE;
1069 close(fd);
1070 *evtmask = eventmask;
1071 return TRUE;
1074 /*****************************************************************************
1075 * SetCommMask (KERNEL32.451)
1077 BOOL WINAPI SetCommMask(INT handle,DWORD evtmask)
1079 int fd;
1081 TRACE(comm, "handle %d, mask %lx\n", handle, evtmask);
1082 if(0>(fd=COMM_Handle2fd(handle,GENERIC_WRITE))) {
1083 return FALSE;
1085 close(fd);
1086 eventmask = evtmask;
1087 return TRUE;
1090 /*****************************************************************************
1091 * SetCommState16 (USER.201)
1093 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
1095 struct termios port;
1096 struct DosDeviceStruct *ptr;
1098 TRACE(comm, "fd %d, ptr %p\n", lpdcb->Id, lpdcb);
1099 if (tcgetattr(lpdcb->Id, &port) == -1) {
1100 commerror = WinError();
1101 return -1;
1104 port.c_cc[VMIN] = 0;
1105 port.c_cc[VTIME] = 1;
1107 #ifdef IMAXBEL
1108 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1109 #else
1110 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1111 #endif
1112 port.c_iflag |= (IGNBRK);
1114 port.c_oflag &= ~(OPOST);
1116 port.c_cflag &= ~(HUPCL);
1117 port.c_cflag |= CLOCAL | CREAD;
1119 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1120 port.c_lflag |= NOFLSH;
1122 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
1123 commerror = IE_BADID;
1124 return -1;
1126 if (ptr->baudrate > 0)
1127 lpdcb->BaudRate = ptr->baudrate;
1128 TRACE(comm,"baudrate %d\n",lpdcb->BaudRate);
1129 #ifdef CBAUD
1130 port.c_cflag &= ~CBAUD;
1131 switch (lpdcb->BaudRate) {
1132 case 110:
1133 case CBR_110:
1134 port.c_cflag |= B110;
1135 break;
1136 case 300:
1137 case CBR_300:
1138 port.c_cflag |= B300;
1139 break;
1140 case 600:
1141 case CBR_600:
1142 port.c_cflag |= B600;
1143 break;
1144 case 1200:
1145 case CBR_1200:
1146 port.c_cflag |= B1200;
1147 break;
1148 case 2400:
1149 case CBR_2400:
1150 port.c_cflag |= B2400;
1151 break;
1152 case 4800:
1153 case CBR_4800:
1154 port.c_cflag |= B4800;
1155 break;
1156 case 9600:
1157 case CBR_9600:
1158 port.c_cflag |= B9600;
1159 break;
1160 case 19200:
1161 case CBR_19200:
1162 port.c_cflag |= B19200;
1163 break;
1164 case 38400:
1165 case CBR_38400:
1166 port.c_cflag |= B38400;
1167 break;
1168 #ifdef B57600
1169 case 57600:
1170 port.c_cflag |= B57600;
1171 break;
1172 #endif
1173 #ifdef B115200
1174 case 57601:
1175 port.c_cflag |= B115200;
1176 break;
1177 #endif
1178 default:
1179 commerror = IE_BAUDRATE;
1180 return -1;
1182 #elif !defined(__EMX__)
1183 switch (lpdcb->BaudRate) {
1184 case 110:
1185 case CBR_110:
1186 port.c_ospeed = B110;
1187 break;
1188 case 300:
1189 case CBR_300:
1190 port.c_ospeed = B300;
1191 break;
1192 case 600:
1193 case CBR_600:
1194 port.c_ospeed = B600;
1195 break;
1196 case 1200:
1197 case CBR_1200:
1198 port.c_ospeed = B1200;
1199 break;
1200 case 2400:
1201 case CBR_2400:
1202 port.c_ospeed = B2400;
1203 break;
1204 case 4800:
1205 case CBR_4800:
1206 port.c_ospeed = B4800;
1207 break;
1208 case 9600:
1209 case CBR_9600:
1210 port.c_ospeed = B9600;
1211 break;
1212 case 19200:
1213 case CBR_19200:
1214 port.c_ospeed = B19200;
1215 break;
1216 case 38400:
1217 case CBR_38400:
1218 port.c_ospeed = B38400;
1219 break;
1220 default:
1221 commerror = IE_BAUDRATE;
1222 return -1;
1224 port.c_ispeed = port.c_ospeed;
1225 #endif
1226 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1227 port.c_cflag &= ~CSIZE;
1228 switch (lpdcb->ByteSize) {
1229 case 5:
1230 port.c_cflag |= CS5;
1231 break;
1232 case 6:
1233 port.c_cflag |= CS6;
1234 break;
1235 case 7:
1236 port.c_cflag |= CS7;
1237 break;
1238 case 8:
1239 port.c_cflag |= CS8;
1240 break;
1241 default:
1242 commerror = IE_BYTESIZE;
1243 return -1;
1246 TRACE(comm,"parity %d\n",lpdcb->Parity);
1247 port.c_cflag &= ~(PARENB | PARODD);
1248 if (lpdcb->fParity)
1249 switch (lpdcb->Parity) {
1250 case NOPARITY:
1251 port.c_iflag &= ~INPCK;
1252 break;
1253 case ODDPARITY:
1254 port.c_cflag |= (PARENB | PARODD);
1255 port.c_iflag |= INPCK;
1256 break;
1257 case EVENPARITY:
1258 port.c_cflag |= PARENB;
1259 port.c_iflag |= INPCK;
1260 break;
1261 default:
1262 commerror = IE_BYTESIZE;
1263 return -1;
1267 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1269 switch (lpdcb->StopBits) {
1270 case ONESTOPBIT:
1271 port.c_cflag &= ~CSTOPB;
1272 break;
1273 case TWOSTOPBITS:
1274 port.c_cflag |= CSTOPB;
1275 break;
1276 default:
1277 commerror = IE_BYTESIZE;
1278 return -1;
1280 #ifdef CRTSCTS
1282 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1283 port.c_cflag |= CRTSCTS;
1285 if (lpdcb->fDtrDisable)
1286 port.c_cflag &= ~CRTSCTS;
1287 #endif
1288 if (lpdcb->fInX)
1289 port.c_iflag |= IXON;
1290 else
1291 port.c_iflag &= ~IXON;
1292 if (lpdcb->fOutX)
1293 port.c_iflag |= IXOFF;
1294 else
1295 port.c_iflag &= ~IXOFF;
1297 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
1298 commerror = WinError();
1299 return FALSE;
1300 } else {
1301 commerror = 0;
1302 return 0;
1306 /*****************************************************************************
1307 * SetCommState (KERNEL32.452)
1309 BOOL WINAPI SetCommState(INT handle,LPDCB lpdcb)
1311 struct termios port;
1312 int fd;
1313 struct get_write_fd_request req;
1315 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1317 req.handle = handle;
1318 CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
1319 CLIENT_WaitReply( NULL, &fd, 0 );
1321 if(fd<0)
1322 return FALSE;
1324 if (tcgetattr(fd,&port) == -1) {
1325 commerror = WinError();
1326 return FALSE;
1329 port.c_cc[VMIN] = 0;
1330 port.c_cc[VTIME] = 1;
1332 #ifdef IMAXBEL
1333 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1334 #else
1335 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1336 #endif
1337 port.c_iflag |= (IGNBRK);
1339 port.c_oflag &= ~(OPOST);
1341 port.c_cflag &= ~(HUPCL);
1342 port.c_cflag |= CLOCAL | CREAD;
1344 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1345 port.c_lflag |= NOFLSH;
1348 ** MJM - removed default baudrate settings
1349 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
1351 #ifdef CBAUD
1352 port.c_cflag &= ~CBAUD;
1353 switch (lpdcb->BaudRate) {
1354 case 110:
1355 case CBR_110:
1356 port.c_cflag |= B110;
1357 break;
1358 case 300:
1359 case CBR_300:
1360 port.c_cflag |= B300;
1361 break;
1362 case 600:
1363 case CBR_600:
1364 port.c_cflag |= B600;
1365 break;
1366 case 1200:
1367 case CBR_1200:
1368 port.c_cflag |= B1200;
1369 break;
1370 case 2400:
1371 case CBR_2400:
1372 port.c_cflag |= B2400;
1373 break;
1374 case 4800:
1375 case CBR_4800:
1376 port.c_cflag |= B4800;
1377 break;
1378 case 9600:
1379 case CBR_9600:
1380 port.c_cflag |= B9600;
1381 break;
1382 case 19200:
1383 case CBR_19200:
1384 port.c_cflag |= B19200;
1385 break;
1386 case 38400:
1387 case CBR_38400:
1388 port.c_cflag |= B38400;
1389 break;
1390 default:
1391 commerror = IE_BAUDRATE;
1392 return FALSE;
1394 #elif !defined(__EMX__)
1395 switch (lpdcb->BaudRate) {
1396 case 110:
1397 case CBR_110:
1398 port.c_ospeed = B110;
1399 break;
1400 case 300:
1401 case CBR_300:
1402 port.c_ospeed = B300;
1403 break;
1404 case 600:
1405 case CBR_600:
1406 port.c_ospeed = B600;
1407 break;
1408 case 1200:
1409 case CBR_1200:
1410 port.c_ospeed = B1200;
1411 break;
1412 case 2400:
1413 case CBR_2400:
1414 port.c_ospeed = B2400;
1415 break;
1416 case 4800:
1417 case CBR_4800:
1418 port.c_ospeed = B4800;
1419 break;
1420 case 9600:
1421 case CBR_9600:
1422 port.c_ospeed = B9600;
1423 break;
1424 case 19200:
1425 case CBR_19200:
1426 port.c_ospeed = B19200;
1427 break;
1428 case 38400:
1429 case CBR_38400:
1430 port.c_ospeed = B38400;
1431 break;
1432 default:
1433 commerror = IE_BAUDRATE;
1434 return FALSE;
1436 port.c_ispeed = port.c_ospeed;
1437 #endif
1438 TRACE(comm,"bytesize %d\n",lpdcb->ByteSize);
1439 port.c_cflag &= ~CSIZE;
1440 switch (lpdcb->ByteSize) {
1441 case 5:
1442 port.c_cflag |= CS5;
1443 break;
1444 case 6:
1445 port.c_cflag |= CS6;
1446 break;
1447 case 7:
1448 port.c_cflag |= CS7;
1449 break;
1450 case 8:
1451 port.c_cflag |= CS8;
1452 break;
1453 default:
1454 commerror = IE_BYTESIZE;
1455 return FALSE;
1458 TRACE(comm,"parity %d\n",lpdcb->Parity);
1459 port.c_cflag &= ~(PARENB | PARODD);
1460 if (lpdcb->fParity)
1461 switch (lpdcb->Parity) {
1462 case NOPARITY:
1463 port.c_iflag &= ~INPCK;
1464 break;
1465 case ODDPARITY:
1466 port.c_cflag |= (PARENB | PARODD);
1467 port.c_iflag |= INPCK;
1468 break;
1469 case EVENPARITY:
1470 port.c_cflag |= PARENB;
1471 port.c_iflag |= INPCK;
1472 break;
1473 default:
1474 commerror = IE_BYTESIZE;
1475 return FALSE;
1479 TRACE(comm,"stopbits %d\n",lpdcb->StopBits);
1480 switch (lpdcb->StopBits) {
1481 case ONESTOPBIT:
1482 port.c_cflag &= ~CSTOPB;
1483 break;
1484 case TWOSTOPBITS:
1485 port.c_cflag |= CSTOPB;
1486 break;
1487 default:
1488 commerror = IE_BYTESIZE;
1489 return FALSE;
1491 #ifdef CRTSCTS
1492 if ( lpdcb->fOutxCtsFlow ||
1493 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1494 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1496 port.c_cflag |= CRTSCTS;
1497 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1498 port.c_cflag &= ~CRTSCTS;
1500 #endif
1501 if (lpdcb->fInX)
1502 port.c_iflag |= IXON;
1503 else
1504 port.c_iflag &= ~IXON;
1505 if (lpdcb->fOutX)
1506 port.c_iflag |= IXOFF;
1507 else
1508 port.c_iflag &= ~IXOFF;
1510 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1511 commerror = WinError();
1512 return FALSE;
1513 } else {
1514 commerror = 0;
1515 return TRUE;
1520 /*****************************************************************************
1521 * GetCommState (USER.202)
1523 INT16 WINAPI GetCommState16(INT16 fd, LPDCB16 lpdcb)
1525 struct termios port;
1527 TRACE(comm,"fd %d, ptr %p\n", fd, lpdcb);
1528 if (tcgetattr(fd, &port) == -1) {
1529 commerror = WinError();
1530 return -1;
1532 lpdcb->Id = fd;
1533 #ifndef __EMX__
1534 #ifdef CBAUD
1535 switch (port.c_cflag & CBAUD) {
1536 #else
1537 switch (port.c_ospeed) {
1538 #endif
1539 case B110:
1540 lpdcb->BaudRate = 110;
1541 break;
1542 case B300:
1543 lpdcb->BaudRate = 300;
1544 break;
1545 case B600:
1546 lpdcb->BaudRate = 600;
1547 break;
1548 case B1200:
1549 lpdcb->BaudRate = 1200;
1550 break;
1551 case B2400:
1552 lpdcb->BaudRate = 2400;
1553 break;
1554 case B4800:
1555 lpdcb->BaudRate = 4800;
1556 break;
1557 case B9600:
1558 lpdcb->BaudRate = 9600;
1559 break;
1560 case B19200:
1561 lpdcb->BaudRate = 19200;
1562 break;
1563 case B38400:
1564 lpdcb->BaudRate = 38400;
1565 break;
1566 #ifdef B57600
1567 case B57600:
1568 lpdcb->BaudRate = 57600;
1569 break;
1570 #endif
1571 #ifdef B115200
1572 case B115200:
1573 lpdcb->BaudRate = 57601;
1574 break;
1575 #endif
1577 #endif
1578 switch (port.c_cflag & CSIZE) {
1579 case CS5:
1580 lpdcb->ByteSize = 5;
1581 break;
1582 case CS6:
1583 lpdcb->ByteSize = 6;
1584 break;
1585 case CS7:
1586 lpdcb->ByteSize = 7;
1587 break;
1588 case CS8:
1589 lpdcb->ByteSize = 8;
1590 break;
1593 switch (port.c_cflag & (PARENB | PARODD)) {
1594 case 0:
1595 lpdcb->fParity = FALSE;
1596 lpdcb->Parity = NOPARITY;
1597 break;
1598 case PARENB:
1599 lpdcb->fParity = TRUE;
1600 lpdcb->Parity = EVENPARITY;
1601 break;
1602 case (PARENB | PARODD):
1603 lpdcb->fParity = TRUE;
1604 lpdcb->Parity = ODDPARITY;
1605 break;
1608 if (port.c_cflag & CSTOPB)
1609 lpdcb->StopBits = TWOSTOPBITS;
1610 else
1611 lpdcb->StopBits = ONESTOPBIT;
1613 lpdcb->RlsTimeout = 50;
1614 lpdcb->CtsTimeout = 50;
1615 lpdcb->DsrTimeout = 50;
1616 lpdcb->fNull = 0;
1617 lpdcb->fChEvt = 0;
1618 lpdcb->fBinary = 1;
1619 lpdcb->fDtrDisable = 0;
1621 #ifdef CRTSCTS
1623 if (port.c_cflag & CRTSCTS) {
1624 lpdcb->fDtrflow = 1;
1625 lpdcb->fRtsflow = 1;
1626 lpdcb->fOutxCtsFlow = 1;
1627 lpdcb->fOutxDsrFlow = 1;
1628 } else
1629 #endif
1630 lpdcb->fDtrDisable = 1;
1632 if (port.c_iflag & IXON)
1633 lpdcb->fInX = 1;
1634 else
1635 lpdcb->fInX = 0;
1637 if (port.c_iflag & IXOFF)
1638 lpdcb->fOutX = 1;
1639 else
1640 lpdcb->fOutX = 0;
1642 lpdcb->XonChar =
1643 lpdcb->XoffChar =
1645 lpdcb->XonLim = 10;
1646 lpdcb->XoffLim = 10;
1648 commerror = 0;
1649 return 0;
1652 /*****************************************************************************
1653 * GetCommState (KERNEL32.159)
1655 BOOL WINAPI GetCommState(INT handle, LPDCB lpdcb)
1657 struct termios port;
1658 int fd;
1659 struct get_read_fd_request req;
1661 TRACE(comm,"handle %d, ptr %p\n", handle, lpdcb);
1662 req.handle = handle;
1663 CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
1664 CLIENT_WaitReply( NULL, &fd, 0 );
1666 if(fd<0)
1667 return FALSE;
1669 if (tcgetattr(fd, &port) == -1) {
1670 TRACE(comm,"tcgetattr(%d, ...) returned -1",fd);
1671 commerror = WinError();
1672 return FALSE;
1674 #ifndef __EMX__
1675 #ifdef CBAUD
1676 switch (port.c_cflag & CBAUD) {
1677 #else
1678 switch (port.c_ospeed) {
1679 #endif
1680 case B110:
1681 lpdcb->BaudRate = 110;
1682 break;
1683 case B300:
1684 lpdcb->BaudRate = 300;
1685 break;
1686 case B600:
1687 lpdcb->BaudRate = 600;
1688 break;
1689 case B1200:
1690 lpdcb->BaudRate = 1200;
1691 break;
1692 case B2400:
1693 lpdcb->BaudRate = 2400;
1694 break;
1695 case B4800:
1696 lpdcb->BaudRate = 4800;
1697 break;
1698 case B9600:
1699 lpdcb->BaudRate = 9600;
1700 break;
1701 case B19200:
1702 lpdcb->BaudRate = 19200;
1703 break;
1704 case B38400:
1705 lpdcb->BaudRate = 38400;
1706 break;
1708 #endif
1709 switch (port.c_cflag & CSIZE) {
1710 case CS5:
1711 lpdcb->ByteSize = 5;
1712 break;
1713 case CS6:
1714 lpdcb->ByteSize = 6;
1715 break;
1716 case CS7:
1717 lpdcb->ByteSize = 7;
1718 break;
1719 case CS8:
1720 lpdcb->ByteSize = 8;
1721 break;
1724 switch (port.c_cflag & (PARENB | PARODD)) {
1725 case 0:
1726 lpdcb->fParity = FALSE;
1727 lpdcb->Parity = NOPARITY;
1728 break;
1729 case PARENB:
1730 lpdcb->fParity = TRUE;
1731 lpdcb->Parity = EVENPARITY;
1732 break;
1733 case (PARENB | PARODD):
1734 lpdcb->fParity = TRUE;
1735 lpdcb->Parity = ODDPARITY;
1736 break;
1739 if (port.c_cflag & CSTOPB)
1740 lpdcb->StopBits = TWOSTOPBITS;
1741 else
1742 lpdcb->StopBits = ONESTOPBIT;
1744 lpdcb->fNull = 0;
1745 lpdcb->fBinary = 1;
1747 #ifdef CRTSCTS
1749 if (port.c_cflag & CRTSCTS) {
1750 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1751 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1752 lpdcb->fOutxCtsFlow = 1;
1753 lpdcb->fOutxDsrFlow = 1;
1754 } else
1755 #endif
1757 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1758 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1760 if (port.c_iflag & IXON)
1761 lpdcb->fInX = 1;
1762 else
1763 lpdcb->fInX = 0;
1765 if (port.c_iflag & IXOFF)
1766 lpdcb->fOutX = 1;
1767 else
1768 lpdcb->fOutX = 0;
1770 lpdcb->XonChar =
1771 lpdcb->XoffChar =
1773 lpdcb->XonLim = 10;
1774 lpdcb->XoffLim = 10;
1776 commerror = 0;
1778 TRACE(comm,"OK\n");
1780 return TRUE;
1783 /*****************************************************************************
1784 * TransmitCommChar (USER.206)
1786 INT16 WINAPI TransmitCommChar16(INT16 fd,CHAR chTransmit)
1788 struct DosDeviceStruct *ptr;
1790 TRACE(comm, "fd %d, data %d \n", fd, chTransmit);
1791 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1792 commerror = IE_BADID;
1793 return -1;
1796 if (ptr->suspended) {
1797 commerror = IE_HARDWARE;
1798 return -1;
1801 if (write(fd, (void *) &chTransmit, 1) == -1) {
1802 commerror = WinError();
1803 return -1;
1804 } else {
1805 commerror = 0;
1806 return 0;
1810 /*****************************************************************************
1811 * TransmitCommChar (KERNEL32.535)
1813 BOOL WINAPI TransmitCommChar(INT fd,CHAR chTransmit)
1815 struct DosDeviceStruct *ptr;
1817 TRACE(comm,"(%d,'%c')\n",fd,chTransmit);
1818 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1819 commerror = IE_BADID;
1820 return FALSE;
1823 if (ptr->suspended) {
1824 commerror = IE_HARDWARE;
1825 return FALSE;
1827 if (write(fd, (void *) &chTransmit, 1) == -1) {
1828 commerror = WinError();
1829 return FALSE;
1830 } else {
1831 commerror = 0;
1832 return TRUE;
1836 /*****************************************************************************
1837 * UngetCommChar (USER.212)
1839 INT16 WINAPI UngetCommChar16(INT16 fd,CHAR chUnget)
1841 struct DosDeviceStruct *ptr;
1843 TRACE(comm,"fd %d (char %d)\n", fd, chUnget);
1844 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1845 commerror = IE_BADID;
1846 return -1;
1849 if (ptr->suspended) {
1850 commerror = IE_HARDWARE;
1851 return -1;
1854 ptr->unget = 1;
1855 ptr->unget_byte = chUnget;
1856 commerror = 0;
1857 return 0;
1860 /*****************************************************************************
1861 * ReadComm (USER.204)
1863 INT16 WINAPI ReadComm16(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1865 int status, length;
1866 struct DosDeviceStruct *ptr;
1868 TRACE(comm, "fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1869 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1870 commerror = IE_BADID;
1871 return -1;
1874 if (ptr->suspended) {
1875 commerror = IE_HARDWARE;
1876 return -1;
1879 if (ptr->unget) {
1880 *lpvBuf = ptr->unget_byte;
1881 lpvBuf++;
1882 ptr->unget = 0;
1884 length = 1;
1885 } else
1886 length = 0;
1888 status = read(fd, (void *) lpvBuf, cbRead);
1890 if (status == -1) {
1891 if (errno != EAGAIN) {
1892 commerror = WinError();
1893 return -1 - length;
1894 } else {
1895 commerror = 0;
1896 return length;
1898 } else {
1899 TRACE(comm,"%.*s\n", length+status, lpvBuf);
1900 commerror = 0;
1901 return length + status;
1905 /*****************************************************************************
1906 * WriteComm (USER.205)
1908 INT16 WINAPI WriteComm16(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1910 int length;
1911 struct DosDeviceStruct *ptr;
1913 TRACE(comm,"fd %d, ptr %p, length %d\n",
1914 fd, lpvBuf, cbWrite);
1915 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1916 commerror = IE_BADID;
1917 return -1;
1920 if (ptr->suspended) {
1921 commerror = IE_HARDWARE;
1922 return -1;
1925 TRACE(comm,"%.*s\n", cbWrite, lpvBuf );
1926 length = write(fd, (void *) lpvBuf, cbWrite);
1928 if (length == -1) {
1929 commerror = WinError();
1930 return -1;
1931 } else {
1932 commerror = 0;
1933 return length;
1938 /*****************************************************************************
1939 * GetCommTimeouts (KERNEL32.160)
1941 BOOL WINAPI GetCommTimeouts(INT fd,LPCOMMTIMEOUTS lptimeouts)
1943 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1944 return TRUE;
1947 /*****************************************************************************
1948 * SetCommTimeouts (KERNEL32.453)
1950 BOOL WINAPI SetCommTimeouts(INT fd,LPCOMMTIMEOUTS lptimeouts) {
1951 FIXME(comm,"(%x,%p):stub.\n",fd,lptimeouts);
1952 return TRUE;
1955 /***********************************************************************
1956 * EnableCommNotification (USER.246)
1958 BOOL16 WINAPI EnableCommNotification16( INT16 fd, HWND16 hwnd,
1959 INT16 cbWriteNotify, INT16 cbOutQueue )
1961 FIXME(comm, "(%d, %x, %d, %d):stub.\n", fd, hwnd, cbWriteNotify, cbOutQueue);
1962 return TRUE;
1965 /***********************************************************************
1966 * GetCommModemStatus (KERNEL32.285)
1968 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
1970 FIXME(comm, "(%d %p)\n",hFile,lpModemStat );
1971 return TRUE;
1973 /***********************************************************************
1974 * WaitCommEvent (KERNEL32.719)
1976 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
1978 FIXME(comm, "(%d %p %p )\n",hFile, eventmask,overlapped);
1979 return TRUE;
1982 /***********************************************************************
1983 * GetCommProperties (KERNEL32.???)
1985 BOOL WINAPI GetCommProperties(HANDLE hFile, LPDCB *dcb)
1987 FIXME(comm, "(%d %p )\n",hFile,dcb);
1988 return TRUE;
1991 /***********************************************************************
1992 * SetCommProperties (KERNEL32.???)
1994 BOOL WINAPI SetCommProperties(HANDLE hFile, LPDCB dcb)
1996 FIXME(comm, "(%d %p )\n",hFile,dcb);
1997 return TRUE;