Removed some unnecessary #includes and dll dependencies.
[wine/multimedia.git] / misc / comm.c
blob7596a3148a8eba65442abda3f1c6de09484d9f2c
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
6 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
7 * - Implemented buffers and EnableCommNotification.
9 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
10 * - Fixed the modem control part of EscapeCommFunction16.
12 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
13 * - Use port indices instead of unixfds for win16
14 * - Moved things around (separated win16 and win32 routines)
15 * - Added some hints on how to implement buffers and EnableCommNotification.
17 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
18 * - ptr->fd wasn't getting cleared on close.
19 * - GetCommEventMask() and GetCommError() didn't do much of anything.
20 * IMHO, they are still wrong, but they at least implement the RXCHAR
21 * event and return I/O queue sizes, which makes the app I'm interested
22 * in (analog devices EZKIT DSP development system) work.
24 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
25 * <lawson_whitney@juno.com>
26 * July 6, 1998. Fixes and comments by Valentijn Sessink
27 * <vsessink@ic.uva.nl> [V]
28 * Oktober 98, Rein Klazes [RHK]
29 * A program that wants to monitor the modem status line (RLSD/DCD) may
30 * poll the modem status register in the commMask structure. I update the bit
31 * in GetCommError, waiting for an implementation of communication events.
35 #include "config.h"
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <termios.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #ifdef HAVE_STRINGS_H
43 # include <strings.h>
44 #endif
45 #include <errno.h>
46 #include <ctype.h>
47 #include <sys/stat.h>
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
50 #endif
51 #include <sys/ioctl.h>
52 #include <unistd.h>
54 #include "windef.h"
55 #include "comm.h"
56 #ifdef HAVE_SYS_MODEM_H
57 # include <sys/modem.h>
58 #endif
59 #ifdef HAVE_SYS_STRTIO_H
60 # include <sys/strtio.h>
61 #endif
62 #include "heap.h"
63 #include "options.h"
65 #include "server.h"
66 #include "winerror.h"
67 #include "services.h"
68 #include "callback.h"
69 #include "file.h"
71 #include "debugtools.h"
73 DEFAULT_DEBUG_CHANNEL(comm);
75 #ifndef TIOCINQ
76 #define TIOCINQ FIONREAD
77 #endif
79 /* window's semi documented modem status register */
80 #define COMM_MSR_OFFSET 35
81 #define MSR_CTS 0x10
82 #define MSR_DSR 0x20
83 #define MSR_RI 0x40
84 #define MSR_RLSD 0x80
85 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
87 #define FLAG_LPT 0x80
89 #ifdef linux
90 #define CMSPAR 0x40000000 /* stick parity */
91 #endif
93 struct DosDeviceStruct COM[MAX_PORTS];
94 struct DosDeviceStruct LPT[MAX_PORTS];
95 /* pointers to unknown(==undocumented) comm structure */
96 LPCVOID *unknown[MAX_PORTS];
97 /* save terminal states */
98 static struct termios m_stat[MAX_PORTS];
100 /* update window's semi documented modem status register */
101 /* see knowledge base Q101417 */
102 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
104 UCHAR tmpmsr=0;
105 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
106 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
107 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
108 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
109 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
112 void COMM_Init(void)
114 int x;
115 char option[10], temp[256], *btemp;
116 struct stat st;
118 for (x=0; x!=MAX_PORTS; x++) {
119 strcpy(option,"COMx");
120 option[3] = '1' + x;
121 option[4] = '\0';
123 PROFILE_GetWineIniString( "serialports", option, "*",
124 temp, sizeof(temp) );
125 if (!strcmp(temp, "*") || *temp == '\0')
126 COM[x].devicename = NULL;
127 else {
128 btemp = strchr(temp,',');
129 if (btemp != NULL) {
130 *btemp++ = '\0';
131 COM[x].baudrate = atoi(btemp);
132 } else {
133 COM[x].baudrate = -1;
135 stat(temp, &st);
136 if (!S_ISCHR(st.st_mode))
137 WARN("Can't use `%s' as %s !\n", temp, option);
138 else
139 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
140 WARN("Can't malloc for device info!\n");
141 else {
142 COM[x].fd = 0;
143 strcpy(COM[x].devicename, temp);
145 TRACE("%s = %s\n", option, COM[x].devicename);
148 strcpy(option, "LPTx");
149 option[3] = '1' + x;
150 option[4] = '\0';
152 PROFILE_GetWineIniString( "parallelports", option, "*",
153 temp, sizeof(temp) );
154 if (!strcmp(temp, "*") || *temp == '\0')
155 LPT[x].devicename = NULL;
156 else {
157 stat(temp, &st);
158 if (!S_ISCHR(st.st_mode))
159 WARN("Can't use `%s' as %s !\n", temp, option);
160 else
161 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
162 WARN("Can't malloc for device info!\n");
163 else {
164 LPT[x].fd = 0;
165 strcpy(LPT[x].devicename, temp);
167 TRACE("%s = %s\n", option, LPT[x].devicename);
174 static struct DosDeviceStruct *GetDeviceStruct(int fd)
176 if ((fd&0x7F)<=MAX_PORTS) {
177 if (!(fd&FLAG_LPT)) {
178 if (COM[fd].fd)
179 return &COM[fd];
180 } else {
181 fd &= 0x7f;
182 if (LPT[fd].fd)
183 return &LPT[fd];
187 return NULL;
190 static int GetCommPort_fd(int fd)
192 int x;
194 for (x=0; x<MAX_PORTS; x++) {
195 if (COM[x].fd == fd)
196 return x;
199 return -1;
202 static int ValidCOMPort(int x)
204 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
207 static int ValidLPTPort(int x)
209 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
212 static int WinError(void)
214 TRACE("errno = %d\n", errno);
215 switch (errno) {
216 default:
217 return CE_IOE;
221 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
223 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
224 + ptr->ibuf_head - ptr->ibuf_tail;
227 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
229 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
230 + ptr->obuf_head - ptr->obuf_tail;
233 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
235 unsigned int mstat, okay;
236 okay = ioctl(fd, TIOCMGET, &mstat);
237 if (okay) return okay;
238 if (andy) mstat &= andy;
239 mstat |= orrie;
240 return ioctl(fd, TIOCMSET, &mstat);
243 static void CALLBACK comm_notification( ULONG_PTR private )
245 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
246 int prev, bleft, len;
247 WORD mask = 0;
248 int cid = GetCommPort_fd(ptr->fd);
250 TRACE("async notification\n");
251 /* read data from comm port */
252 prev = comm_inbuf(ptr);
253 do {
254 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
255 - ptr->ibuf_head;
256 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
257 if (len > 0) {
258 if (!bleft) {
259 ptr->commerror = CE_RXOVER;
260 } else {
261 /* check for events */
262 if ((ptr->eventmask & EV_RXFLAG) &&
263 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
264 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
265 mask |= CN_EVENT;
267 if (ptr->eventmask & EV_RXCHAR) {
268 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
269 mask |= CN_EVENT;
271 /* advance buffer position */
272 ptr->ibuf_head += len;
273 if (ptr->ibuf_head >= ptr->ibuf_size)
274 ptr->ibuf_head = 0;
277 } while (len > 0);
278 /* check for notification */
279 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
280 (comm_inbuf(ptr)>=ptr->n_read)) {
281 /* passed the receive notification threshold */
282 mask |= CN_RECEIVE;
285 /* write any TransmitCommChar character */
286 if (ptr->xmit>=0) {
287 len = write(ptr->fd, &(ptr->xmit), 1);
288 if (len > 0) ptr->xmit = -1;
290 /* write from output queue */
291 prev = comm_outbuf(ptr);
292 do {
293 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
294 - ptr->obuf_tail;
295 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
296 if (len > 0) {
297 ptr->obuf_tail += len;
298 if (ptr->obuf_tail >= ptr->obuf_size)
299 ptr->obuf_tail = 0;
300 /* flag event */
301 if (ptr->obuf_tail == ptr->obuf_head) {
302 if (ptr->s_write) {
303 SERVICE_Delete( ptr->s_write );
304 ptr->s_write = INVALID_HANDLE_VALUE;
306 if (ptr->eventmask & EV_TXEMPTY) {
307 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
308 mask |= CN_EVENT;
312 } while (len > 0);
313 /* check for notification */
314 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
315 (comm_outbuf(ptr)<ptr->n_write)) {
316 /* passed the transmit notification threshold */
317 mask |= CN_TRANSMIT;
320 /* send notifications, if any */
321 if (ptr->wnd && mask) {
322 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
323 Callout.PostMessage16(ptr->wnd, WM_COMMNOTIFY, cid, mask);
327 static void comm_waitread(struct DosDeviceStruct *ptr)
329 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
330 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
331 GENERIC_READ | SYNCHRONIZE ),
332 comm_notification,
333 (ULONG_PTR)ptr );
336 static void comm_waitwrite(struct DosDeviceStruct *ptr)
338 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
339 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
340 GENERIC_WRITE | SYNCHRONIZE ),
341 comm_notification,
342 (ULONG_PTR)ptr );
345 /**************************************************************************
346 * BuildCommDCB (USER.213)
348 * According to the ECMA-234 (368.3) the function will return FALSE on
349 * success, otherwise it will return -1.
350 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
351 * NEEDS TO BE FIXED
353 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
355 /* "COM1:9600,n,8,1" */
356 /* 012345 */
357 int port;
358 char *ptr, temp[256];
360 TRACE("(%s), ptr %p\n", device, lpdcb);
362 if (!lstrncmpiA(device,"COM",3)) {
363 port = device[3] - '0';
366 if (port-- == 0) {
367 ERR("BUG ! COM0 can't exist!.\n");
368 return -1;
371 if (!ValidCOMPort(port)) {
372 FIXME("invalid COM port %d?\n",port);
373 return -1;
376 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
378 lpdcb->Id = port;
380 if (!*(device+4))
381 return 0;
383 if (*(device+4) != ':')
384 return -1;
386 strcpy(temp,device+5);
387 ptr = strtok(temp, ", ");
389 if (COM[port].baudrate > 0)
390 lpdcb->BaudRate = COM[port].baudrate;
391 else
392 lpdcb->BaudRate = atoi(ptr);
393 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
395 ptr = strtok(NULL, ", ");
396 if (islower(*ptr))
397 *ptr = toupper(*ptr);
399 TRACE("parity (%c)\n", *ptr);
400 lpdcb->fParity = TRUE;
401 switch (*ptr) {
402 case 'N':
403 lpdcb->Parity = NOPARITY;
404 lpdcb->fParity = FALSE;
405 break;
406 case 'E':
407 lpdcb->Parity = EVENPARITY;
408 break;
409 case 'M':
410 lpdcb->Parity = MARKPARITY;
411 break;
412 case 'O':
413 lpdcb->Parity = ODDPARITY;
414 break;
415 default:
416 WARN("Unknown parity `%c'!\n", *ptr);
417 return -1;
420 ptr = strtok(NULL, ", ");
421 TRACE("charsize (%c)\n", *ptr);
422 lpdcb->ByteSize = *ptr - '0';
424 ptr = strtok(NULL, ", ");
425 TRACE("stopbits (%c)\n", *ptr);
426 switch (*ptr) {
427 case '1':
428 lpdcb->StopBits = ONESTOPBIT;
429 break;
430 case '2':
431 lpdcb->StopBits = TWOSTOPBITS;
432 break;
433 default:
434 WARN("Unknown # of stopbits `%c'!\n", *ptr);
435 return -1;
439 return 0;
442 /*****************************************************************************
443 * OpenComm (USER.200)
445 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
447 int port,fd;
449 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
451 if (strlen(device) < 4)
452 return IE_BADID;
454 port = device[3] - '0';
456 if (port-- == 0)
457 ERR("BUG ! COM0 or LPT0 don't exist !\n");
459 if (!lstrncmpiA(device,"COM",3)) {
461 TRACE("%s = %s\n", device, COM[port].devicename);
463 if (!ValidCOMPort(port))
464 return IE_BADID;
466 if (COM[port].fd)
467 return IE_OPEN;
469 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
470 if (fd == -1) {
471 ERR("error=%d\n", errno);
472 return IE_HARDWARE;
473 } else {
474 unknown[port] = SEGPTR_ALLOC(40);
475 bzero(unknown[port],40);
476 COM[port].fd = fd;
477 COM[port].commerror = 0;
478 COM[port].eventmask = 0;
479 COM[port].evtchar = 0; /* FIXME: default? */
480 /* save terminal state */
481 tcgetattr(fd,&m_stat[port]);
482 /* set default parameters */
483 if(COM[port].baudrate>-1){
484 DCB16 dcb;
485 GetCommState16(port, &dcb);
486 dcb.BaudRate=COM[port].baudrate;
487 /* more defaults:
488 * databits, parity, stopbits
490 SetCommState16( &dcb);
492 /* init priority characters */
493 COM[port].unget = -1;
494 COM[port].xmit = -1;
495 /* allocate buffers */
496 COM[port].ibuf_size = cbInQueue;
497 COM[port].ibuf_head = COM[port].ibuf_tail= 0;
498 COM[port].obuf_size = cbOutQueue;
499 COM[port].obuf_head = COM[port].obuf_tail = 0;
501 COM[port].inbuf = malloc(cbInQueue);
502 if (COM[port].inbuf) {
503 COM[port].outbuf = malloc(cbOutQueue);
504 if (!COM[port].outbuf)
505 free(COM[port].inbuf);
506 } else COM[port].outbuf = NULL;
507 if (!COM[port].outbuf) {
508 /* not enough memory */
509 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
510 close(COM[port].fd);
511 ERR("out of memory");
512 return IE_MEMORY;
515 COM[port].s_read = INVALID_HANDLE_VALUE;
516 COM[port].s_write = INVALID_HANDLE_VALUE;
517 comm_waitread( &COM[port] );
518 return port;
521 else
522 if (!lstrncmpiA(device,"LPT",3)) {
524 if (!ValidLPTPort(port))
525 return IE_BADID;
527 if (LPT[port].fd)
528 return IE_OPEN;
530 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
531 if (fd == -1) {
532 return IE_HARDWARE;
533 } else {
534 LPT[port].fd = fd;
535 LPT[port].commerror = 0;
536 LPT[port].eventmask = 0;
537 return port|FLAG_LPT;
540 return 0;
543 /*****************************************************************************
544 * CloseComm (USER.207)
546 INT16 WINAPI CloseComm16(INT16 cid)
548 struct DosDeviceStruct *ptr;
550 TRACE("cid=%d\n", cid);
551 if ((ptr = GetDeviceStruct(cid)) == NULL) {
552 FIXME("no cid=%d found!\n", cid);
553 return -1;
555 if (!(cid&FLAG_LPT)) {
556 /* COM port */
557 SEGPTR_FREE(unknown[cid]); /* [LW] */
559 SERVICE_Delete( COM[cid].s_write );
560 SERVICE_Delete( COM[cid].s_read );
561 /* free buffers */
562 free(ptr->outbuf);
563 free(ptr->inbuf);
565 /* reset modem lines */
566 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
569 if (close(ptr->fd) == -1) {
570 ptr->commerror = WinError();
571 /* FIXME: should we clear ptr->fd here? */
572 return -1;
573 } else {
574 ptr->commerror = 0;
575 ptr->fd = 0;
576 return 0;
580 /*****************************************************************************
581 * SetCommBreak (USER.210)
583 INT16 WINAPI SetCommBreak16(INT16 cid)
585 struct DosDeviceStruct *ptr;
587 TRACE("cid=%d\n", cid);
588 if ((ptr = GetDeviceStruct(cid)) == NULL) {
589 FIXME("no cid=%d found!\n", cid);
590 return -1;
593 ptr->suspended = 1;
594 ptr->commerror = 0;
595 return 0;
598 /*****************************************************************************
599 * ClearCommBreak (USER.211)
601 INT16 WINAPI ClearCommBreak16(INT16 cid)
603 struct DosDeviceStruct *ptr;
605 TRACE("cid=%d\n", cid);
606 if (!(ptr = GetDeviceStruct(cid))) {
607 FIXME("no cid=%d found!\n", cid);
608 return -1;
610 ptr->suspended = 0;
611 ptr->commerror = 0;
612 return 0;
615 /*****************************************************************************
616 * EscapeCommFunction (USER.214)
618 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
620 int max;
621 struct DosDeviceStruct *ptr;
622 struct termios port;
624 TRACE("cid=%d, function=%d\n", cid, nFunction);
625 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
626 if ((ptr = GetDeviceStruct(cid)) == NULL) {
627 FIXME("no cid=%d found!\n", cid);
628 return -1;
630 if (tcgetattr(ptr->fd,&port) == -1) {
631 TRACE("tcgetattr failed\n");
632 ptr->commerror=WinError();
633 return -1;
635 } else ptr = NULL;
637 switch (nFunction) {
638 case RESETDEV:
639 TRACE("RESETDEV\n");
640 break;
642 case GETMAXCOM:
643 TRACE("GETMAXCOM\n");
644 for (max = MAX_PORTS;!COM[max].devicename;max--)
646 return max;
647 break;
649 case GETMAXLPT:
650 TRACE("GETMAXLPT\n");
651 for (max = MAX_PORTS;!LPT[max].devicename;max--)
653 return FLAG_LPT + max;
654 break;
656 case GETBASEIRQ:
657 TRACE("GETBASEIRQ\n");
658 /* FIXME: use tables */
659 /* just fake something for now */
660 if (cid & FLAG_LPT) {
661 /* LPT1: irq 7, LPT2: irq 5 */
662 return (cid & 0x7f) ? 5 : 7;
663 } else {
664 /* COM1: irq 4, COM2: irq 3,
665 COM3: irq 4, COM4: irq 3 */
666 return 4 - (cid & 1);
668 break;
670 case CLRDTR:
671 TRACE("CLRDTR\n");
672 #ifdef TIOCM_DTR
673 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
674 #endif
675 case CLRRTS:
676 TRACE("CLRRTS\n");
677 #ifdef TIOCM_RTS
678 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
679 #endif
681 case SETDTR:
682 TRACE("SETDTR\n");
683 #ifdef TIOCM_DTR
684 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
685 #endif
687 case SETRTS:
688 TRACE("SETRTS\n");
689 #ifdef TIOCM_RTS
690 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
691 #endif
693 case SETXOFF:
694 TRACE("SETXOFF\n");
695 port.c_iflag |= IXOFF;
696 break;
698 case SETXON:
699 TRACE("SETXON\n");
700 port.c_iflag |= IXON;
701 break;
703 default:
704 WARN("(cid=%d,nFunction=%d): Unknown function\n",
705 cid, nFunction);
706 break;
709 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
710 ptr->commerror = WinError();
711 return -1;
712 } else {
713 ptr->commerror = 0;
714 return 0;
718 /*****************************************************************************
719 * FlushComm (USER.215)
721 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
723 int queue;
724 struct DosDeviceStruct *ptr;
726 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
727 if ((ptr = GetDeviceStruct(cid)) == NULL) {
728 FIXME("no cid=%d found!\n", cid);
729 return -1;
731 switch (fnQueue) {
732 case 0:
733 queue = TCOFLUSH;
734 ptr->obuf_tail = ptr->obuf_head;
735 break;
736 case 1:
737 queue = TCIFLUSH;
738 ptr->ibuf_head = ptr->ibuf_tail;
739 break;
740 default:
741 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
742 cid, fnQueue);
743 return -1;
745 if (tcflush(ptr->fd, queue)) {
746 ptr->commerror = WinError();
747 return -1;
748 } else {
749 ptr->commerror = 0;
750 return 0;
754 /********************************************************************
755 * GetCommError (USER.203)
757 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
759 int temperror;
760 struct DosDeviceStruct *ptr;
761 unsigned char *stol;
762 unsigned int mstat;
764 if ((ptr = GetDeviceStruct(cid)) == NULL) {
765 FIXME("no handle for cid = %0x!.\n",cid);
766 return -1;
768 if (cid&FLAG_LPT) {
769 WARN(" cid %d not comm port\n",cid);
770 return CE_MODE;
772 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
773 ioctl(ptr->fd,TIOCMGET,&mstat);
774 COMM_MSRUpdate( stol, mstat);
776 if (lpStat) {
777 lpStat->status = 0;
779 lpStat->cbOutQue = comm_outbuf(ptr);
780 lpStat->cbInQue = comm_inbuf(ptr);
782 TRACE("cid %d, error %d, lpStat %d %d %d stol %x\n",
783 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
784 lpStat->cbOutQue, *stol);
786 else
787 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
788 cid, ptr->commerror, *stol);
790 /* Return any errors and clear it */
791 temperror = ptr->commerror;
792 ptr->commerror = 0;
793 return(temperror);
796 /*****************************************************************************
797 * SetCommEventMask (USER.208)
799 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
801 struct DosDeviceStruct *ptr;
802 unsigned char *stol;
803 int repid;
804 unsigned int mstat;
806 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
807 if ((ptr = GetDeviceStruct(cid)) == NULL) {
808 FIXME("no handle for cid = %0x!.\n",cid);
809 return (SEGPTR)NULL;
812 ptr->eventmask = fuEvtMask;
814 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
815 WARN(" cid %d not comm port\n",cid);
816 return (SEGPTR)NULL;
818 /* it's a COM port ? -> modify flags */
819 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
820 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
821 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
822 COMM_MSRUpdate( stol, mstat);
824 TRACE(" modem dcd construct %x\n",*stol);
825 return SEGPTR_GET(unknown[cid]);
828 /*****************************************************************************
829 * GetCommEventMask (USER.209)
831 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
833 struct DosDeviceStruct *ptr;
834 WORD events;
836 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
837 if ((ptr = GetDeviceStruct(cid)) == NULL) {
838 FIXME("no handle for cid = %0x!.\n",cid);
839 return 0;
842 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
843 WARN(" cid %d not comm port\n",cid);
844 return 0;
847 events = *(WORD*)(unknown[cid]) & fnEvtClear;
848 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
849 return events;
852 /*****************************************************************************
853 * SetCommState16 (USER.201)
855 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
857 struct termios port;
858 struct DosDeviceStruct *ptr;
859 int bytesize, stopbits;
860 int fail=0;
862 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
863 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
864 FIXME("no handle for cid = %0x!.\n",lpdcb->Id);
865 return -1;
867 if (tcgetattr(ptr->fd, &port) == -1) {
868 ptr->commerror = WinError();
869 return -1;
872 port.c_cc[VMIN] = 0;
873 port.c_cc[VTIME] = 1;
875 #ifdef IMAXBEL
876 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
877 #else
878 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
879 #endif
880 port.c_iflag |= (IGNBRK);
882 port.c_oflag &= ~(OPOST);
884 port.c_cflag &= ~(HUPCL);
885 port.c_cflag |= CLOCAL | CREAD;
887 port.c_lflag &= ~(ICANON|ECHO|ISIG);
888 port.c_lflag |= NOFLSH;
890 TRACE("baudrate %d\n",lpdcb->BaudRate);
891 #ifdef CBAUD
892 port.c_cflag &= ~CBAUD;
893 switch (lpdcb->BaudRate) {
894 case 110:
895 case CBR_110:
896 port.c_cflag |= B110;
897 break;
898 case 300:
899 case CBR_300:
900 port.c_cflag |= B300;
901 break;
902 case 600:
903 case CBR_600:
904 port.c_cflag |= B600;
905 break;
906 case 1200:
907 case CBR_1200:
908 port.c_cflag |= B1200;
909 break;
910 case 2400:
911 case CBR_2400:
912 port.c_cflag |= B2400;
913 break;
914 case 4800:
915 case CBR_4800:
916 port.c_cflag |= B4800;
917 break;
918 case 9600:
919 case CBR_9600:
920 port.c_cflag |= B9600;
921 break;
922 case 19200:
923 case CBR_19200:
924 port.c_cflag |= B19200;
925 break;
926 case 38400:
927 case CBR_38400:
928 port.c_cflag |= B38400;
929 break;
930 #ifdef B57600
931 case 57600:
932 port.c_cflag |= B57600;
933 break;
934 #endif
935 #ifdef B115200
936 case 57601:
937 port.c_cflag |= B115200;
938 break;
939 #endif
940 default:
941 ptr->commerror = IE_BAUDRATE;
942 fail=1;
944 #elif !defined(__EMX__)
945 switch (lpdcb->BaudRate) {
946 case 110:
947 case CBR_110:
948 port.c_ospeed = B110;
949 break;
950 case 300:
951 case CBR_300:
952 port.c_ospeed = B300;
953 break;
954 case 600:
955 case CBR_600:
956 port.c_ospeed = B600;
957 break;
958 case 1200:
959 case CBR_1200:
960 port.c_ospeed = B1200;
961 break;
962 case 2400:
963 case CBR_2400:
964 port.c_ospeed = B2400;
965 break;
966 case 4800:
967 case CBR_4800:
968 port.c_ospeed = B4800;
969 break;
970 case 9600:
971 case CBR_9600:
972 port.c_ospeed = B9600;
973 break;
974 case 19200:
975 case CBR_19200:
976 port.c_ospeed = B19200;
977 break;
978 case 38400:
979 case CBR_38400:
980 port.c_ospeed = B38400;
981 break;
982 default:
983 ptr->commerror = IE_BAUDRATE;
984 fail=1;
986 port.c_ispeed = port.c_ospeed;
987 #endif
988 bytesize=lpdcb->ByteSize;
989 stopbits=lpdcb->StopBits;
991 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
992 #ifdef CMSPAR
993 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
994 #else
995 port.c_cflag &= ~(PARENB | PARODD);
996 #endif
997 if (lpdcb->fParity)
998 port.c_iflag |= INPCK;
999 else
1000 port.c_iflag &= ~INPCK;
1001 switch (lpdcb->Parity) {
1002 case NOPARITY:
1003 break;
1004 case ODDPARITY:
1005 port.c_cflag |= (PARENB | PARODD);
1006 break;
1007 case EVENPARITY:
1008 port.c_cflag |= PARENB;
1009 break;
1010 #ifdef CMSPAR
1011 /* Linux defines mark/space (stick) parity */
1012 case MARKPARITY:
1013 port.c_cflag |= (PARENB | CMSPAR);
1014 break;
1015 case SPACEPARITY:
1016 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1017 break;
1018 #else
1019 /* try the POSIX way */
1020 case MARKPARITY:
1021 if( stopbits == ONESTOPBIT) {
1022 stopbits = TWOSTOPBITS;
1023 port.c_iflag &= ~INPCK;
1024 } else {
1025 ptr->commerror = IE_BYTESIZE;
1026 fail=1;
1028 break;
1029 case SPACEPARITY:
1030 if( bytesize < 8) {
1031 bytesize +=1;
1032 port.c_iflag &= ~INPCK;
1033 } else {
1034 ptr->commerror = IE_BYTESIZE;
1035 fail=1;
1037 break;
1038 #endif
1039 default:
1040 ptr->commerror = IE_BYTESIZE;
1041 fail=1;
1044 TRACE("bytesize %d\n",bytesize);
1045 port.c_cflag &= ~CSIZE;
1046 switch (bytesize) {
1047 case 5:
1048 port.c_cflag |= CS5;
1049 break;
1050 case 6:
1051 port.c_cflag |= CS6;
1052 break;
1053 case 7:
1054 port.c_cflag |= CS7;
1055 break;
1056 case 8:
1057 port.c_cflag |= CS8;
1058 break;
1059 default:
1060 ptr->commerror = IE_BYTESIZE;
1061 fail=1;
1064 TRACE("stopbits %d\n",stopbits);
1066 switch (stopbits) {
1067 case ONESTOPBIT:
1068 port.c_cflag &= ~CSTOPB;
1069 break;
1070 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1071 case TWOSTOPBITS:
1072 port.c_cflag |= CSTOPB;
1073 break;
1074 default:
1075 ptr->commerror = IE_BYTESIZE;
1076 fail=1;
1078 #ifdef CRTSCTS
1080 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1081 port.c_cflag |= CRTSCTS;
1083 if (lpdcb->fDtrDisable)
1084 port.c_cflag &= ~CRTSCTS;
1085 #endif
1086 if (lpdcb->fInX)
1087 port.c_iflag |= IXON;
1088 else
1089 port.c_iflag &= ~IXON;
1090 if (lpdcb->fOutX)
1091 port.c_iflag |= IXOFF;
1092 else
1093 port.c_iflag &= ~IXOFF;
1095 ptr->evtchar = lpdcb->EvtChar;
1097 if(fail)
1098 return -1;
1100 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1101 ptr->commerror = WinError();
1102 return -1;
1103 } else {
1104 ptr->commerror = 0;
1105 return 0;
1109 /*****************************************************************************
1110 * GetCommState (USER.202)
1112 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1114 int speed;
1115 struct DosDeviceStruct *ptr;
1116 struct termios port;
1118 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1119 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1120 FIXME("no handle for cid = %0x!.\n",cid);
1121 return -1;
1123 if (tcgetattr(ptr->fd, &port) == -1) {
1124 ptr->commerror = WinError();
1125 return -1;
1127 lpdcb->Id = cid;
1128 #ifndef __EMX__
1129 #ifdef CBAUD
1130 speed = port.c_cflag & CBAUD;
1131 #else
1132 speed = port.c_ospeed;
1133 #endif
1134 switch(speed) {
1135 case B110:
1136 lpdcb->BaudRate = 110;
1137 break;
1138 case B300:
1139 lpdcb->BaudRate = 300;
1140 break;
1141 case B600:
1142 lpdcb->BaudRate = 600;
1143 break;
1144 case B1200:
1145 lpdcb->BaudRate = 1200;
1146 break;
1147 case B2400:
1148 lpdcb->BaudRate = 2400;
1149 break;
1150 case B4800:
1151 lpdcb->BaudRate = 4800;
1152 break;
1153 case B9600:
1154 lpdcb->BaudRate = 9600;
1155 break;
1156 case B19200:
1157 lpdcb->BaudRate = 19200;
1158 break;
1159 case B38400:
1160 lpdcb->BaudRate = 38400;
1161 break;
1162 #ifdef B57600
1163 case B57600:
1164 lpdcb->BaudRate = 57600;
1165 break;
1166 #endif
1167 #ifdef B115200
1168 case B115200:
1169 lpdcb->BaudRate = 57601;
1170 break;
1171 #endif
1173 #endif
1174 switch (port.c_cflag & CSIZE) {
1175 case CS5:
1176 lpdcb->ByteSize = 5;
1177 break;
1178 case CS6:
1179 lpdcb->ByteSize = 6;
1180 break;
1181 case CS7:
1182 lpdcb->ByteSize = 7;
1183 break;
1184 case CS8:
1185 lpdcb->ByteSize = 8;
1186 break;
1189 if(port.c_iflag & INPCK)
1190 lpdcb->fParity = TRUE;
1191 else
1192 lpdcb->fParity = FALSE;
1193 #ifdef CMSPAR
1194 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1195 #else
1196 switch (port.c_cflag & (PARENB | PARODD))
1197 #endif
1199 case 0:
1200 lpdcb->Parity = NOPARITY;
1201 break;
1202 case PARENB:
1203 lpdcb->Parity = EVENPARITY;
1204 break;
1205 case (PARENB | PARODD):
1206 lpdcb->Parity = ODDPARITY;
1207 break;
1208 #ifdef CMSPAR
1209 case (PARENB | CMSPAR):
1210 lpdcb->Parity = MARKPARITY;
1211 break;
1212 case (PARENB | PARODD | CMSPAR):
1213 lpdcb->Parity = SPACEPARITY;
1214 break;
1215 #endif
1218 if (port.c_cflag & CSTOPB)
1219 if(lpdcb->ByteSize == 5)
1220 lpdcb->StopBits = ONE5STOPBITS;
1221 else
1222 lpdcb->StopBits = TWOSTOPBITS;
1223 else
1224 lpdcb->StopBits = ONESTOPBIT;
1226 lpdcb->RlsTimeout = 50;
1227 lpdcb->CtsTimeout = 50;
1228 lpdcb->DsrTimeout = 50;
1229 lpdcb->fNull = 0;
1230 lpdcb->fChEvt = 0;
1231 lpdcb->fBinary = 1;
1232 lpdcb->fDtrDisable = 0;
1234 #ifdef CRTSCTS
1236 if (port.c_cflag & CRTSCTS) {
1237 lpdcb->fDtrflow = 1;
1238 lpdcb->fRtsflow = 1;
1239 lpdcb->fOutxCtsFlow = 1;
1240 lpdcb->fOutxDsrFlow = 1;
1241 } else
1242 #endif
1243 lpdcb->fDtrDisable = 1;
1245 if (port.c_iflag & IXON)
1246 lpdcb->fInX = 1;
1247 else
1248 lpdcb->fInX = 0;
1250 if (port.c_iflag & IXOFF)
1251 lpdcb->fOutX = 1;
1252 else
1253 lpdcb->fOutX = 0;
1255 lpdcb->XonChar =
1256 lpdcb->XoffChar =
1258 lpdcb->XonLim = 10;
1259 lpdcb->XoffLim = 10;
1261 lpdcb->EvtChar = ptr->evtchar;
1263 ptr->commerror = 0;
1264 return 0;
1267 /*****************************************************************************
1268 * TransmitCommChar (USER.206)
1270 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1272 struct DosDeviceStruct *ptr;
1274 TRACE("cid %d, data %d \n", cid, chTransmit);
1275 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1276 FIXME("no handle for cid = %0x!.\n",cid);
1277 return -1;
1280 if (ptr->suspended) {
1281 ptr->commerror = IE_HARDWARE;
1282 return -1;
1285 if (ptr->xmit >= 0) {
1286 /* character already queued */
1287 /* FIXME: which error would Windows return? */
1288 ptr->commerror = CE_TXFULL;
1289 return -1;
1292 if (ptr->obuf_head == ptr->obuf_tail) {
1293 /* transmit queue empty, try to transmit directly */
1294 if (write(ptr->fd, &chTransmit, 1) == -1) {
1295 /* didn't work, queue it */
1296 ptr->xmit = chTransmit;
1297 comm_waitwrite(ptr);
1299 } else {
1300 /* data in queue, let this char be transmitted next */
1301 ptr->xmit = chTransmit;
1302 comm_waitwrite(ptr);
1305 ptr->commerror = 0;
1306 return 0;
1309 /*****************************************************************************
1310 * UngetCommChar (USER.212)
1312 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1314 struct DosDeviceStruct *ptr;
1316 TRACE("cid %d (char %d)\n", cid, chUnget);
1317 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1318 FIXME("no handle for cid = %0x!.\n",cid);
1319 return -1;
1322 if (ptr->suspended) {
1323 ptr->commerror = IE_HARDWARE;
1324 return -1;
1327 if (ptr->unget>=0) {
1328 /* character already queued */
1329 /* FIXME: which error would Windows return? */
1330 ptr->commerror = CE_RXOVER;
1331 return -1;
1334 ptr->unget = chUnget;
1336 ptr->commerror = 0;
1337 return 0;
1340 /*****************************************************************************
1341 * ReadComm (USER.204)
1343 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1345 int status, length;
1346 struct DosDeviceStruct *ptr;
1347 LPSTR orgBuf = lpvBuf;
1349 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1350 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1351 FIXME("no handle for cid = %0x!.\n",cid);
1352 return -1;
1355 if (ptr->suspended) {
1356 ptr->commerror = IE_HARDWARE;
1357 return -1;
1360 /* read unget character */
1361 if (ptr->unget>=0) {
1362 *lpvBuf++ = ptr->unget;
1363 ptr->unget = -1;
1365 length = 1;
1366 } else
1367 length = 0;
1369 /* read from receive buffer */
1370 while (length < cbRead) {
1371 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1372 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1373 if (!status) break;
1374 if ((cbRead - length) < status)
1375 status = cbRead - length;
1377 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1378 ptr->ibuf_tail += status;
1379 if (ptr->ibuf_tail >= ptr->ibuf_size)
1380 ptr->ibuf_tail = 0;
1381 lpvBuf += status;
1382 length += status;
1385 TRACE("%.*s\n", length, orgBuf);
1386 ptr->commerror = 0;
1387 return length;
1390 /*****************************************************************************
1391 * WriteComm (USER.205)
1393 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1395 int status, length;
1396 struct DosDeviceStruct *ptr;
1398 TRACE("cid %d, ptr %p, length %d\n",
1399 cid, lpvBuf, cbWrite);
1400 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1401 FIXME("no handle for cid = %0x!.\n",cid);
1402 return -1;
1405 if (ptr->suspended) {
1406 ptr->commerror = IE_HARDWARE;
1407 return -1;
1410 TRACE("%.*s\n", cbWrite, lpvBuf );
1412 length = 0;
1413 while (length < cbWrite) {
1414 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1415 /* no data queued, try to write directly */
1416 status = write(ptr->fd, lpvBuf, cbWrite - length);
1417 if (status > 0) {
1418 lpvBuf += status;
1419 length += status;
1420 continue;
1423 /* can't write directly, put into transmit buffer */
1424 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1425 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1426 if (!status) break;
1427 if ((cbWrite - length) < status)
1428 status = cbWrite - length;
1429 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1430 ptr->obuf_head += status;
1431 if (ptr->obuf_head >= ptr->obuf_size)
1432 ptr->obuf_head = 0;
1433 lpvBuf += status;
1434 length += status;
1435 comm_waitwrite(ptr);
1438 ptr->commerror = 0;
1439 return length;
1442 /***********************************************************************
1443 * EnableCommNotification (USER.246)
1445 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1446 INT16 cbWriteNotify, INT16 cbOutQueue )
1448 struct DosDeviceStruct *ptr;
1450 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1451 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1452 FIXME("no handle for cid = %0x!.\n",cid);
1453 return -1;
1455 ptr->wnd = hwnd;
1456 ptr->n_read = cbWriteNotify;
1457 ptr->n_write = cbOutQueue;
1458 return TRUE;
1462 /**************************************************************************
1463 * BuildCommDCBA (KERNEL32.14)
1465 BOOL WINAPI BuildCommDCBA(LPCSTR device,LPDCB lpdcb)
1467 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1470 /**************************************************************************
1471 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
1473 BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb,
1474 LPCOMMTIMEOUTS lptimeouts)
1476 int port;
1477 char *ptr,*temp;
1479 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1481 if (!lstrncmpiA(device,"COM",3)) {
1482 port=device[3]-'0';
1483 if (port--==0) {
1484 ERR("BUG! COM0 can't exists!.\n");
1485 return FALSE;
1487 if (!ValidCOMPort(port))
1488 return FALSE;
1489 if (*(device+4)!=':')
1490 return FALSE;
1491 temp=(LPSTR)(device+5);
1492 } else
1493 temp=(LPSTR)device;
1495 lpdcb->DCBlength = sizeof(DCB);
1496 if (strchr(temp,',')) { /* old style */
1497 DCB16 dcb16;
1498 BOOL16 ret;
1499 char last=temp[strlen(temp)-1];
1501 ret=BuildCommDCB16(device,&dcb16);
1502 if (ret)
1503 return FALSE;
1504 lpdcb->BaudRate = dcb16.BaudRate;
1505 lpdcb->ByteSize = dcb16.ByteSize;
1506 lpdcb->fBinary = dcb16.fBinary;
1507 lpdcb->Parity = dcb16.Parity;
1508 lpdcb->fParity = dcb16.fParity;
1509 lpdcb->fNull = dcb16.fNull;
1510 lpdcb->StopBits = dcb16.StopBits;
1511 if (last == 'x') {
1512 lpdcb->fInX = TRUE;
1513 lpdcb->fOutX = TRUE;
1514 lpdcb->fOutxCtsFlow = FALSE;
1515 lpdcb->fOutxDsrFlow = FALSE;
1516 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1517 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1518 } else if (last=='p') {
1519 lpdcb->fInX = FALSE;
1520 lpdcb->fOutX = FALSE;
1521 lpdcb->fOutxCtsFlow = TRUE;
1522 lpdcb->fOutxDsrFlow = TRUE;
1523 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1524 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1525 } else {
1526 lpdcb->fInX = FALSE;
1527 lpdcb->fOutX = FALSE;
1528 lpdcb->fOutxCtsFlow = FALSE;
1529 lpdcb->fOutxDsrFlow = FALSE;
1530 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1531 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1533 lpdcb->XonChar = dcb16.XonChar;
1534 lpdcb->XoffChar = dcb16.XoffChar;
1535 lpdcb->ErrorChar= dcb16.PeChar;
1536 lpdcb->fErrorChar= dcb16.fPeChar;
1537 lpdcb->EofChar = dcb16.EofChar;
1538 lpdcb->EvtChar = dcb16.EvtChar;
1539 lpdcb->XonLim = dcb16.XonLim;
1540 lpdcb->XoffLim = dcb16.XoffLim;
1541 return TRUE;
1543 ptr=strtok(temp," ");
1544 while (ptr) {
1545 DWORD flag,x;
1547 flag=0;
1548 if (!strncmp("baud=",ptr,5)) {
1549 if (!sscanf(ptr+5,"%ld",&x))
1550 WARN("Couldn't parse %s\n",ptr);
1551 lpdcb->BaudRate = x;
1552 flag=1;
1554 if (!strncmp("stop=",ptr,5)) {
1555 if (!sscanf(ptr+5,"%ld",&x))
1556 WARN("Couldn't parse %s\n",ptr);
1557 lpdcb->StopBits = x;
1558 flag=1;
1560 if (!strncmp("data=",ptr,5)) {
1561 if (!sscanf(ptr+5,"%ld",&x))
1562 WARN("Couldn't parse %s\n",ptr);
1563 lpdcb->ByteSize = x;
1564 flag=1;
1566 if (!strncmp("parity=",ptr,7)) {
1567 lpdcb->fParity = TRUE;
1568 switch (ptr[8]) {
1569 case 'N':case 'n':
1570 lpdcb->fParity = FALSE;
1571 lpdcb->Parity = NOPARITY;
1572 break;
1573 case 'E':case 'e':
1574 lpdcb->Parity = EVENPARITY;
1575 break;
1576 case 'O':case 'o':
1577 lpdcb->Parity = ODDPARITY;
1578 break;
1579 case 'M':case 'm':
1580 lpdcb->Parity = MARKPARITY;
1581 break;
1583 flag=1;
1585 if (!flag)
1586 ERR("Unhandled specifier '%s', please report.\n",ptr);
1587 ptr=strtok(NULL," ");
1589 if (lpdcb->BaudRate==110)
1590 lpdcb->StopBits = 2;
1591 return TRUE;
1594 /**************************************************************************
1595 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
1597 BOOL WINAPI BuildCommDCBAndTimeoutsW( LPCWSTR devid, LPDCB lpdcb,
1598 LPCOMMTIMEOUTS lptimeouts )
1600 LPSTR devidA;
1601 BOOL ret;
1603 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1604 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1605 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1606 HeapFree( GetProcessHeap(), 0, devidA );
1607 return ret;
1610 /**************************************************************************
1611 * BuildCommDCBW (KERNEL32.17)
1613 BOOL WINAPI BuildCommDCBW(LPCWSTR devid,LPDCB lpdcb)
1615 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1618 /*****************************************************************************
1619 * COMM_GetReadFd
1620 * Returns a file descriptor for reading.
1621 * Make sure to close the handle afterwards!
1623 static int COMM_GetReadFd( HANDLE handle)
1625 int fd;
1626 struct get_read_fd_request *req = get_req_buffer();
1627 req->handle = handle;
1628 server_call_fd( REQ_GET_READ_FD, -1, &fd );
1629 return fd;
1632 /*****************************************************************************
1633 * COMM_GetWriteFd
1634 * Returns a file descriptor for writing.
1635 * Make sure to close the handle afterwards!
1637 static int COMM_GetWriteFd( HANDLE handle)
1639 int fd = -1;
1640 struct get_write_fd_request *req = get_req_buffer();
1641 req->handle = handle;
1642 server_call_fd( REQ_GET_WRITE_FD, -1, &fd );
1643 return fd;
1646 /* FIXME: having these global for win32 for now */
1647 int commerror=0,eventmask=0;
1649 /*****************************************************************************
1650 * SetCommBreak (KERNEL32.449)
1652 BOOL WINAPI SetCommBreak(HANDLE handle)
1654 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1655 int fd,result;
1657 fd = COMM_GetWriteFd(handle);
1658 if(fd<0) {
1659 TRACE("COMM_GetWriteFd failed\n");
1660 return FALSE;
1662 result = ioctl(fd,TIOCSBRK,0);
1663 close(fd);
1664 if (result ==-1)
1666 TRACE("ioctl failed\n");
1667 SetLastError(ERROR_NOT_SUPPORTED);
1668 return FALSE;
1670 return TRUE;
1671 #else
1672 FIXME("ioctl not available\n");
1673 SetLastError(ERROR_NOT_SUPPORTED);
1674 return FALSE;
1675 #endif
1678 /*****************************************************************************
1679 * ClearCommBreak (KERNEL32.20)
1681 BOOL WINAPI ClearCommBreak(HANDLE handle)
1683 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1684 int fd,result;
1686 fd = COMM_GetWriteFd(handle);
1687 if(fd<0) {
1688 TRACE("COMM_GetWriteFd failed\n");
1689 return FALSE;
1691 result = ioctl(fd,TIOCCBRK,0);
1692 close(fd);
1693 if (result ==-1)
1695 TRACE("ioctl failed\n");
1696 SetLastError(ERROR_NOT_SUPPORTED);
1697 return FALSE;
1699 return TRUE;
1700 #else
1701 FIXME("ioctl not available\n");
1702 SetLastError(ERROR_NOT_SUPPORTED);
1703 return FALSE;
1704 #endif
1707 /*****************************************************************************
1708 * EscapeCommFunction (KERNEL32.214)
1710 BOOL WINAPI EscapeCommFunction(HANDLE handle,UINT nFunction)
1712 int fd,direct=FALSE,result=FALSE;
1713 struct termios port;
1715 TRACE("handle %d, function=%d\n", handle, nFunction);
1716 fd = COMM_GetWriteFd(handle);
1717 if(fd<0) {
1718 FIXME("handle %d not found.\n",handle);
1719 return FALSE;
1722 if (tcgetattr(fd,&port) == -1) {
1723 commerror=WinError();
1724 close(fd);
1725 return FALSE;
1728 switch (nFunction) {
1729 case RESETDEV:
1730 TRACE("\n");
1731 break;
1733 case CLRDTR:
1734 TRACE("CLRDTR\n");
1735 #ifdef TIOCM_DTR
1736 direct=TRUE;
1737 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1738 break;
1739 #endif
1741 case CLRRTS:
1742 TRACE("CLRRTS\n");
1743 #ifdef TIOCM_RTS
1744 direct=TRUE;
1745 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1746 break;
1747 #endif
1749 case SETDTR:
1750 TRACE("SETDTR\n");
1751 #ifdef TIOCM_DTR
1752 direct=TRUE;
1753 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1754 break;
1755 #endif
1757 case SETRTS:
1758 TRACE("SETRTS\n");
1759 #ifdef TIOCM_DTR
1760 direct=TRUE;
1761 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1762 break;
1763 #endif
1765 case SETXOFF:
1766 TRACE("SETXOFF\n");
1767 port.c_iflag |= IXOFF;
1768 break;
1770 case SETXON:
1771 TRACE("SETXON\n");
1772 port.c_iflag |= IXON;
1773 break;
1774 case SETBREAK:
1775 TRACE("setbreak\n");
1776 #ifdef TIOCSBRK
1777 direct=TRUE;
1778 result = ioctl(fd,TIOCSBRK,0);
1779 break;
1780 #endif
1781 case CLRBREAK:
1782 TRACE("clrbreak\n");
1783 #ifdef TIOCSBRK
1784 direct=TRUE;
1785 result = ioctl(fd,TIOCCBRK,0);
1786 break;
1787 #endif
1788 default:
1789 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1790 handle, nFunction);
1791 break;
1794 if (!direct)
1795 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1796 commerror = WinError();
1797 close(fd);
1798 return FALSE;
1799 } else
1800 result= TRUE;
1801 else
1803 if (result == -1)
1805 result= FALSE;
1806 commerror=WinError();
1808 else
1809 result = TRUE;
1811 close(fd);
1812 return result;
1815 /********************************************************************
1816 * PurgeComm (KERNEL32.557)
1818 BOOL WINAPI PurgeComm( HANDLE handle, DWORD flags)
1820 int fd;
1822 TRACE("handle %d, flags %lx\n", handle, flags);
1824 fd = COMM_GetWriteFd(handle);
1825 if(fd<0) {
1826 FIXME("no handle %d found\n",handle);
1827 return FALSE;
1831 ** not exactly sure how these are different
1832 ** Perhaps if we had our own internal queues, one flushes them
1833 ** and the other flushes the kernel's buffers.
1835 if(flags&PURGE_TXABORT)
1836 tcflush(fd,TCOFLUSH);
1837 if(flags&PURGE_RXABORT)
1838 tcflush(fd,TCIFLUSH);
1839 if(flags&PURGE_TXCLEAR)
1840 tcflush(fd,TCOFLUSH);
1841 if(flags&PURGE_RXCLEAR)
1842 tcflush(fd,TCIFLUSH);
1843 close(fd);
1845 return 1;
1848 /*****************************************************************************
1849 * ClearCommError (KERNEL32.21)
1851 BOOL WINAPI ClearCommError(HANDLE handle,LPDWORD errors,LPCOMSTAT lpStat)
1853 int fd;
1855 fd=COMM_GetReadFd(handle);
1856 if(0>fd)
1858 FIXME("no handle %d found\n",handle);
1859 return FALSE;
1862 if (lpStat)
1864 lpStat->status = 0;
1866 #ifdef TIOCOUTQ
1867 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1868 WARN("ioctl returned error\n");
1869 #else
1870 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
1871 #endif
1873 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
1874 WARN("ioctl returned error\n");
1876 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
1877 handle, lpStat->cbInQue, lpStat->cbOutQue);
1880 close(fd);
1882 if(errors)
1883 *errors = 0;
1886 ** After an asynchronous write opperation, the
1887 ** app will call ClearCommError to see if the
1888 ** results are ready yet. It waits for ERROR_IO_PENDING
1890 commerror = ERROR_IO_PENDING;
1892 return TRUE;
1895 /*****************************************************************************
1896 * SetupComm (KERNEL32.676)
1898 BOOL WINAPI SetupComm( HANDLE handle, DWORD insize, DWORD outsize)
1900 int fd;
1902 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1903 fd=COMM_GetWriteFd(handle);
1904 if(0>fd) {
1905 FIXME("handle %d not found?\n",handle);
1906 return FALSE;
1908 close(fd);
1909 return TRUE;
1912 /*****************************************************************************
1913 * GetCommMask (KERNEL32.156)
1915 BOOL WINAPI GetCommMask(HANDLE handle,LPDWORD evtmask)
1917 int fd;
1919 TRACE("handle %d, mask %p\n", handle, evtmask);
1920 if(0>(fd=COMM_GetReadFd(handle)))
1922 FIXME("no handle %d found\n",handle);
1923 return FALSE;
1925 close(fd);
1926 *evtmask = eventmask;
1927 TRACE("%s%s%s%s%s%s%s%s%s\n",
1928 (eventmask&EV_BREAK)?"EV_BREAK":"",
1929 (eventmask&EV_CTS)?"EV_CTS":"",
1930 (eventmask&EV_DSR)?"EV_DSR":"",
1931 (eventmask&EV_ERR)?"EV_ERR":"",
1932 (eventmask&EV_RING)?"EV_RING":"",
1933 (eventmask&EV_RLSD)?"EV_RLSD":"",
1934 (eventmask&EV_RXCHAR)?"EV_RXCHAR":"",
1935 (eventmask&EV_RXFLAG)?"EV_RXFLAG":"",
1936 (eventmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1938 return TRUE;
1941 /*****************************************************************************
1942 * SetCommMask (KERNEL32.451)
1944 BOOL WINAPI SetCommMask(HANDLE handle,DWORD evtmask)
1946 int fd;
1948 TRACE("handle %d, mask %lx\n", handle, evtmask);
1949 TRACE("%s%s%s%s%s%s%s%s%s\n",
1950 (evtmask&EV_BREAK)?"EV_BREAK":"",
1951 (evtmask&EV_CTS)?"EV_CTS":"",
1952 (evtmask&EV_DSR)?"EV_DSR":"",
1953 (evtmask&EV_ERR)?"EV_ERR":"",
1954 (evtmask&EV_RING)?"EV_RING":"",
1955 (evtmask&EV_RLSD)?"EV_RLSD":"",
1956 (evtmask&EV_RXCHAR)?"EV_RXCHAR":"",
1957 (evtmask&EV_RXFLAG)?"EV_RXFLAG":"",
1958 (evtmask&EV_TXEMPTY)?"EV_TXEMPTY":"");
1960 if(0>(fd=COMM_GetWriteFd(handle))) {
1961 FIXME("no handle %d found\n",handle);
1962 return FALSE;
1964 close(fd);
1965 eventmask = evtmask;
1966 return TRUE;
1969 /*****************************************************************************
1970 * SetCommState (KERNEL32.452)
1972 BOOL WINAPI SetCommState(HANDLE handle,LPDCB lpdcb)
1974 struct termios port;
1975 int fd;
1976 int bytesize, stopbits;
1978 TRACE("handle %d, ptr %p\n", handle, lpdcb);
1979 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1980 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1981 (lpdcb->StopBits == ONESTOPBIT)?1:
1982 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1983 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1984 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1986 if ((fd = COMM_GetWriteFd(handle)) < 0) {
1987 FIXME("no handle %d found\n",handle);
1988 return FALSE;
1991 if ((tcgetattr(fd,&port)) == -1) {
1992 int save_error = errno;
1993 commerror = WinError();
1994 close( fd );
1995 #ifdef HAVE_STRERROR
1996 ERR("tcgetattr error '%s'\n", strerror(save_error));
1997 #else
1998 ERR("tcgetattr error %d\n", save_error);
1999 #endif
2000 return FALSE;
2003 port.c_cc[VMIN] = 0;
2004 port.c_cc[VTIME] = 1;
2006 #ifdef IMAXBEL
2007 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
2008 #else
2009 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
2010 #endif
2011 port.c_iflag |= (IGNBRK);
2013 port.c_oflag &= ~(OPOST);
2015 port.c_cflag &= ~(HUPCL);
2016 port.c_cflag |= CLOCAL | CREAD;
2018 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2019 port.c_lflag |= NOFLSH;
2022 ** MJM - removed default baudrate settings
2023 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2025 #ifdef CBAUD
2026 port.c_cflag &= ~CBAUD;
2027 switch (lpdcb->BaudRate) {
2028 case 110:
2029 case CBR_110:
2030 port.c_cflag |= B110;
2031 break;
2032 case 300:
2033 case CBR_300:
2034 port.c_cflag |= B300;
2035 break;
2036 case 600:
2037 case CBR_600:
2038 port.c_cflag |= B600;
2039 break;
2040 case 1200:
2041 case CBR_1200:
2042 port.c_cflag |= B1200;
2043 break;
2044 case 2400:
2045 case CBR_2400:
2046 port.c_cflag |= B2400;
2047 break;
2048 case 4800:
2049 case CBR_4800:
2050 port.c_cflag |= B4800;
2051 break;
2052 case 9600:
2053 case CBR_9600:
2054 port.c_cflag |= B9600;
2055 break;
2056 case 19200:
2057 case CBR_19200:
2058 port.c_cflag |= B19200;
2059 break;
2060 case 38400:
2061 case CBR_38400:
2062 port.c_cflag |= B38400;
2063 break;
2064 #ifdef B57600
2065 case 57600:
2066 port.c_cflag |= B57600;
2067 break;
2068 #endif
2069 #ifdef B115200
2070 case 115200:
2071 port.c_cflag |= B115200;
2072 break;
2073 #endif
2074 #ifdef B230400
2075 case 230400:
2076 port.c_cflag |= B230400;
2077 break;
2078 #endif
2079 #ifdef B460800
2080 case 460600:
2081 port.c_cflag |= B460800;
2082 break;
2083 #endif
2084 default:
2085 commerror = IE_BAUDRATE;
2086 close( fd );
2087 ERR("baudrate %ld\n",lpdcb->BaudRate);
2088 return FALSE;
2090 #elif !defined(__EMX__)
2091 switch (lpdcb->BaudRate) {
2092 case 110:
2093 case CBR_110:
2094 port.c_ospeed = B110;
2095 break;
2096 case 300:
2097 case CBR_300:
2098 port.c_ospeed = B300;
2099 break;
2100 case 600:
2101 case CBR_600:
2102 port.c_ospeed = B600;
2103 break;
2104 case 1200:
2105 case CBR_1200:
2106 port.c_ospeed = B1200;
2107 break;
2108 case 2400:
2109 case CBR_2400:
2110 port.c_ospeed = B2400;
2111 break;
2112 case 4800:
2113 case CBR_4800:
2114 port.c_ospeed = B4800;
2115 break;
2116 case 9600:
2117 case CBR_9600:
2118 port.c_ospeed = B9600;
2119 break;
2120 case 19200:
2121 case CBR_19200:
2122 port.c_ospeed = B19200;
2123 break;
2124 case 38400:
2125 case CBR_38400:
2126 port.c_ospeed = B38400;
2127 break;
2128 default:
2129 commerror = IE_BAUDRATE;
2130 close( fd );
2131 ERR("baudrate %ld\n",lpdcb->BaudRate);
2132 return FALSE;
2134 port.c_ispeed = port.c_ospeed;
2135 #endif
2136 bytesize=lpdcb->ByteSize;
2137 stopbits=lpdcb->StopBits;
2139 #ifdef CMSPAR
2140 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2141 #else
2142 port.c_cflag &= ~(PARENB | PARODD);
2143 #endif
2144 if (lpdcb->fParity)
2145 port.c_iflag |= INPCK;
2146 else
2147 port.c_iflag &= ~INPCK;
2148 switch (lpdcb->Parity) {
2149 case NOPARITY:
2150 break;
2151 case ODDPARITY:
2152 port.c_cflag |= (PARENB | PARODD);
2153 break;
2154 case EVENPARITY:
2155 port.c_cflag |= PARENB;
2156 break;
2157 #ifdef CMSPAR
2158 /* Linux defines mark/space (stick) parity */
2159 case MARKPARITY:
2160 port.c_cflag |= (PARENB | CMSPAR);
2161 break;
2162 case SPACEPARITY:
2163 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2164 break;
2165 #else
2166 /* try the POSIX way */
2167 case MARKPARITY:
2168 if( stopbits == ONESTOPBIT) {
2169 stopbits = TWOSTOPBITS;
2170 port.c_iflag &= ~INPCK;
2171 } else {
2172 commerror = IE_BYTESIZE;
2173 close( fd );
2174 ERR("Cannot set MARK Parity\n");
2175 return FALSE;
2177 break;
2178 case SPACEPARITY:
2179 if( bytesize < 8) {
2180 bytesize +=1;
2181 port.c_iflag &= ~INPCK;
2182 } else {
2183 commerror = IE_BYTESIZE;
2184 close( fd );
2185 ERR("Cannot set SPACE Parity\n");
2186 return FALSE;
2188 break;
2189 #endif
2190 default:
2191 commerror = IE_BYTESIZE;
2192 close( fd );
2193 ERR("Parity\n");
2194 return FALSE;
2198 port.c_cflag &= ~CSIZE;
2199 switch (bytesize) {
2200 case 5:
2201 port.c_cflag |= CS5;
2202 break;
2203 case 6:
2204 port.c_cflag |= CS6;
2205 break;
2206 case 7:
2207 port.c_cflag |= CS7;
2208 break;
2209 case 8:
2210 port.c_cflag |= CS8;
2211 break;
2212 default:
2213 commerror = IE_BYTESIZE;
2214 close( fd );
2215 ERR("ByteSize\n");
2216 return FALSE;
2219 switch (stopbits) {
2220 case ONESTOPBIT:
2221 port.c_cflag &= ~CSTOPB;
2222 break;
2223 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2224 case TWOSTOPBITS:
2225 port.c_cflag |= CSTOPB;
2226 break;
2227 default:
2228 commerror = IE_BYTESIZE;
2229 close( fd );
2230 ERR("StopBits\n");
2231 return FALSE;
2233 #ifdef CRTSCTS
2234 if ( lpdcb->fOutxCtsFlow ||
2235 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2236 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2239 port.c_cflag |= CRTSCTS;
2240 TRACE("CRTSCTS\n");
2243 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2245 port.c_cflag &= ~CRTSCTS;
2246 TRACE("~CRTSCTS\n");
2249 #endif
2250 if (lpdcb->fInX)
2251 port.c_iflag |= IXON;
2252 else
2253 port.c_iflag &= ~IXON;
2254 if (lpdcb->fOutX)
2255 port.c_iflag |= IXOFF;
2256 else
2257 port.c_iflag &= ~IXOFF;
2259 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2260 int save_error=errno;
2261 commerror = WinError();
2262 close( fd );
2263 #ifdef HAVE_STRERROR
2264 ERR("tcgetattr error '%s'\n", strerror(save_error));
2265 #else
2266 ERR("tcgetattr error %d\n", save_error);
2267 #endif
2268 return FALSE;
2269 } else {
2270 commerror = 0;
2271 close( fd );
2272 return TRUE;
2277 /*****************************************************************************
2278 * GetCommState (KERNEL32.159)
2280 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
2282 struct termios port;
2283 int fd,speed;
2285 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2287 if ((fd = COMM_GetReadFd(handle)) < 0)
2289 ERR("can't get COMM_GetReadFd\n");
2290 return FALSE;
2292 if (tcgetattr(fd, &port) == -1) {
2293 int save_error=errno;
2294 #ifdef HAVE_STRERROR
2295 ERR("tcgetattr error '%s'\n", strerror(save_error));
2296 #else
2297 ERR("tcgetattr error %d\n", save_error);
2298 #endif
2299 commerror = WinError();
2300 close( fd );
2301 return FALSE;
2303 close( fd );
2304 #ifndef __EMX__
2305 #ifdef CBAUD
2306 speed= (port.c_cflag & CBAUD);
2307 #else
2308 speed= (cfgetospeed(&port));
2309 #endif
2310 switch (speed) {
2311 case B110:
2312 lpdcb->BaudRate = 110;
2313 break;
2314 case B300:
2315 lpdcb->BaudRate = 300;
2316 break;
2317 case B600:
2318 lpdcb->BaudRate = 600;
2319 break;
2320 case B1200:
2321 lpdcb->BaudRate = 1200;
2322 break;
2323 case B2400:
2324 lpdcb->BaudRate = 2400;
2325 break;
2326 case B4800:
2327 lpdcb->BaudRate = 4800;
2328 break;
2329 case B9600:
2330 lpdcb->BaudRate = 9600;
2331 break;
2332 case B19200:
2333 lpdcb->BaudRate = 19200;
2334 break;
2335 case B38400:
2336 lpdcb->BaudRate = 38400;
2337 break;
2338 #ifdef B57600
2339 case B57600:
2340 lpdcb->BaudRate = 57600;
2341 break;
2342 #endif
2343 #ifdef B115200
2344 case B115200:
2345 lpdcb->BaudRate = 115200;
2346 break;
2347 #endif
2348 #ifdef B230400
2349 case B230400:
2350 lpdcb->BaudRate = 230400;
2351 break;
2352 #endif
2353 #ifdef B460800
2354 case B460800:
2355 lpdcb->BaudRate = 460800;
2356 break;
2357 #endif
2358 default:
2359 ERR("unknown speed %x \n",speed);
2361 #endif
2362 switch (port.c_cflag & CSIZE) {
2363 case CS5:
2364 lpdcb->ByteSize = 5;
2365 break;
2366 case CS6:
2367 lpdcb->ByteSize = 6;
2368 break;
2369 case CS7:
2370 lpdcb->ByteSize = 7;
2371 break;
2372 case CS8:
2373 lpdcb->ByteSize = 8;
2374 break;
2375 default:
2376 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2379 if(port.c_iflag & INPCK)
2380 lpdcb->fParity = TRUE;
2381 else
2382 lpdcb->fParity = FALSE;
2383 #ifdef CMSPAR
2384 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
2385 #else
2386 switch (port.c_cflag & (PARENB | PARODD))
2387 #endif
2389 case 0:
2390 lpdcb->Parity = NOPARITY;
2391 break;
2392 case PARENB:
2393 lpdcb->Parity = EVENPARITY;
2394 break;
2395 case (PARENB | PARODD):
2396 lpdcb->Parity = ODDPARITY;
2397 break;
2398 #ifdef CMSPAR
2399 case (PARENB | CMSPAR):
2400 lpdcb->Parity = MARKPARITY;
2401 break;
2402 case (PARENB | PARODD | CMSPAR):
2403 lpdcb->Parity = SPACEPARITY;
2404 break;
2405 #endif
2408 if (port.c_cflag & CSTOPB)
2409 if(lpdcb->ByteSize == 5)
2410 lpdcb->StopBits = ONE5STOPBITS;
2411 else
2412 lpdcb->StopBits = TWOSTOPBITS;
2413 else
2414 lpdcb->StopBits = ONESTOPBIT;
2416 lpdcb->fNull = 0;
2417 lpdcb->fBinary = 1;
2419 #ifdef CRTSCTS
2421 if (port.c_cflag & CRTSCTS) {
2422 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2423 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2424 lpdcb->fOutxCtsFlow = 1;
2425 lpdcb->fOutxDsrFlow = 1;
2426 } else
2427 #endif
2429 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2430 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2432 if (port.c_iflag & IXON)
2433 lpdcb->fInX = 1;
2434 else
2435 lpdcb->fInX = 0;
2437 if (port.c_iflag & IXOFF)
2438 lpdcb->fOutX = 1;
2439 else
2440 lpdcb->fOutX = 0;
2442 lpdcb->XonChar =
2443 lpdcb->XoffChar =
2445 lpdcb->XonLim = 10;
2446 lpdcb->XoffLim = 10;
2448 commerror = 0;
2450 TRACE("OK\n");
2452 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2453 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2454 (lpdcb->StopBits == ONESTOPBIT)?1:
2455 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2456 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2457 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2458 #ifdef CRTSCTS
2459 if ( lpdcb->fOutxCtsFlow ||
2460 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2461 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2463 TRACE("CRTSCTS\n");
2465 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2466 TRACE("~CRTSCTS\n");
2468 #endif
2469 return TRUE;
2472 /*****************************************************************************
2473 * TransmitCommChar (KERNEL32.535)
2475 BOOL WINAPI TransmitCommChar(HANDLE hComm,CHAR chTransmit)
2477 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
2478 return TRUE;
2481 /*****************************************************************************
2482 * GetCommTimeouts (KERNEL32.160)
2484 BOOL WINAPI GetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts)
2486 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2487 return TRUE;
2490 /*****************************************************************************
2491 * SetCommTimeouts (KERNEL32.453)
2493 BOOL WINAPI SetCommTimeouts(HANDLE hcom,LPCOMMTIMEOUTS lptimeouts) {
2494 /* struct DosDeviceStruct *ptr; */
2495 struct termios tios;
2496 int fd;
2498 FIXME("(%x,%p):stub.\n",hcom,lptimeouts);
2500 if ((ptr = GetDeviceStruct(hcom)) == NULL) {
2501 FIXME("no handle for cid = %0x!.\n",hcom);
2502 return FALSE;
2506 fd = COMM_GetWriteFd(hcom);
2507 if (fd < 0) {
2508 FIXME("no fd for cid = %0x!.\n",hcom);
2509 return FALSE;
2513 FIXME("ReadIntervalTimeout %ld\n",lptimeouts->ReadIntervalTimeout);
2514 FIXME("ReadTotalTimeoutMultiplier %ld\n",lptimeouts->ReadTotalTimeoutMultiplier);
2515 FIXME("ReadTotalTimeoutConstant %ld\n",lptimeouts->ReadTotalTimeoutConstant);
2516 FIXME("WriteTotalTimeoutMultiplier %ld\n",lptimeouts->WriteTotalTimeoutMultiplier);
2517 FIXME("WriteTotalTimeoutConstant %ld\n",lptimeouts->WriteTotalTimeoutConstant);
2520 if (-1==tcgetattr(fd,&tios)) {
2521 FIXME("tcgetattr on fd %d failed!\n",fd);
2522 return FALSE;
2524 /* VTIME is in 1/10 seconds */
2525 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2526 if (-1==tcsetattr(fd,0,&tios)) {
2527 FIXME("tcsetattr on fd %d failed!\n",fd);
2528 return FALSE;
2530 return TRUE;
2533 /***********************************************************************
2534 * GetCommModemStatus (KERNEL32.285)
2536 BOOL WINAPI GetCommModemStatus(HANDLE hFile,LPDWORD lpModemStat )
2538 int fd,mstat, result=FALSE;
2540 *lpModemStat=0;
2541 #ifdef TIOCMGET
2542 fd = COMM_GetWriteFd(hFile);
2543 if(fd<0)
2544 return FALSE;
2545 result = ioctl(fd, TIOCMGET, &mstat);
2546 close(fd);
2547 if (result == -1)
2549 TRACE("ioctl failed\n");
2550 return FALSE;
2552 if (mstat & TIOCM_CTS)
2553 *lpModemStat |= MS_CTS_ON;
2554 if (mstat & TIOCM_DSR)
2555 *lpModemStat |= MS_DSR_ON;
2556 if (mstat & TIOCM_RNG)
2557 *lpModemStat |= MS_RING_ON;
2558 /*FIXME: Not really sure about RLSD UB 990810*/
2559 if (mstat & TIOCM_CAR)
2560 *lpModemStat |= MS_RLSD_ON;
2561 TRACE("%s%s%s%s\n",
2562 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2563 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2564 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2565 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2566 return TRUE;
2567 #else
2568 return FALSE;
2569 #endif
2571 /***********************************************************************
2572 * WaitCommEvent (KERNEL32.719)
2574 BOOL WINAPI WaitCommEvent(HANDLE hFile,LPDWORD eventmask ,LPOVERLAPPED overlapped)
2576 FIXME("(%d %p %p )\n",hFile, eventmask,overlapped);
2577 return TRUE;
2580 /***********************************************************************
2581 * GetCommProperties (KERNEL32.286)
2583 * This function fills in a structure with the capabilities of the
2584 * communications port driver.
2586 * RETURNS
2588 * TRUE on success, FALSE on failure
2589 * If successful, the lpCommProp structure be filled in with
2590 * properties of the comm port.
2592 BOOL WINAPI GetCommProperties(
2593 HANDLE hFile, /* handle of the comm port */
2594 LPCOMMPROP lpCommProp /* pointer to struct to be filled */
2596 FIXME("(%d %p )\n",hFile,lpCommProp);
2597 if(!lpCommProp)
2598 return FALSE;
2601 * These values should be valid for LINUX's serial driver
2602 * FIXME: Perhaps they deserve an #ifdef LINUX
2604 memset(lpCommProp,0,sizeof(COMMPROP));
2605 lpCommProp->wPacketLength = 1;
2606 lpCommProp->wPacketVersion = 1;
2607 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2608 lpCommProp->dwReserved1 = 0;
2609 lpCommProp->dwMaxTxQueue = 4096;
2610 lpCommProp->dwMaxRxQueue = 4096;
2611 lpCommProp->dwMaxBaud = BAUD_115200;
2612 lpCommProp->dwProvSubType = PST_RS232;
2613 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
2614 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2615 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2616 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2617 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2618 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2619 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2620 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2621 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2622 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2623 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2625 return TRUE;
2628 /***********************************************************************
2629 * FIXME:
2630 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2631 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2632 * This is dependent on the type of COMM port, but since it is doubtful
2633 * anybody will get around to implementing support for fancy serial
2634 * ports in WINE, this is hardcoded for the time being. The name of
2635 * this DLL should be stored in and read from the system registry in
2636 * the hive HKEY_LOCAL_MACHINE, key
2637 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2638 * where ???? is the port number... that is determined by PNP
2639 * The DLL should be loaded when the COMM port is opened, and closed
2640 * when the COMM port is closed. - MJM 20 June 2000
2641 ***********************************************************************/
2642 static CHAR lpszSerialUI[] = "serialui.dll";
2645 /***********************************************************************
2646 * CommConfigDialogA (KERNEL32.140)
2648 * Raises a dialog that allows the user to configure a comm port.
2649 * Fills the COMMCONFIG struct with information specified by the user.
2650 * This function should call a similar routine in the COMM driver...
2652 * RETURNS
2654 * TRUE on success, FALSE on failure
2655 * If successful, the lpCommConfig structure will contain a new
2656 * configuration for the comm port, as specified by the user.
2658 * BUGS
2659 * The library with the CommConfigDialog code is never unloaded.
2660 * Perhaps this should be done when the comm port is closed?
2662 BOOL WINAPI CommConfigDialogA(
2663 LPCSTR lpszDevice, /* name of communications device */
2664 HANDLE hWnd, /* parent window for the dialog */
2665 LPCOMMCONFIG lpCommConfig /* pointer to struct to fill */
2667 FARPROC lpfnCommDialog;
2668 HMODULE hConfigModule;
2669 BOOL r;
2671 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
2673 hConfigModule = LoadLibraryA(lpszSerialUI);
2674 if(!hConfigModule)
2675 return FALSE;
2677 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2679 if(!lpfnCommDialog)
2680 return FALSE;
2682 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2684 /* UnloadLibrary(hConfigModule); */
2686 return r;
2689 /***********************************************************************
2690 * CommConfigDialogW (KERNEL32.141)
2692 * see CommConfigDialogA for more info
2694 BOOL WINAPI CommConfigDialogW(
2695 LPCWSTR lpszDevice, /* name of communications device */
2696 HANDLE hWnd, /* parent window for the dialog */
2697 LPCOMMCONFIG lpCommConfig /* pointer to struct to fill */
2699 BOOL r;
2700 LPSTR lpDeviceA;
2702 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2703 if(lpDeviceA)
2704 return FALSE;
2705 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2706 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2707 return r;
2710 /***********************************************************************
2711 * GetCommConfig (KERNEL32.283)
2713 * Fill in the COMMCONFIG structure for the comm port hFile
2715 * RETURNS
2717 * TRUE on success, FALSE on failure
2718 * If successful, lpCommConfig contains the comm port configuration.
2720 BOOL WINAPI GetCommConfig(
2721 HFILE hFile,
2722 LPCOMMCONFIG lpCommConfig
2724 BOOL r;
2726 TRACE("(%x %p)\n",hFile,lpCommConfig);
2728 if(lpCommConfig == NULL)
2729 return FALSE;
2731 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2732 lpCommConfig->wVersion = 1;
2733 lpCommConfig->wReserved = 0;
2734 r = GetCommState(hFile,&lpCommConfig->dcb);
2735 lpCommConfig->dwProviderSubType = PST_RS232;
2736 lpCommConfig->dwProviderOffset = 0;
2737 lpCommConfig->dwProviderSize = 0;
2739 return r;
2742 /***********************************************************************
2743 * SetCommConfig (KERNEL32.617)
2746 BOOL WINAPI SetCommConfig(
2747 HFILE hFile,
2748 LPCOMMCONFIG lpCommConfig
2750 BOOL r;
2752 TRACE("(%x %p)\n",hFile,lpCommConfig);
2754 r = SetCommState(hFile,&lpCommConfig->dcb);
2755 return r;
2758 /***********************************************************************
2759 * SetDefaultCommConfigA (KERNEL32.@)
2761 BOOL WINAPI SetDefaultCommConfigA(
2762 LPCSTR lpszDevice,
2763 LPCOMMCONFIG lpCommConfig,
2764 DWORD dwSize
2766 FARPROC lpfnSetDefaultCommConfig;
2767 HMODULE hConfigModule;
2768 BOOL r;
2770 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2772 hConfigModule = LoadLibraryA(lpszSerialUI);
2773 if(!hConfigModule)
2774 return FALSE;
2776 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2778 if(! lpfnSetDefaultCommConfig)
2779 return TRUE;
2781 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2783 /* UnloadLibrary(hConfigModule); */
2785 return r;
2789 /***********************************************************************
2790 * SetDefaultCommConfigW (KERNEL32.639)
2793 BOOL WINAPI SetDefaultCommConfigW(
2794 LPCWSTR lpszDevice,
2795 LPCOMMCONFIG lpCommConfig,
2796 DWORD dwSize
2798 BOOL r;
2799 LPSTR lpDeviceA;
2801 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2803 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2804 if(lpDeviceA)
2805 return FALSE;
2806 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2807 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2808 return r;
2812 /***********************************************************************
2813 * GetDefaultCommConfigA (KERNEL32.313)
2815 BOOL WINAPI GetDefaultCommConfigA(LPCSTR lpszName,LPCOMMCONFIG lpCC,
2816 LPDWORD lpdwSize)
2818 LPDCB lpdcb = &(lpCC->dcb);
2819 char temp[40];
2821 if (strncasecmp(lpszName,"COM",3)) {
2822 ERR("not implemented for <%s>\n", lpszName);
2823 return FALSE;
2826 if (!ValidCOMPort(lpszName[3]-'1'))
2827 return FALSE;
2829 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2830 if (*lpdwSize < sizeof(COMMCONFIG)) {
2831 *lpdwSize = sizeof(COMMCONFIG);
2832 return FALSE;
2835 *lpdwSize = sizeof(COMMCONFIG);
2837 lpCC->dwSize = sizeof(COMMCONFIG);
2838 lpCC->wVersion = 1;
2839 lpCC->dwProviderSubType = PST_RS232;
2840 lpCC->dwProviderOffset = 0L;
2841 lpCC->dwProviderSize = 0L;
2843 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2844 FIXME("setting %s as default\n", temp);
2846 return BuildCommDCBA( temp, lpdcb);
2849 /**************************************************************************
2850 * GetDefaultCommConfigW (KERNEL32.314)
2852 BOOL WINAPI GetDefaultCommConfigW( LPCWSTR lpszName,LPCOMMCONFIG lpCC,
2853 LPDWORD lpdwSize)
2855 LPSTR lpszNameA;
2856 BOOL ret;
2858 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2859 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2860 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2861 HeapFree( GetProcessHeap(), 0, lpszNameA );
2862 return ret;