Don't use RTSCTS if Str handshake is enabled.
[wine/hacks.git] / dlls / kernel / comm.c
blob877b2cf52003757fbe8ac7b0404e9d48fa2c0875
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>
53 #include <sys/poll.h>
55 #include "windef.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"
64 #include "wine/port.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 #if !defined(TIOCINQ) && defined(FIONREAD)
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 #define MAX_PORTS 9
95 struct DosDeviceStruct {
96 char *devicename; /* /dev/ttyS0 */
97 int fd;
98 int suspended;
99 int unget,xmit;
100 int baudrate;
101 int evtchar;
102 /* events */
103 int commerror, eventmask;
104 /* buffers */
105 char *inbuf,*outbuf;
106 unsigned ibuf_size,ibuf_head,ibuf_tail;
107 unsigned obuf_size,obuf_head,obuf_tail;
108 /* notifications */
109 int wnd, n_read, n_write;
110 HANDLE s_read, s_write;
114 static struct DosDeviceStruct COM[MAX_PORTS];
115 static struct DosDeviceStruct LPT[MAX_PORTS];
116 /* pointers to unknown(==undocumented) comm structure */
117 static LPCVOID *unknown[MAX_PORTS];
118 /* save terminal states */
119 static struct termios m_stat[MAX_PORTS];
121 /* update window's semi documented modem status register */
122 /* see knowledge base Q101417 */
123 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
125 UCHAR tmpmsr=0;
126 #ifdef TIOCM_CTS
127 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
128 #endif
129 #ifdef TIOCM_DSR
130 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
131 #endif
132 #ifdef TIOCM_RI
133 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
134 #endif
135 #ifdef TIOCM_CAR
136 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
137 #endif
138 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
141 void COMM_Init(void)
143 int x;
144 char option[10], temp[256], *btemp;
145 struct stat st;
147 for (x=0; x!=MAX_PORTS; x++) {
148 strcpy(option,"COMx");
149 option[3] = '1' + x;
150 option[4] = '\0';
152 PROFILE_GetWineIniString( "serialports", option, "*",
153 temp, sizeof(temp) );
154 if (!strcmp(temp, "*") || *temp == '\0')
155 COM[x].devicename = NULL;
156 else {
157 btemp = strchr(temp,',');
158 if (btemp != NULL) {
159 *btemp++ = '\0';
160 COM[x].baudrate = atoi(btemp);
161 } else {
162 COM[x].baudrate = -1;
164 stat(temp, &st);
165 if (!S_ISCHR(st.st_mode))
166 WARN("Can't use `%s' as %s !\n", temp, option);
167 else
168 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
169 WARN("Can't malloc for device info!\n");
170 else {
171 COM[x].fd = 0;
172 strcpy(COM[x].devicename, temp);
174 TRACE("%s = %s\n", option, COM[x].devicename);
177 strcpy(option, "LPTx");
178 option[3] = '1' + x;
179 option[4] = '\0';
181 PROFILE_GetWineIniString( "parallelports", option, "*",
182 temp, sizeof(temp) );
183 if (!strcmp(temp, "*") || *temp == '\0')
184 LPT[x].devicename = NULL;
185 else {
186 stat(temp, &st);
187 if (!S_ISCHR(st.st_mode))
188 WARN("Can't use `%s' as %s !\n", temp, option);
189 else
190 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
191 WARN("Can't malloc for device info!\n");
192 else {
193 LPT[x].fd = 0;
194 strcpy(LPT[x].devicename, temp);
196 TRACE("%s = %s\n", option, LPT[x].devicename);
203 static struct DosDeviceStruct *GetDeviceStruct(int fd)
205 if ((fd&0x7F)<=MAX_PORTS) {
206 if (!(fd&FLAG_LPT)) {
207 if (COM[fd].fd)
208 return &COM[fd];
209 } else {
210 fd &= 0x7f;
211 if (LPT[fd].fd)
212 return &LPT[fd];
216 return NULL;
219 static int GetCommPort_fd(int fd)
221 int x;
223 for (x=0; x<MAX_PORTS; x++) {
224 if (COM[x].fd == fd)
225 return x;
228 return -1;
231 static int ValidCOMPort(int x)
233 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
236 static int ValidLPTPort(int x)
238 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
241 static int WinError(void)
243 TRACE("errno = %d\n", errno);
244 switch (errno) {
245 default:
246 return CE_IOE;
250 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
252 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
253 + ptr->ibuf_head - ptr->ibuf_tail;
256 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
258 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
259 + ptr->obuf_head - ptr->obuf_tail;
262 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
264 unsigned int mstat, okay;
265 okay = ioctl(fd, TIOCMGET, &mstat);
266 if (okay) return okay;
267 if (andy) mstat &= andy;
268 mstat |= orrie;
269 return ioctl(fd, TIOCMSET, &mstat);
272 static void CALLBACK comm_notification( ULONG_PTR private )
274 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
275 int prev, bleft, len;
276 WORD mask = 0;
277 int cid = GetCommPort_fd(ptr->fd);
279 TRACE("async notification\n");
280 /* read data from comm port */
281 prev = comm_inbuf(ptr);
282 do {
283 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
284 - ptr->ibuf_head;
285 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
286 if (len > 0) {
287 if (!bleft) {
288 ptr->commerror = CE_RXOVER;
289 } else {
290 /* check for events */
291 if ((ptr->eventmask & EV_RXFLAG) &&
292 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
293 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
294 mask |= CN_EVENT;
296 if (ptr->eventmask & EV_RXCHAR) {
297 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
298 mask |= CN_EVENT;
300 /* advance buffer position */
301 ptr->ibuf_head += len;
302 if (ptr->ibuf_head >= ptr->ibuf_size)
303 ptr->ibuf_head = 0;
306 } while (len > 0);
307 /* check for notification */
308 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
309 (comm_inbuf(ptr)>=ptr->n_read)) {
310 /* passed the receive notification threshold */
311 mask |= CN_RECEIVE;
314 /* write any TransmitCommChar character */
315 if (ptr->xmit>=0) {
316 len = write(ptr->fd, &(ptr->xmit), 1);
317 if (len > 0) ptr->xmit = -1;
319 /* write from output queue */
320 prev = comm_outbuf(ptr);
321 do {
322 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
323 - ptr->obuf_tail;
324 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
325 if (len > 0) {
326 ptr->obuf_tail += len;
327 if (ptr->obuf_tail >= ptr->obuf_size)
328 ptr->obuf_tail = 0;
329 /* flag event */
330 if (ptr->obuf_tail == ptr->obuf_head) {
331 if (ptr->s_write) {
332 SERVICE_Delete( ptr->s_write );
333 ptr->s_write = INVALID_HANDLE_VALUE;
335 if (ptr->eventmask & EV_TXEMPTY) {
336 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
337 mask |= CN_EVENT;
341 } while (len > 0);
342 /* check for notification */
343 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
344 (comm_outbuf(ptr)<ptr->n_write)) {
345 /* passed the transmit notification threshold */
346 mask |= CN_TRANSMIT;
349 /* send notifications, if any */
350 if (ptr->wnd && mask) {
351 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
352 if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
356 static void comm_waitread(struct DosDeviceStruct *ptr)
358 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
359 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
360 GENERIC_READ | SYNCHRONIZE ),
361 comm_notification,
362 (ULONG_PTR)ptr );
365 static void comm_waitwrite(struct DosDeviceStruct *ptr)
367 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
368 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
369 GENERIC_WRITE | SYNCHRONIZE ),
370 comm_notification,
371 (ULONG_PTR)ptr );
374 /**************************************************************************
375 * BuildCommDCB16 (USER.213)
377 * According to the ECMA-234 (368.3) the function will return FALSE on
378 * success, otherwise it will return -1.
379 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
380 * NEEDS TO BE FIXED
382 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
384 /* "COM1:96,n,8,1" */
385 /* 012345 */
386 int port;
387 char *ptr, temp[256];
389 TRACE("(%s), ptr %p\n", device, lpdcb);
391 if (!strncasecmp(device,"COM",3)) {
392 port = device[3] - '0';
395 if (port-- == 0) {
396 ERR("BUG ! COM0 can't exist!\n");
397 return -1;
400 if (!ValidCOMPort(port)) {
401 FIXME("invalid COM port %d?\n",port);
402 return -1;
405 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
407 lpdcb->Id = port;
409 if (!*(device+4))
410 return 0;
412 if (*(device+4) != ':')
413 return -1;
415 strcpy(temp,device+5);
416 ptr = strtok(temp, ", ");
418 if (COM[port].baudrate > 0)
419 lpdcb->BaudRate = COM[port].baudrate;
420 else
422 int rate;
423 /* DOS/Windows only compares the first two numbers
424 * and assigns an appropriate baud rate.
425 * You can supply 961324245, it still returns 9600 ! */
426 if (strlen(ptr) < 2)
428 WARN("Unknown baudrate string '%s' !\n", ptr);
429 return -1; /* error: less than 2 chars */
431 ptr[2] = '\0';
432 rate = atoi(ptr);
434 switch (rate) {
435 case 11:
436 case 30:
437 case 60:
438 rate *= 10;
439 break;
440 case 12:
441 case 24:
442 case 48:
443 case 96:
444 rate *= 100;
445 break;
446 case 19:
447 rate = 19200;
448 break;
449 default:
450 WARN("Unknown baudrate indicator %d !\n", rate);
451 return -1;
454 lpdcb->BaudRate = rate;
456 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
458 ptr = strtok(NULL, ", ");
459 if (islower(*ptr))
460 *ptr = toupper(*ptr);
462 TRACE("parity (%c)\n", *ptr);
463 lpdcb->fParity = TRUE;
464 switch (*ptr) {
465 case 'N':
466 lpdcb->Parity = NOPARITY;
467 lpdcb->fParity = FALSE;
468 break;
469 case 'E':
470 lpdcb->Parity = EVENPARITY;
471 break;
472 case 'M':
473 lpdcb->Parity = MARKPARITY;
474 break;
475 case 'O':
476 lpdcb->Parity = ODDPARITY;
477 break;
478 default:
479 WARN("Unknown parity `%c'!\n", *ptr);
480 return -1;
483 ptr = strtok(NULL, ", ");
484 TRACE("charsize (%c)\n", *ptr);
485 lpdcb->ByteSize = *ptr - '0';
487 ptr = strtok(NULL, ", ");
488 TRACE("stopbits (%c)\n", *ptr);
489 switch (*ptr) {
490 case '1':
491 lpdcb->StopBits = ONESTOPBIT;
492 break;
493 case '2':
494 lpdcb->StopBits = TWOSTOPBITS;
495 break;
496 default:
497 WARN("Unknown # of stopbits `%c'!\n", *ptr);
498 return -1;
502 return 0;
505 /*****************************************************************************
506 * OpenComm16 (USER.200)
508 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
510 int port,fd;
512 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
514 if (strlen(device) < 4)
515 return IE_BADID;
517 port = device[3] - '0';
519 if (port-- == 0)
520 ERR("BUG ! COM0 or LPT0 don't exist !\n");
522 if (!strncasecmp(device,"COM",3)) {
524 TRACE("%s = %s\n", device, COM[port].devicename);
526 if (!ValidCOMPort(port))
527 return IE_BADID;
529 if (COM[port].fd)
530 return IE_OPEN;
532 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
533 if (fd == -1) {
534 ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno));
535 return IE_HARDWARE;
536 } else {
537 unknown[port] = SEGPTR_ALLOC(40);
538 bzero(unknown[port],40);
539 COM[port].fd = fd;
540 COM[port].commerror = 0;
541 COM[port].eventmask = 0;
542 COM[port].evtchar = 0; /* FIXME: default? */
543 /* save terminal state */
544 tcgetattr(fd,&m_stat[port]);
545 /* set default parameters */
546 if(COM[port].baudrate>-1){
547 DCB16 dcb;
548 GetCommState16(port, &dcb);
549 dcb.BaudRate=COM[port].baudrate;
550 /* more defaults:
551 * databits, parity, stopbits
553 SetCommState16( &dcb);
555 /* init priority characters */
556 COM[port].unget = -1;
557 COM[port].xmit = -1;
558 /* allocate buffers */
559 COM[port].ibuf_size = cbInQueue;
560 COM[port].ibuf_head = COM[port].ibuf_tail = 0;
561 COM[port].obuf_size = cbOutQueue;
562 COM[port].obuf_head = COM[port].obuf_tail = 0;
564 COM[port].inbuf = malloc(cbInQueue);
565 if (COM[port].inbuf) {
566 COM[port].outbuf = malloc(cbOutQueue);
567 if (!COM[port].outbuf)
568 free(COM[port].inbuf);
569 } else COM[port].outbuf = NULL;
570 if (!COM[port].outbuf) {
571 /* not enough memory */
572 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
573 close(COM[port].fd);
574 ERR("out of memory\n");
575 return IE_MEMORY;
578 COM[port].s_read = INVALID_HANDLE_VALUE;
579 COM[port].s_write = INVALID_HANDLE_VALUE;
580 comm_waitread( &COM[port] );
581 return port;
584 else
585 if (!strncasecmp(device,"LPT",3)) {
587 if (!ValidLPTPort(port))
588 return IE_BADID;
590 if (LPT[port].fd)
591 return IE_OPEN;
593 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
594 if (fd == -1) {
595 return IE_HARDWARE;
596 } else {
597 LPT[port].fd = fd;
598 LPT[port].commerror = 0;
599 LPT[port].eventmask = 0;
600 return port|FLAG_LPT;
603 return 0;
606 /*****************************************************************************
607 * CloseComm16 (USER.207)
609 INT16 WINAPI CloseComm16(INT16 cid)
611 struct DosDeviceStruct *ptr;
613 TRACE("cid=%d\n", cid);
614 if ((ptr = GetDeviceStruct(cid)) == NULL) {
615 FIXME("no cid=%d found!\n", cid);
616 return -1;
618 if (!(cid&FLAG_LPT)) {
619 /* COM port */
620 SEGPTR_FREE(unknown[cid]); /* [LW] */
622 SERVICE_Delete( COM[cid].s_write );
623 SERVICE_Delete( COM[cid].s_read );
624 /* free buffers */
625 free(ptr->outbuf);
626 free(ptr->inbuf);
628 /* reset modem lines */
629 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
632 if (close(ptr->fd) == -1) {
633 ptr->commerror = WinError();
634 /* FIXME: should we clear ptr->fd here? */
635 return -1;
636 } else {
637 ptr->commerror = 0;
638 ptr->fd = 0;
639 return 0;
643 /*****************************************************************************
644 * SetCommBreak16 (USER.210)
646 INT16 WINAPI SetCommBreak16(INT16 cid)
648 struct DosDeviceStruct *ptr;
650 TRACE("cid=%d\n", cid);
651 if ((ptr = GetDeviceStruct(cid)) == NULL) {
652 FIXME("no cid=%d found!\n", cid);
653 return -1;
656 ptr->suspended = 1;
657 ptr->commerror = 0;
658 return 0;
661 /*****************************************************************************
662 * ClearCommBreak16 (USER.211)
664 INT16 WINAPI ClearCommBreak16(INT16 cid)
666 struct DosDeviceStruct *ptr;
668 TRACE("cid=%d\n", cid);
669 if (!(ptr = GetDeviceStruct(cid))) {
670 FIXME("no cid=%d found!\n", cid);
671 return -1;
673 ptr->suspended = 0;
674 ptr->commerror = 0;
675 return 0;
678 /*****************************************************************************
679 * EscapeCommFunction16 (USER.214)
681 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
683 int max;
684 struct DosDeviceStruct *ptr;
685 struct termios port;
687 TRACE("cid=%d, function=%d\n", cid, nFunction);
688 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
689 if ((ptr = GetDeviceStruct(cid)) == NULL) {
690 FIXME("no cid=%d found!\n", cid);
691 return -1;
693 if (tcgetattr(ptr->fd,&port) == -1) {
694 TRACE("tcgetattr failed\n");
695 ptr->commerror=WinError();
696 return -1;
698 } else ptr = NULL;
700 switch (nFunction) {
701 case RESETDEV:
702 TRACE("RESETDEV\n");
703 break;
705 case GETMAXCOM:
706 TRACE("GETMAXCOM\n");
707 for (max = MAX_PORTS;!COM[max].devicename;max--)
709 return max;
710 break;
712 case GETMAXLPT:
713 TRACE("GETMAXLPT\n");
714 for (max = MAX_PORTS;!LPT[max].devicename;max--)
716 return FLAG_LPT + max;
717 break;
719 case GETBASEIRQ:
720 TRACE("GETBASEIRQ\n");
721 /* FIXME: use tables */
722 /* just fake something for now */
723 if (cid & FLAG_LPT) {
724 /* LPT1: irq 7, LPT2: irq 5 */
725 return (cid & 0x7f) ? 5 : 7;
726 } else {
727 /* COM1: irq 4, COM2: irq 3,
728 COM3: irq 4, COM4: irq 3 */
729 return 4 - (cid & 1);
731 break;
733 case CLRDTR:
734 TRACE("CLRDTR\n");
735 #ifdef TIOCM_DTR
736 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
737 #endif
738 case CLRRTS:
739 TRACE("CLRRTS\n");
740 #ifdef TIOCM_RTS
741 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
742 #endif
744 case SETDTR:
745 TRACE("SETDTR\n");
746 #ifdef TIOCM_DTR
747 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
748 #endif
750 case SETRTS:
751 TRACE("SETRTS\n");
752 #ifdef TIOCM_RTS
753 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
754 #endif
756 case SETXOFF:
757 TRACE("SETXOFF\n");
758 port.c_iflag |= IXOFF;
759 break;
761 case SETXON:
762 TRACE("SETXON\n");
763 port.c_iflag |= IXON;
764 break;
766 default:
767 WARN("(cid=%d,nFunction=%d): Unknown function\n",
768 cid, nFunction);
769 break;
772 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
773 ptr->commerror = WinError();
774 return -1;
775 } else {
776 ptr->commerror = 0;
777 return 0;
781 /*****************************************************************************
782 * FlushComm16 (USER.215)
784 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
786 int queue;
787 struct DosDeviceStruct *ptr;
789 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
790 if ((ptr = GetDeviceStruct(cid)) == NULL) {
791 FIXME("no cid=%d found!\n", cid);
792 return -1;
794 switch (fnQueue) {
795 case 0:
796 queue = TCOFLUSH;
797 ptr->obuf_tail = ptr->obuf_head;
798 break;
799 case 1:
800 queue = TCIFLUSH;
801 ptr->ibuf_head = ptr->ibuf_tail;
802 break;
803 default:
804 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
805 cid, fnQueue);
806 return -1;
808 if (tcflush(ptr->fd, queue)) {
809 ptr->commerror = WinError();
810 return -1;
811 } else {
812 ptr->commerror = 0;
813 return 0;
817 /********************************************************************
818 * GetCommError16 (USER.203)
820 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
822 int temperror;
823 struct DosDeviceStruct *ptr;
824 unsigned char *stol;
825 unsigned int mstat;
827 if ((ptr = GetDeviceStruct(cid)) == NULL) {
828 FIXME("no handle for cid = %0x!\n",cid);
829 return -1;
831 if (cid&FLAG_LPT) {
832 WARN(" cid %d not comm port\n",cid);
833 return CE_MODE;
835 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
836 ioctl(ptr->fd,TIOCMGET,&mstat);
837 COMM_MSRUpdate( stol, mstat);
839 if (lpStat) {
840 lpStat->status = 0;
842 lpStat->cbOutQue = comm_outbuf(ptr);
843 lpStat->cbInQue = comm_inbuf(ptr);
845 TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
846 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
847 lpStat->cbOutQue, *stol);
849 else
850 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
851 cid, ptr->commerror, *stol);
853 /* Return any errors and clear it */
854 temperror = ptr->commerror;
855 ptr->commerror = 0;
856 return(temperror);
859 /*****************************************************************************
860 * SetCommEventMask16 (USER.208)
862 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
864 struct DosDeviceStruct *ptr;
865 unsigned char *stol;
866 int repid;
867 unsigned int mstat;
869 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
870 if ((ptr = GetDeviceStruct(cid)) == NULL) {
871 FIXME("no handle for cid = %0x!\n",cid);
872 return (SEGPTR)NULL;
875 ptr->eventmask = fuEvtMask;
877 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
878 WARN(" cid %d not comm port\n",cid);
879 return (SEGPTR)NULL;
881 /* it's a COM port ? -> modify flags */
882 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
883 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
884 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
885 COMM_MSRUpdate( stol, mstat);
887 TRACE(" modem dcd construct %x\n",*stol);
888 return SEGPTR_GET(unknown[cid]);
891 /*****************************************************************************
892 * GetCommEventMask16 (USER.209)
894 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
896 struct DosDeviceStruct *ptr;
897 WORD events;
899 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
900 if ((ptr = GetDeviceStruct(cid)) == NULL) {
901 FIXME("no handle for cid = %0x!\n",cid);
902 return 0;
905 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
906 WARN(" cid %d not comm port\n",cid);
907 return 0;
910 events = *(WORD*)(unknown[cid]) & fnEvtClear;
911 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
912 return events;
915 /*****************************************************************************
916 * SetCommState16 (USER.201)
918 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
920 struct termios port;
921 struct DosDeviceStruct *ptr;
922 int bytesize, stopbits;
923 int fail=0;
925 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
926 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
927 FIXME("no handle for cid = %0x!\n",lpdcb->Id);
928 return -1;
930 if (tcgetattr(ptr->fd, &port) == -1) {
931 ptr->commerror = WinError();
932 return -1;
935 port.c_cc[VMIN] = 0;
936 port.c_cc[VTIME] = 1;
938 #ifdef IMAXBEL
939 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
940 #else
941 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
942 #endif
943 port.c_iflag |= (IGNBRK);
945 port.c_oflag &= ~(OPOST);
947 port.c_cflag &= ~(HUPCL);
948 port.c_cflag |= CLOCAL | CREAD;
950 port.c_lflag &= ~(ICANON|ECHO|ISIG);
951 port.c_lflag |= NOFLSH;
953 TRACE("baudrate %d\n",lpdcb->BaudRate);
954 #ifdef CBAUD
955 port.c_cflag &= ~CBAUD;
956 switch (lpdcb->BaudRate) {
957 case 110:
958 case CBR_110:
959 port.c_cflag |= B110;
960 break;
961 case 300:
962 case CBR_300:
963 port.c_cflag |= B300;
964 break;
965 case 600:
966 case CBR_600:
967 port.c_cflag |= B600;
968 break;
969 case 1200:
970 case CBR_1200:
971 port.c_cflag |= B1200;
972 break;
973 case 2400:
974 case CBR_2400:
975 port.c_cflag |= B2400;
976 break;
977 case 4800:
978 case CBR_4800:
979 port.c_cflag |= B4800;
980 break;
981 case 9600:
982 case CBR_9600:
983 port.c_cflag |= B9600;
984 break;
985 case 19200:
986 case CBR_19200:
987 port.c_cflag |= B19200;
988 break;
989 case 38400:
990 case CBR_38400:
991 port.c_cflag |= B38400;
992 break;
993 #ifdef B57600
994 case 57600:
995 port.c_cflag |= B57600;
996 break;
997 #endif
998 #ifdef B115200
999 case 57601:
1000 port.c_cflag |= B115200;
1001 break;
1002 #endif
1003 default:
1004 ptr->commerror = IE_BAUDRATE;
1005 fail=1;
1007 #elif !defined(__EMX__)
1008 switch (lpdcb->BaudRate) {
1009 case 110:
1010 case CBR_110:
1011 port.c_ospeed = B110;
1012 break;
1013 case 300:
1014 case CBR_300:
1015 port.c_ospeed = B300;
1016 break;
1017 case 600:
1018 case CBR_600:
1019 port.c_ospeed = B600;
1020 break;
1021 case 1200:
1022 case CBR_1200:
1023 port.c_ospeed = B1200;
1024 break;
1025 case 2400:
1026 case CBR_2400:
1027 port.c_ospeed = B2400;
1028 break;
1029 case 4800:
1030 case CBR_4800:
1031 port.c_ospeed = B4800;
1032 break;
1033 case 9600:
1034 case CBR_9600:
1035 port.c_ospeed = B9600;
1036 break;
1037 case 19200:
1038 case CBR_19200:
1039 port.c_ospeed = B19200;
1040 break;
1041 case 38400:
1042 case CBR_38400:
1043 port.c_ospeed = B38400;
1044 break;
1045 default:
1046 ptr->commerror = IE_BAUDRATE;
1047 fail=1;
1049 port.c_ispeed = port.c_ospeed;
1050 #endif
1051 bytesize=lpdcb->ByteSize;
1052 stopbits=lpdcb->StopBits;
1054 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
1055 #ifdef CMSPAR
1056 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1057 #else
1058 port.c_cflag &= ~(PARENB | PARODD);
1059 #endif
1060 if (lpdcb->fParity)
1061 port.c_iflag |= INPCK;
1062 else
1063 port.c_iflag &= ~INPCK;
1064 switch (lpdcb->Parity) {
1065 case NOPARITY:
1066 break;
1067 case ODDPARITY:
1068 port.c_cflag |= (PARENB | PARODD);
1069 break;
1070 case EVENPARITY:
1071 port.c_cflag |= PARENB;
1072 break;
1073 #ifdef CMSPAR
1074 /* Linux defines mark/space (stick) parity */
1075 case MARKPARITY:
1076 port.c_cflag |= (PARENB | CMSPAR);
1077 break;
1078 case SPACEPARITY:
1079 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1080 break;
1081 #else
1082 /* try the POSIX way */
1083 case MARKPARITY:
1084 if( stopbits == ONESTOPBIT) {
1085 stopbits = TWOSTOPBITS;
1086 port.c_iflag &= ~INPCK;
1087 } else {
1088 ptr->commerror = IE_BYTESIZE;
1089 fail=1;
1091 break;
1092 case SPACEPARITY:
1093 if( bytesize < 8) {
1094 bytesize +=1;
1095 port.c_iflag &= ~INPCK;
1096 } else {
1097 ptr->commerror = IE_BYTESIZE;
1098 fail=1;
1100 break;
1101 #endif
1102 default:
1103 ptr->commerror = IE_BYTESIZE;
1104 fail=1;
1107 TRACE("bytesize %d\n",bytesize);
1108 port.c_cflag &= ~CSIZE;
1109 switch (bytesize) {
1110 case 5:
1111 port.c_cflag |= CS5;
1112 break;
1113 case 6:
1114 port.c_cflag |= CS6;
1115 break;
1116 case 7:
1117 port.c_cflag |= CS7;
1118 break;
1119 case 8:
1120 port.c_cflag |= CS8;
1121 break;
1122 default:
1123 ptr->commerror = IE_BYTESIZE;
1124 fail=1;
1127 TRACE("stopbits %d\n",stopbits);
1129 switch (stopbits) {
1130 case ONESTOPBIT:
1131 port.c_cflag &= ~CSTOPB;
1132 break;
1133 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1134 case TWOSTOPBITS:
1135 port.c_cflag |= CSTOPB;
1136 break;
1137 default:
1138 ptr->commerror = IE_BYTESIZE;
1139 fail=1;
1141 #ifdef CRTSCTS
1143 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1144 port.c_cflag |= CRTSCTS;
1146 if (lpdcb->fDtrDisable)
1147 port.c_cflag &= ~CRTSCTS;
1148 #endif
1149 if (lpdcb->fInX)
1150 port.c_iflag |= IXON;
1151 else
1152 port.c_iflag &= ~IXON;
1153 if (lpdcb->fOutX)
1154 port.c_iflag |= IXOFF;
1155 else
1156 port.c_iflag &= ~IXOFF;
1158 ptr->evtchar = lpdcb->EvtChar;
1160 if(fail)
1161 return -1;
1163 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1164 ptr->commerror = WinError();
1165 return -1;
1166 } else {
1167 ptr->commerror = 0;
1168 return 0;
1172 /*****************************************************************************
1173 * GetCommState16 (USER.202)
1175 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1177 int speed;
1178 struct DosDeviceStruct *ptr;
1179 struct termios port;
1181 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1182 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1183 FIXME("no handle for cid = %0x!\n",cid);
1184 return -1;
1186 if (tcgetattr(ptr->fd, &port) == -1) {
1187 ptr->commerror = WinError();
1188 return -1;
1190 lpdcb->Id = cid;
1191 #ifndef __EMX__
1192 #ifdef CBAUD
1193 speed = port.c_cflag & CBAUD;
1194 #else
1195 speed = port.c_ospeed;
1196 #endif
1197 switch(speed) {
1198 case B110:
1199 lpdcb->BaudRate = 110;
1200 break;
1201 case B300:
1202 lpdcb->BaudRate = 300;
1203 break;
1204 case B600:
1205 lpdcb->BaudRate = 600;
1206 break;
1207 case B1200:
1208 lpdcb->BaudRate = 1200;
1209 break;
1210 case B2400:
1211 lpdcb->BaudRate = 2400;
1212 break;
1213 case B4800:
1214 lpdcb->BaudRate = 4800;
1215 break;
1216 case B9600:
1217 lpdcb->BaudRate = 9600;
1218 break;
1219 case B19200:
1220 lpdcb->BaudRate = 19200;
1221 break;
1222 case B38400:
1223 lpdcb->BaudRate = 38400;
1224 break;
1225 #ifdef B57600
1226 case B57600:
1227 lpdcb->BaudRate = 57600;
1228 break;
1229 #endif
1230 #ifdef B115200
1231 case B115200:
1232 lpdcb->BaudRate = 57601;
1233 break;
1234 #endif
1236 #endif
1237 switch (port.c_cflag & CSIZE) {
1238 case CS5:
1239 lpdcb->ByteSize = 5;
1240 break;
1241 case CS6:
1242 lpdcb->ByteSize = 6;
1243 break;
1244 case CS7:
1245 lpdcb->ByteSize = 7;
1246 break;
1247 case CS8:
1248 lpdcb->ByteSize = 8;
1249 break;
1252 if(port.c_iflag & INPCK)
1253 lpdcb->fParity = TRUE;
1254 else
1255 lpdcb->fParity = FALSE;
1256 #ifdef CMSPAR
1257 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1258 #else
1259 switch (port.c_cflag & (PARENB | PARODD))
1260 #endif
1262 case 0:
1263 lpdcb->Parity = NOPARITY;
1264 break;
1265 case PARENB:
1266 lpdcb->Parity = EVENPARITY;
1267 break;
1268 case (PARENB | PARODD):
1269 lpdcb->Parity = ODDPARITY;
1270 break;
1271 #ifdef CMSPAR
1272 case (PARENB | CMSPAR):
1273 lpdcb->Parity = MARKPARITY;
1274 break;
1275 case (PARENB | PARODD | CMSPAR):
1276 lpdcb->Parity = SPACEPARITY;
1277 break;
1278 #endif
1281 if (port.c_cflag & CSTOPB)
1282 if(lpdcb->ByteSize == 5)
1283 lpdcb->StopBits = ONE5STOPBITS;
1284 else
1285 lpdcb->StopBits = TWOSTOPBITS;
1286 else
1287 lpdcb->StopBits = ONESTOPBIT;
1289 lpdcb->RlsTimeout = 50;
1290 lpdcb->CtsTimeout = 50;
1291 lpdcb->DsrTimeout = 50;
1292 lpdcb->fNull = 0;
1293 lpdcb->fChEvt = 0;
1294 lpdcb->fBinary = 1;
1295 lpdcb->fDtrDisable = 0;
1297 #ifdef CRTSCTS
1299 if (port.c_cflag & CRTSCTS) {
1300 lpdcb->fDtrflow = 1;
1301 lpdcb->fRtsflow = 1;
1302 lpdcb->fOutxCtsFlow = 1;
1303 lpdcb->fOutxDsrFlow = 1;
1304 } else
1305 #endif
1306 lpdcb->fDtrDisable = 1;
1308 if (port.c_iflag & IXON)
1309 lpdcb->fInX = 1;
1310 else
1311 lpdcb->fInX = 0;
1313 if (port.c_iflag & IXOFF)
1314 lpdcb->fOutX = 1;
1315 else
1316 lpdcb->fOutX = 0;
1318 lpdcb->XonChar =
1319 lpdcb->XoffChar =
1321 lpdcb->XonLim = 10;
1322 lpdcb->XoffLim = 10;
1324 lpdcb->EvtChar = ptr->evtchar;
1326 ptr->commerror = 0;
1327 return 0;
1330 /*****************************************************************************
1331 * TransmitCommChar16 (USER.206)
1333 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1335 struct DosDeviceStruct *ptr;
1337 TRACE("cid %d, data %d \n", cid, chTransmit);
1338 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1339 FIXME("no handle for cid = %0x!\n",cid);
1340 return -1;
1343 if (ptr->suspended) {
1344 ptr->commerror = IE_HARDWARE;
1345 return -1;
1348 if (ptr->xmit >= 0) {
1349 /* character already queued */
1350 /* FIXME: which error would Windows return? */
1351 ptr->commerror = CE_TXFULL;
1352 return -1;
1355 if (ptr->obuf_head == ptr->obuf_tail) {
1356 /* transmit queue empty, try to transmit directly */
1357 if (write(ptr->fd, &chTransmit, 1) == -1) {
1358 /* didn't work, queue it */
1359 ptr->xmit = chTransmit;
1360 comm_waitwrite(ptr);
1362 } else {
1363 /* data in queue, let this char be transmitted next */
1364 ptr->xmit = chTransmit;
1365 comm_waitwrite(ptr);
1368 ptr->commerror = 0;
1369 return 0;
1372 /*****************************************************************************
1373 * UngetCommChar16 (USER.212)
1375 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1377 struct DosDeviceStruct *ptr;
1379 TRACE("cid %d (char %d)\n", cid, chUnget);
1380 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1381 FIXME("no handle for cid = %0x!\n",cid);
1382 return -1;
1385 if (ptr->suspended) {
1386 ptr->commerror = IE_HARDWARE;
1387 return -1;
1390 if (ptr->unget>=0) {
1391 /* character already queued */
1392 /* FIXME: which error would Windows return? */
1393 ptr->commerror = CE_RXOVER;
1394 return -1;
1397 ptr->unget = chUnget;
1399 ptr->commerror = 0;
1400 return 0;
1403 /*****************************************************************************
1404 * ReadComm16 (USER.204)
1406 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1408 int status, length;
1409 struct DosDeviceStruct *ptr;
1410 LPSTR orgBuf = lpvBuf;
1412 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1413 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1414 FIXME("no handle for cid = %0x!\n",cid);
1415 return -1;
1418 if (ptr->suspended) {
1419 ptr->commerror = IE_HARDWARE;
1420 return -1;
1423 /* read unget character */
1424 if (ptr->unget>=0) {
1425 *lpvBuf++ = ptr->unget;
1426 ptr->unget = -1;
1428 length = 1;
1429 } else
1430 length = 0;
1432 /* read from receive buffer */
1433 while (length < cbRead) {
1434 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1435 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1436 if (!status) break;
1437 if ((cbRead - length) < status)
1438 status = cbRead - length;
1440 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1441 ptr->ibuf_tail += status;
1442 if (ptr->ibuf_tail >= ptr->ibuf_size)
1443 ptr->ibuf_tail = 0;
1444 lpvBuf += status;
1445 length += status;
1448 TRACE("%.*s\n", length, orgBuf);
1449 ptr->commerror = 0;
1450 return length;
1453 /*****************************************************************************
1454 * WriteComm16 (USER.205)
1456 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1458 int status, length;
1459 struct DosDeviceStruct *ptr;
1461 TRACE("cid %d, ptr %p, length %d\n",
1462 cid, lpvBuf, cbWrite);
1463 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1464 FIXME("no handle for cid = %0x!\n",cid);
1465 return -1;
1468 if (ptr->suspended) {
1469 ptr->commerror = IE_HARDWARE;
1470 return -1;
1473 TRACE("%.*s\n", cbWrite, lpvBuf );
1475 length = 0;
1476 while (length < cbWrite) {
1477 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1478 /* no data queued, try to write directly */
1479 status = write(ptr->fd, lpvBuf, cbWrite - length);
1480 if (status > 0) {
1481 lpvBuf += status;
1482 length += status;
1483 continue;
1486 /* can't write directly, put into transmit buffer */
1487 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1488 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1489 if (!status) break;
1490 if ((cbWrite - length) < status)
1491 status = cbWrite - length;
1492 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1493 ptr->obuf_head += status;
1494 if (ptr->obuf_head >= ptr->obuf_size)
1495 ptr->obuf_head = 0;
1496 lpvBuf += status;
1497 length += status;
1498 comm_waitwrite(ptr);
1501 ptr->commerror = 0;
1502 return length;
1505 /***********************************************************************
1506 * EnableCommNotification (USER.245)
1508 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1509 INT16 cbWriteNotify, INT16 cbOutQueue )
1511 struct DosDeviceStruct *ptr;
1513 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1514 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1515 FIXME("no handle for cid = %0x!\n",cid);
1516 return -1;
1518 ptr->wnd = hwnd;
1519 ptr->n_read = cbWriteNotify;
1520 ptr->n_write = cbOutQueue;
1521 return TRUE;
1525 /**************************************************************************
1526 * BuildCommDCBA (KERNEL32.113)
1528 * Updates a device control block data structure with values from an
1529 * ascii device control string. The device control string has two forms
1530 * normal and extended, it must be exclusively in one or the other form.
1532 * RETURNS
1534 * True on success, false on an malformed control string.
1536 BOOL WINAPI BuildCommDCBA(
1537 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
1538 LPDCB lpdcb) /* [out] The device control block to be updated. */
1540 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1543 /**************************************************************************
1544 * BuildCommDCBAndTimeoutsA (KERNEL32.114)
1546 * Updates a device control block data structure with values from an
1547 * ascii device control string. Taking time out values from a time outs
1548 * struct if desired by the control string.
1550 * RETURNS
1552 * True on success, false bad handles etc
1554 BOOL WINAPI BuildCommDCBAndTimeoutsA(
1555 LPCSTR device, /* [in] The ascii device control string. */
1556 LPDCB lpdcb, /* [out] The device control block to be updated. */
1557 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
1559 int port;
1560 char *ptr,*temp;
1562 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1564 if (!strncasecmp(device,"COM",3)) {
1565 port=device[3]-'0';
1566 if (port--==0) {
1567 ERR("BUG! COM0 can't exist!\n");
1568 return FALSE;
1570 if (!ValidCOMPort(port))
1571 return FALSE;
1572 if (*(device+4)!=':')
1573 return FALSE;
1574 temp=(LPSTR)(device+5);
1575 } else
1576 temp=(LPSTR)device;
1578 lpdcb->DCBlength = sizeof(DCB);
1579 if (strchr(temp,',')) { /* old style */
1580 DCB16 dcb16;
1581 BOOL16 ret;
1582 char last=temp[strlen(temp)-1];
1584 ret=BuildCommDCB16(device,&dcb16);
1585 if (ret)
1586 return FALSE;
1587 lpdcb->BaudRate = dcb16.BaudRate;
1588 lpdcb->ByteSize = dcb16.ByteSize;
1589 lpdcb->fBinary = dcb16.fBinary;
1590 lpdcb->Parity = dcb16.Parity;
1591 lpdcb->fParity = dcb16.fParity;
1592 lpdcb->fNull = dcb16.fNull;
1593 lpdcb->StopBits = dcb16.StopBits;
1594 if (last == 'x') {
1595 lpdcb->fInX = TRUE;
1596 lpdcb->fOutX = TRUE;
1597 lpdcb->fOutxCtsFlow = FALSE;
1598 lpdcb->fOutxDsrFlow = FALSE;
1599 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1600 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1601 } else if (last=='p') {
1602 lpdcb->fInX = FALSE;
1603 lpdcb->fOutX = FALSE;
1604 lpdcb->fOutxCtsFlow = TRUE;
1605 lpdcb->fOutxDsrFlow = TRUE;
1606 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1607 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1608 } else {
1609 lpdcb->fInX = FALSE;
1610 lpdcb->fOutX = FALSE;
1611 lpdcb->fOutxCtsFlow = FALSE;
1612 lpdcb->fOutxDsrFlow = FALSE;
1613 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1614 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1616 lpdcb->XonChar = dcb16.XonChar;
1617 lpdcb->XoffChar = dcb16.XoffChar;
1618 lpdcb->ErrorChar= dcb16.PeChar;
1619 lpdcb->fErrorChar= dcb16.fPeChar;
1620 lpdcb->EofChar = dcb16.EofChar;
1621 lpdcb->EvtChar = dcb16.EvtChar;
1622 lpdcb->XonLim = dcb16.XonLim;
1623 lpdcb->XoffLim = dcb16.XoffLim;
1624 return TRUE;
1626 ptr=strtok(temp," ");
1627 while (ptr) {
1628 DWORD flag,x;
1630 flag=0;
1631 if (!strncmp("baud=",ptr,5)) {
1632 if (!sscanf(ptr+5,"%ld",&x))
1633 WARN("Couldn't parse %s\n",ptr);
1634 lpdcb->BaudRate = x;
1635 flag=1;
1637 if (!strncmp("stop=",ptr,5)) {
1638 if (!sscanf(ptr+5,"%ld",&x))
1639 WARN("Couldn't parse %s\n",ptr);
1640 lpdcb->StopBits = x;
1641 flag=1;
1643 if (!strncmp("data=",ptr,5)) {
1644 if (!sscanf(ptr+5,"%ld",&x))
1645 WARN("Couldn't parse %s\n",ptr);
1646 lpdcb->ByteSize = x;
1647 flag=1;
1649 if (!strncmp("parity=",ptr,7)) {
1650 lpdcb->fParity = TRUE;
1651 switch (ptr[8]) {
1652 case 'N':case 'n':
1653 lpdcb->fParity = FALSE;
1654 lpdcb->Parity = NOPARITY;
1655 break;
1656 case 'E':case 'e':
1657 lpdcb->Parity = EVENPARITY;
1658 break;
1659 case 'O':case 'o':
1660 lpdcb->Parity = ODDPARITY;
1661 break;
1662 case 'M':case 'm':
1663 lpdcb->Parity = MARKPARITY;
1664 break;
1666 flag=1;
1668 if (!flag)
1669 ERR("Unhandled specifier '%s', please report.\n",ptr);
1670 ptr=strtok(NULL," ");
1672 if (lpdcb->BaudRate==110)
1673 lpdcb->StopBits = 2;
1674 return TRUE;
1677 /**************************************************************************
1678 * BuildCommDCBAndTimeoutsW (KERNEL32.115)
1680 * Updates a device control block data structure with values from an
1681 * unicode device control string. Taking time out values from a time outs
1682 * struct if desired by the control string.
1684 * RETURNS
1686 * True on success, false bad handles etc.
1688 BOOL WINAPI BuildCommDCBAndTimeoutsW(
1689 LPCWSTR devid, /* [in] The unicode device control string. */
1690 LPDCB lpdcb, /* [out] The device control block to be updated. */
1691 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
1693 BOOL ret = FALSE;
1694 LPSTR devidA;
1696 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1697 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1698 if (devidA)
1700 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1701 HeapFree( GetProcessHeap(), 0, devidA );
1703 return ret;
1706 /**************************************************************************
1707 * BuildCommDCBW (KERNEL32.116)
1709 * Updates a device control block structure with values from an
1710 * unicode device control string. The device control string has two forms
1711 * normal and extended, it must be exclusively in one or the other form.
1713 * RETURNS
1715 * True on success, false on an malformed control string.
1717 BOOL WINAPI BuildCommDCBW(
1718 LPCWSTR devid, /* [in] The unicode device control string. */
1719 LPDCB lpdcb) /* [out] The device control block to be updated. */
1721 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1724 /* FIXME: having these global for win32 for now */
1725 int commerror=0;
1727 /*****************************************************************************
1728 * SetCommBreak (KERNEL32.616)
1730 * Halts the transmission of characters to a communications device.
1732 * RETURNS
1734 * True on success, and false if the communications device could not be found,
1735 * the control is not supported.
1737 * BUGS
1739 * Only TIOCSBRK and TIOCCBRK are supported.
1741 BOOL WINAPI SetCommBreak(
1742 HANDLE handle) /* [in] The communictions device to suspend. */
1744 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1745 int fd,result;
1747 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1748 if(fd<0) {
1749 TRACE("FILE_GetUnixHandle failed\n");
1750 return FALSE;
1752 result = ioctl(fd,TIOCSBRK,0);
1753 close(fd);
1754 if (result ==-1)
1756 TRACE("ioctl failed\n");
1757 SetLastError(ERROR_NOT_SUPPORTED);
1758 return FALSE;
1760 return TRUE;
1761 #else
1762 FIXME("ioctl not available\n");
1763 SetLastError(ERROR_NOT_SUPPORTED);
1764 return FALSE;
1765 #endif
1768 /*****************************************************************************
1769 * ClearCommBreak (KERNEL32.135)
1771 * Resumes character transmission from a communication device.
1773 * RETURNS
1775 * True on success and false if the communications device could not be found.
1777 * BUGS
1779 * Only TIOCSBRK and TIOCCBRK are supported.
1781 BOOL WINAPI ClearCommBreak(
1782 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
1784 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1785 int fd,result;
1787 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1788 if(fd<0) {
1789 TRACE("FILE_GetUnixHandle failed\n");
1790 return FALSE;
1792 result = ioctl(fd,TIOCCBRK,0);
1793 close(fd);
1794 if (result ==-1)
1796 TRACE("ioctl failed\n");
1797 SetLastError(ERROR_NOT_SUPPORTED);
1798 return FALSE;
1800 return TRUE;
1801 #else
1802 FIXME("ioctl not available\n");
1803 SetLastError(ERROR_NOT_SUPPORTED);
1804 return FALSE;
1805 #endif
1808 /*****************************************************************************
1809 * EscapeCommFunction (KERNEL32.213)
1811 * Directs a communication device to perform an extended function.
1813 * RETURNS
1815 * True or requested data on successful completion of the command,
1816 * false if the device is not present cannot execute the command
1817 * or the command failed.
1819 BOOL WINAPI EscapeCommFunction(
1820 HANDLE handle, /* [in] The communication device to perform the extended function. */
1821 UINT nFunction) /* [in] The extended function to be performed. */
1823 int fd,direct=FALSE,result=FALSE;
1824 struct termios port;
1826 TRACE("handle %d, function=%d\n", handle, nFunction);
1827 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1828 if(fd<0) {
1829 FIXME("handle %d not found.\n",handle);
1830 return FALSE;
1833 if (tcgetattr(fd,&port) == -1) {
1834 commerror=WinError();
1835 close(fd);
1836 return FALSE;
1839 switch (nFunction) {
1840 case RESETDEV:
1841 TRACE("\n");
1842 break;
1844 case CLRDTR:
1845 TRACE("CLRDTR\n");
1846 #ifdef TIOCM_DTR
1847 direct=TRUE;
1848 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1849 break;
1850 #endif
1852 case CLRRTS:
1853 TRACE("CLRRTS\n");
1854 #ifdef TIOCM_RTS
1855 direct=TRUE;
1856 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1857 break;
1858 #endif
1860 case SETDTR:
1861 TRACE("SETDTR\n");
1862 #ifdef TIOCM_DTR
1863 direct=TRUE;
1864 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1865 break;
1866 #endif
1868 case SETRTS:
1869 TRACE("SETRTS\n");
1870 #ifdef TIOCM_DTR
1871 direct=TRUE;
1872 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1873 break;
1874 #endif
1876 case SETXOFF:
1877 TRACE("SETXOFF\n");
1878 port.c_iflag |= IXOFF;
1879 break;
1881 case SETXON:
1882 TRACE("SETXON\n");
1883 port.c_iflag |= IXON;
1884 break;
1885 case SETBREAK:
1886 TRACE("setbreak\n");
1887 #ifdef TIOCSBRK
1888 direct=TRUE;
1889 result = ioctl(fd,TIOCSBRK,0);
1890 break;
1891 #endif
1892 case CLRBREAK:
1893 TRACE("clrbreak\n");
1894 #ifdef TIOCSBRK
1895 direct=TRUE;
1896 result = ioctl(fd,TIOCCBRK,0);
1897 break;
1898 #endif
1899 default:
1900 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1901 handle, nFunction);
1902 break;
1905 if (!direct)
1906 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1907 commerror = WinError();
1908 close(fd);
1909 return FALSE;
1910 } else
1911 result= TRUE;
1912 else
1914 if (result == -1)
1916 result= FALSE;
1917 commerror=WinError();
1919 else
1920 result = TRUE;
1922 close(fd);
1923 return result;
1926 /********************************************************************
1927 * PurgeComm (KERNEL32.558)
1929 * Terminates pending operations and/or discards buffers on a
1930 * communication resource.
1932 * RETURNS
1934 * True on success and false if the communications handle is bad.
1936 BOOL WINAPI PurgeComm(
1937 HANDLE handle, /* [in] The communication resource to be purged. */
1938 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
1940 int fd;
1942 TRACE("handle %d, flags %lx\n", handle, flags);
1944 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1945 if(fd<0) {
1946 FIXME("no handle %d found\n",handle);
1947 return FALSE;
1951 ** not exactly sure how these are different
1952 ** Perhaps if we had our own internal queues, one flushes them
1953 ** and the other flushes the kernel's buffers.
1955 if(flags&PURGE_TXABORT)
1956 tcflush(fd,TCOFLUSH);
1957 if(flags&PURGE_RXABORT)
1958 tcflush(fd,TCIFLUSH);
1959 if(flags&PURGE_TXCLEAR)
1960 tcflush(fd,TCOFLUSH);
1961 if(flags&PURGE_RXCLEAR)
1962 tcflush(fd,TCIFLUSH);
1963 close(fd);
1965 return 1;
1968 /*****************************************************************************
1969 * ClearCommError (KERNEL32.136)
1971 * Enables further I/O operations on a communications resource after
1972 * supplying error and current status information.
1974 * RETURNS
1976 * True on success, false if the communication resource handle is bad.
1978 BOOL WINAPI ClearCommError(
1979 HANDLE handle, /* [in] The communication resource with the error. */
1980 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
1981 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
1983 int fd;
1985 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
1986 if(0>fd)
1988 FIXME("no handle %d found\n",handle);
1989 return FALSE;
1992 if (lpStat)
1994 lpStat->status = 0;
1996 #ifdef TIOCOUTQ
1997 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1998 WARN("ioctl returned error\n");
1999 #else
2000 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
2001 #endif
2003 #ifdef TIOCINQ
2004 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
2005 WARN("ioctl returned error\n");
2006 #endif
2008 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
2009 handle, lpStat->cbInQue, lpStat->cbOutQue);
2012 close(fd);
2014 if(errors)
2015 *errors = 0;
2018 ** After an asynchronous write opperation, the
2019 ** app will call ClearCommError to see if the
2020 ** results are ready yet. It waits for ERROR_IO_PENDING
2022 commerror = ERROR_IO_PENDING;
2024 return TRUE;
2027 /*****************************************************************************
2028 * SetupComm (KERNEL32.677)
2030 * Called after CreateFile to hint to the communication resource to use
2031 * specified sizes for input and output buffers rather than the default values.
2033 * RETURNS
2035 * True if successful, false if the communications resource handle is bad.
2037 * BUGS
2039 * Stub.
2041 BOOL WINAPI SetupComm(
2042 HANDLE handle, /* [in] The just created communication resource handle. */
2043 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
2044 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
2046 int fd;
2048 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
2049 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
2050 if(0>fd) {
2051 FIXME("handle %d not found?\n",handle);
2052 return FALSE;
2054 close(fd);
2055 return TRUE;
2058 /*****************************************************************************
2059 * GetCommMask (KERNEL32.284)
2061 * Obtain the events associated with a communication device that will cause a call
2062 * WaitCommEvent to return.
2064 * RETURNS
2066 * True on success, fail on bad device handle etc.
2068 BOOL WINAPI GetCommMask(
2069 HANDLE handle, /* [in] The communications device. */
2070 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
2072 BOOL ret;
2074 TRACE("handle %d, mask %p\n", handle, evtmask);
2076 SERVER_START_REQ( get_serial_info )
2078 req->handle = handle;
2079 if ((ret = !SERVER_CALL_ERR()))
2081 if (evtmask) *evtmask = req->eventmask;
2084 SERVER_END_REQ;
2085 return ret;
2088 /*****************************************************************************
2089 * SetCommMask (KERNEL32.618)
2091 * There be some things we need to hear about yon there communications device.
2092 * (Set which events associated with a communication device should cause
2093 * a call WaitCommEvent to return.)
2095 * RETURNS
2097 * True on success, false on bad handle etc.
2099 BOOL WINAPI SetCommMask(
2100 HANDLE handle, /* [in] The communications device. */
2101 DWORD evtmask) /* [in] The events that to be monitored. */
2103 BOOL ret;
2105 TRACE("handle %d, mask %lx\n", handle, evtmask);
2107 SERVER_START_REQ( set_serial_info )
2109 req->handle = handle;
2110 req->flags = SERIALINFO_SET_MASK;
2111 req->eventmask = evtmask;
2112 ret = !SERVER_CALL_ERR();
2114 SERVER_END_REQ;
2115 return ret;
2118 /*****************************************************************************
2119 * SetCommState (KERNEL32.619)
2121 * Re-initializes all hardware and control settings of a communications device,
2122 * with values from a device control block without effecting the input and output
2123 * queues.
2125 * RETURNS
2127 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
2129 BOOL WINAPI SetCommState(
2130 HANDLE handle, /* [in] The communications device. */
2131 LPDCB lpdcb) /* [out] The device control block. */
2133 struct termios port;
2134 int fd, bytesize, stopbits;
2136 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2137 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2138 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2139 (lpdcb->StopBits == ONESTOPBIT)?1:
2140 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2141 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2142 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2144 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2145 if (fd < 0) {
2146 FIXME("no handle %d found\n",handle);
2147 return FALSE;
2150 if ((tcgetattr(fd,&port)) == -1) {
2151 int save_error = errno;
2152 commerror = WinError();
2153 close( fd );
2154 ERR("tcgetattr error '%s'\n", strerror(save_error));
2155 return FALSE;
2158 port.c_cc[VMIN] = 0;
2159 port.c_cc[VTIME] = 1;
2161 #ifdef IMAXBEL
2162 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
2163 #else
2164 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
2165 #endif
2166 port.c_iflag |= (IGNBRK);
2168 port.c_oflag &= ~(OPOST);
2170 port.c_cflag &= ~(HUPCL);
2171 port.c_cflag |= CLOCAL | CREAD;
2173 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2174 port.c_lflag |= NOFLSH;
2177 ** MJM - removed default baudrate settings
2178 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2180 #ifdef CBAUD
2181 port.c_cflag &= ~CBAUD;
2182 switch (lpdcb->BaudRate) {
2183 case 110:
2184 case CBR_110:
2185 port.c_cflag |= B110;
2186 break;
2187 case 300:
2188 case CBR_300:
2189 port.c_cflag |= B300;
2190 break;
2191 case 600:
2192 case CBR_600:
2193 port.c_cflag |= B600;
2194 break;
2195 case 1200:
2196 case CBR_1200:
2197 port.c_cflag |= B1200;
2198 break;
2199 case 2400:
2200 case CBR_2400:
2201 port.c_cflag |= B2400;
2202 break;
2203 case 4800:
2204 case CBR_4800:
2205 port.c_cflag |= B4800;
2206 break;
2207 case 9600:
2208 case CBR_9600:
2209 port.c_cflag |= B9600;
2210 break;
2211 case 19200:
2212 case CBR_19200:
2213 port.c_cflag |= B19200;
2214 break;
2215 case 38400:
2216 case CBR_38400:
2217 port.c_cflag |= B38400;
2218 break;
2219 #ifdef B57600
2220 case 57600:
2221 port.c_cflag |= B57600;
2222 break;
2223 #endif
2224 #ifdef B115200
2225 case 115200:
2226 port.c_cflag |= B115200;
2227 break;
2228 #endif
2229 #ifdef B230400
2230 case 230400:
2231 port.c_cflag |= B230400;
2232 break;
2233 #endif
2234 #ifdef B460800
2235 case 460600:
2236 port.c_cflag |= B460800;
2237 break;
2238 #endif
2239 default:
2240 commerror = IE_BAUDRATE;
2241 close( fd );
2242 ERR("baudrate %ld\n",lpdcb->BaudRate);
2243 return FALSE;
2245 #elif !defined(__EMX__)
2246 switch (lpdcb->BaudRate) {
2247 case 110:
2248 case CBR_110:
2249 port.c_ospeed = B110;
2250 break;
2251 case 300:
2252 case CBR_300:
2253 port.c_ospeed = B300;
2254 break;
2255 case 600:
2256 case CBR_600:
2257 port.c_ospeed = B600;
2258 break;
2259 case 1200:
2260 case CBR_1200:
2261 port.c_ospeed = B1200;
2262 break;
2263 case 2400:
2264 case CBR_2400:
2265 port.c_ospeed = B2400;
2266 break;
2267 case 4800:
2268 case CBR_4800:
2269 port.c_ospeed = B4800;
2270 break;
2271 case 9600:
2272 case CBR_9600:
2273 port.c_ospeed = B9600;
2274 break;
2275 case 19200:
2276 case CBR_19200:
2277 port.c_ospeed = B19200;
2278 break;
2279 case 38400:
2280 case CBR_38400:
2281 port.c_ospeed = B38400;
2282 break;
2283 default:
2284 commerror = IE_BAUDRATE;
2285 close( fd );
2286 ERR("baudrate %ld\n",lpdcb->BaudRate);
2287 return FALSE;
2289 port.c_ispeed = port.c_ospeed;
2290 #endif
2291 bytesize=lpdcb->ByteSize;
2292 stopbits=lpdcb->StopBits;
2294 #ifdef CMSPAR
2295 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2296 #else
2297 port.c_cflag &= ~(PARENB | PARODD);
2298 #endif
2299 if (lpdcb->fParity)
2300 port.c_iflag |= INPCK;
2301 else
2302 port.c_iflag &= ~INPCK;
2303 switch (lpdcb->Parity) {
2304 case NOPARITY:
2305 break;
2306 case ODDPARITY:
2307 port.c_cflag |= (PARENB | PARODD);
2308 break;
2309 case EVENPARITY:
2310 port.c_cflag |= PARENB;
2311 break;
2312 #ifdef CMSPAR
2313 /* Linux defines mark/space (stick) parity */
2314 case MARKPARITY:
2315 port.c_cflag |= (PARENB | CMSPAR);
2316 break;
2317 case SPACEPARITY:
2318 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2319 break;
2320 #else
2321 /* try the POSIX way */
2322 case MARKPARITY:
2323 if( stopbits == ONESTOPBIT) {
2324 stopbits = TWOSTOPBITS;
2325 port.c_iflag &= ~INPCK;
2326 } else {
2327 commerror = IE_BYTESIZE;
2328 close( fd );
2329 ERR("Cannot set MARK Parity\n");
2330 return FALSE;
2332 break;
2333 case SPACEPARITY:
2334 if( bytesize < 8) {
2335 bytesize +=1;
2336 port.c_iflag &= ~INPCK;
2337 } else {
2338 commerror = IE_BYTESIZE;
2339 close( fd );
2340 ERR("Cannot set SPACE Parity\n");
2341 return FALSE;
2343 break;
2344 #endif
2345 default:
2346 commerror = IE_BYTESIZE;
2347 close( fd );
2348 ERR("Parity\n");
2349 return FALSE;
2353 port.c_cflag &= ~CSIZE;
2354 switch (bytesize) {
2355 case 5:
2356 port.c_cflag |= CS5;
2357 break;
2358 case 6:
2359 port.c_cflag |= CS6;
2360 break;
2361 case 7:
2362 port.c_cflag |= CS7;
2363 break;
2364 case 8:
2365 port.c_cflag |= CS8;
2366 break;
2367 default:
2368 commerror = IE_BYTESIZE;
2369 close( fd );
2370 ERR("ByteSize\n");
2371 return FALSE;
2374 switch (stopbits) {
2375 case ONESTOPBIT:
2376 port.c_cflag &= ~CSTOPB;
2377 break;
2378 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2379 case TWOSTOPBITS:
2380 port.c_cflag |= CSTOPB;
2381 break;
2382 default:
2383 commerror = IE_BYTESIZE;
2384 close( fd );
2385 ERR("StopBits\n");
2386 return FALSE;
2388 #ifdef CRTSCTS
2389 if ( lpdcb->fOutxCtsFlow ||
2390 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2393 port.c_cflag |= CRTSCTS;
2394 TRACE("CRTSCTS\n");
2397 if (lpdcb->fDtrControl == DTR_CONTROL_ENABLE)
2399 port.c_cflag &= ~CRTSCTS;
2400 TRACE("~CRTSCTS\n");
2403 #endif
2404 if (lpdcb->fInX)
2405 port.c_iflag |= IXON;
2406 else
2407 port.c_iflag &= ~IXON;
2408 if (lpdcb->fOutX)
2409 port.c_iflag |= IXOFF;
2410 else
2411 port.c_iflag &= ~IXOFF;
2413 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2414 int save_error=errno;
2415 commerror = WinError();
2416 close( fd );
2417 ERR("tcsetattr error '%s'\n", strerror(save_error));
2418 return FALSE;
2419 } else {
2420 commerror = 0;
2421 close( fd );
2422 return TRUE;
2427 /*****************************************************************************
2428 * GetCommState (KERNEL32.287)
2430 * Fills in a device control block with information from a communications device.
2432 * RETURNS
2434 * True on success, false if the communication device handle is bad etc
2436 * BUGS
2438 * XonChar and XoffChar are not set.
2440 BOOL WINAPI GetCommState(
2441 HANDLE handle, /* [in] The communications device. */
2442 LPDCB lpdcb) /* [out] The device control block. */
2444 struct termios port;
2445 int fd,speed;
2447 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2449 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2450 if (fd < 0)
2452 ERR("FILE_GetUnixHandle failed\n");
2453 return FALSE;
2455 if (tcgetattr(fd, &port) == -1) {
2456 int save_error=errno;
2457 ERR("tcgetattr error '%s'\n", strerror(save_error));
2458 commerror = WinError();
2459 close( fd );
2460 return FALSE;
2462 close( fd );
2463 #ifndef __EMX__
2464 #ifdef CBAUD
2465 speed= (port.c_cflag & CBAUD);
2466 #else
2467 speed= (cfgetospeed(&port));
2468 #endif
2469 switch (speed) {
2470 case B110:
2471 lpdcb->BaudRate = 110;
2472 break;
2473 case B300:
2474 lpdcb->BaudRate = 300;
2475 break;
2476 case B600:
2477 lpdcb->BaudRate = 600;
2478 break;
2479 case B1200:
2480 lpdcb->BaudRate = 1200;
2481 break;
2482 case B2400:
2483 lpdcb->BaudRate = 2400;
2484 break;
2485 case B4800:
2486 lpdcb->BaudRate = 4800;
2487 break;
2488 case B9600:
2489 lpdcb->BaudRate = 9600;
2490 break;
2491 case B19200:
2492 lpdcb->BaudRate = 19200;
2493 break;
2494 case B38400:
2495 lpdcb->BaudRate = 38400;
2496 break;
2497 #ifdef B57600
2498 case B57600:
2499 lpdcb->BaudRate = 57600;
2500 break;
2501 #endif
2502 #ifdef B115200
2503 case B115200:
2504 lpdcb->BaudRate = 115200;
2505 break;
2506 #endif
2507 #ifdef B230400
2508 case B230400:
2509 lpdcb->BaudRate = 230400;
2510 break;
2511 #endif
2512 #ifdef B460800
2513 case B460800:
2514 lpdcb->BaudRate = 460800;
2515 break;
2516 #endif
2517 default:
2518 ERR("unknown speed %x \n",speed);
2520 #endif
2521 switch (port.c_cflag & CSIZE) {
2522 case CS5:
2523 lpdcb->ByteSize = 5;
2524 break;
2525 case CS6:
2526 lpdcb->ByteSize = 6;
2527 break;
2528 case CS7:
2529 lpdcb->ByteSize = 7;
2530 break;
2531 case CS8:
2532 lpdcb->ByteSize = 8;
2533 break;
2534 default:
2535 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2538 if(port.c_iflag & INPCK)
2539 lpdcb->fParity = TRUE;
2540 else
2541 lpdcb->fParity = FALSE;
2542 #ifdef CMSPAR
2543 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
2544 #else
2545 switch (port.c_cflag & (PARENB | PARODD))
2546 #endif
2548 case 0:
2549 lpdcb->Parity = NOPARITY;
2550 break;
2551 case PARENB:
2552 lpdcb->Parity = EVENPARITY;
2553 break;
2554 case (PARENB | PARODD):
2555 lpdcb->Parity = ODDPARITY;
2556 break;
2557 #ifdef CMSPAR
2558 case (PARENB | CMSPAR):
2559 lpdcb->Parity = MARKPARITY;
2560 break;
2561 case (PARENB | PARODD | CMSPAR):
2562 lpdcb->Parity = SPACEPARITY;
2563 break;
2564 #endif
2567 if (port.c_cflag & CSTOPB)
2568 if(lpdcb->ByteSize == 5)
2569 lpdcb->StopBits = ONE5STOPBITS;
2570 else
2571 lpdcb->StopBits = TWOSTOPBITS;
2572 else
2573 lpdcb->StopBits = ONESTOPBIT;
2575 lpdcb->fNull = 0;
2576 lpdcb->fBinary = 1;
2578 #ifdef CRTSCTS
2580 if (port.c_cflag & CRTSCTS) {
2581 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2582 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2583 lpdcb->fOutxCtsFlow = 1;
2584 lpdcb->fOutxDsrFlow = 1;
2585 } else
2586 #endif
2588 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2589 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2591 if (port.c_iflag & IXON)
2592 lpdcb->fInX = 1;
2593 else
2594 lpdcb->fInX = 0;
2596 if (port.c_iflag & IXOFF)
2597 lpdcb->fOutX = 1;
2598 else
2599 lpdcb->fOutX = 0;
2601 lpdcb->XonChar =
2602 lpdcb->XoffChar =
2604 lpdcb->XonLim = 10;
2605 lpdcb->XoffLim = 10;
2607 commerror = 0;
2609 TRACE("OK\n");
2611 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2612 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2613 (lpdcb->StopBits == ONESTOPBIT)?1:
2614 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2615 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2616 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2617 #ifdef CRTSCTS
2618 if ( lpdcb->fOutxCtsFlow ||
2619 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2620 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2622 TRACE("CRTSCTS\n");
2624 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2625 TRACE("~CRTSCTS\n");
2627 #endif
2628 return TRUE;
2631 /*****************************************************************************
2632 * TransmitCommChar (KERNEL32.697)
2634 * Transmits a single character in front of any pending characters in the
2635 * output buffer. Usually used to send an interrupt character to a host.
2637 * RETURNS
2639 * True if the call succeeded, false if the previous command character to the
2640 * same device has not been sent yet the handle is bad etc.
2642 * BUGS
2644 * Stub.
2646 BOOL WINAPI TransmitCommChar(
2647 HANDLE hComm, /* [in] The communication device in need of a command character. */
2648 CHAR chTransmit) /* [in] The character to transmit. */
2650 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
2651 return TRUE;
2654 /*****************************************************************************
2655 * GetCommTimeouts (KERNEL32.288)
2657 * Obtains the request time out values for the communications device.
2659 * RETURNS
2661 * True on success, false if communications device handle is bad
2662 * or the target structure is null.
2664 BOOL WINAPI GetCommTimeouts(
2665 HANDLE hComm, /* [in] The communications device. */
2666 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request time outs. */
2668 BOOL ret;
2670 TRACE("(%x,%p)\n",hComm,lptimeouts);
2672 if(!lptimeouts)
2674 SetLastError(ERROR_INVALID_PARAMETER);
2675 return FALSE;
2678 SERVER_START_REQ( get_serial_info )
2680 req->handle = hComm;
2681 if ((ret = !SERVER_CALL_ERR()))
2683 lptimeouts->ReadIntervalTimeout = req->readinterval;
2684 lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
2685 lptimeouts->ReadTotalTimeoutConstant = req->readconst;
2686 lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
2687 lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
2690 SERVER_END_REQ;
2691 return ret;
2694 /*****************************************************************************
2695 * SetCommTimeouts (KERNEL32.620)
2697 * Sets the timeouts used when reading and writing data to/from COMM ports.
2699 * ReadIntervalTimeout
2700 * - converted and passes to linux kernel as c_cc[VTIME]
2701 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
2702 * - used in ReadFile to calculate GetOverlappedResult's timeout
2703 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
2704 * - used in WriteFile to calculate GetOverlappedResult's timeout
2706 * RETURNS
2708 * True if the time outs were set, false otherwise.
2710 BOOL WINAPI SetCommTimeouts(
2711 HANDLE hComm, /* [in] handle of COMM device */
2712 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
2714 BOOL ret;
2715 int fd;
2716 struct termios tios;
2718 TRACE("(%x,%p)\n",hComm,lptimeouts);
2720 if(!lptimeouts)
2722 SetLastError(ERROR_INVALID_PARAMETER);
2723 return FALSE;
2726 SERVER_START_REQ( set_serial_info )
2728 req->handle = hComm;
2729 req->flags = SERIALINFO_SET_TIMEOUTS;
2730 req->readinterval = lptimeouts->ReadIntervalTimeout ;
2731 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
2732 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
2733 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
2734 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
2735 ret = !SERVER_CALL_ERR();
2737 SERVER_END_REQ;
2738 if (!ret) return FALSE;
2740 /* FIXME: move this stuff to the server */
2741 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
2742 if (fd < 0) {
2743 FIXME("no fd for handle = %0x!.\n",hComm);
2744 return FALSE;
2747 if (-1==tcgetattr(fd,&tios)) {
2748 FIXME("tcgetattr on fd %d failed!\n",fd);
2749 return FALSE;
2752 /* VTIME is in 1/10 seconds */
2754 unsigned int ux_timeout;
2756 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
2758 ux_timeout = 0;
2760 else
2762 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
2763 if(ux_timeout == 0)
2765 ux_timeout = 1; /* must be at least some timeout */
2768 tios.c_cc[VTIME] = ux_timeout;
2771 if (-1==tcsetattr(fd,0,&tios)) {
2772 FIXME("tcsetattr on fd %d failed!\n",fd);
2773 return FALSE;
2775 close(fd);
2776 return TRUE;
2779 /***********************************************************************
2780 * GetCommModemStatus (KERNEL32.285)
2782 * Obtains the four control register bits if supported by the hardware.
2784 * RETURNS
2786 * True if the communications handle was good and for hardware that
2787 * control register access, false otherwise.
2789 BOOL WINAPI GetCommModemStatus(
2790 HANDLE hFile, /* [in] The communications device. */
2791 LPDWORD lpModemStat) /* [out] The control register bits. */
2793 int fd,mstat, result=FALSE;
2795 *lpModemStat=0;
2796 #ifdef TIOCMGET
2797 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
2798 if(fd<0)
2799 return FALSE;
2800 result = ioctl(fd, TIOCMGET, &mstat);
2801 close(fd);
2802 if (result == -1)
2804 WARN("ioctl failed\n");
2805 return FALSE;
2807 #ifdef TIOCM_CTS
2808 if (mstat & TIOCM_CTS)
2809 *lpModemStat |= MS_CTS_ON;
2810 #endif
2811 #ifdef TIOCM_DSR
2812 if (mstat & TIOCM_DSR)
2813 *lpModemStat |= MS_DSR_ON;
2814 #endif
2815 #ifdef TIOCM_RNG
2816 if (mstat & TIOCM_RNG)
2817 *lpModemStat |= MS_RING_ON;
2818 #endif
2819 #ifdef TIOCM_CAR
2820 /*FIXME: Not really sure about RLSD UB 990810*/
2821 if (mstat & TIOCM_CAR)
2822 *lpModemStat |= MS_RLSD_ON;
2823 #endif
2824 TRACE("%04x -> %s%s%s%s\n", mstat,
2825 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2826 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2827 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2828 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2829 return TRUE;
2830 #else
2831 return FALSE;
2832 #endif
2835 /***********************************************************************
2836 * COMM_WaitCommEventService (INTERNAL)
2838 * This function is called while the client is waiting on the
2839 * server, so we can't make any server calls here.
2841 static void COMM_WaitCommEventService(async_private *ovp, int events)
2843 LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
2845 TRACE("overlapped %p wait complete %p <- %x\n",lpOverlapped,ovp->buffer,events);
2846 if(events&POLLNVAL)
2848 lpOverlapped->Internal = STATUS_HANDLES_CLOSED;
2849 return;
2851 if(ovp->buffer)
2853 if(events&POLLIN)
2854 *ovp->buffer = EV_RXCHAR;
2857 lpOverlapped->Internal = STATUS_SUCCESS;
2862 /***********************************************************************
2863 * COMM_WaitCommEvent (INTERNAL)
2865 * This function must have an lpOverlapped.
2867 static BOOL COMM_WaitCommEvent(
2868 HANDLE hFile, /* [in] handle of comm port to wait for */
2869 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2870 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2872 int fd,ret;
2873 async_private *ovp;
2875 if(!lpOverlapped)
2877 SetLastError(ERROR_INVALID_PARAMETER);
2878 return FALSE;
2881 if(NtResetEvent(lpOverlapped->hEvent,NULL))
2882 return FALSE;
2884 lpOverlapped->Internal = STATUS_PENDING;
2885 lpOverlapped->InternalHigh = 0;
2886 lpOverlapped->Offset = 0;
2887 lpOverlapped->OffsetHigh = 0;
2889 /* start an ASYNCHRONOUS WaitCommEvent */
2890 SERVER_START_REQ( create_async )
2892 req->file_handle = hFile;
2893 req->count = 0;
2894 req->type = ASYNC_TYPE_WAIT;
2896 ret=SERVER_CALL_ERR();
2898 SERVER_END_REQ;
2900 if (ret)
2901 return FALSE;
2903 fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
2904 if(fd<0)
2905 return FALSE;
2907 ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
2908 if(!ovp)
2910 close(fd);
2911 return FALSE;
2913 ovp->lpOverlapped = lpOverlapped;
2914 ovp->timeout = 0;
2915 ovp->tv.tv_sec = 0;
2916 ovp->tv.tv_usec = 0;
2917 ovp->event = POLLIN;
2918 ovp->func = COMM_WaitCommEventService;
2919 ovp->buffer = (char *)lpdwEvents;
2920 ovp->fd = fd;
2922 ovp->next = NtCurrentTeb()->pending_list;
2923 ovp->prev = NULL;
2924 if(ovp->next)
2925 ovp->next->prev=ovp;
2926 NtCurrentTeb()->pending_list = ovp;
2928 SetLastError(ERROR_IO_PENDING);
2930 return FALSE;
2933 /***********************************************************************
2934 * WaitCommEvent (KERNEL32.719)
2936 * Wait until something interesting happens on a COMM port.
2937 * Interesting things (events) are set by calling SetCommMask before
2938 * this function is called.
2940 * RETURNS:
2941 * TRUE if successful
2942 * FALSE if failure
2944 * The set of detected events will be written to *lpdwEventMask
2945 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2947 * BUGS:
2948 * Only supports EV_RXCHAR and EV_TXEMPTY
2950 BOOL WINAPI WaitCommEvent(
2951 HANDLE hFile, /* [in] handle of comm port to wait for */
2952 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2953 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2955 OVERLAPPED ov;
2956 int ret;
2958 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2960 if(lpOverlapped)
2961 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
2963 /* if there is no overlapped structure, create our own */
2964 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
2966 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
2968 if(GetLastError()!=STATUS_PENDING)
2970 CloseHandle(ov.hEvent);
2971 return FALSE;
2974 /* wait for the overlapped to complete */
2975 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
2976 CloseHandle(ov.hEvent);
2978 return ret;
2981 /***********************************************************************
2982 * GetCommProperties (KERNEL32.286)
2984 * This function fills in a structure with the capabilities of the
2985 * communications port driver.
2987 * RETURNS
2989 * TRUE on success, FALSE on failure
2990 * If successful, the lpCommProp structure be filled in with
2991 * properties of the comm port.
2993 BOOL WINAPI GetCommProperties(
2994 HANDLE hFile, /* [in] handle of the comm port */
2995 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2997 FIXME("(%d %p )\n",hFile,lpCommProp);
2998 if(!lpCommProp)
2999 return FALSE;
3002 * These values should be valid for LINUX's serial driver
3003 * FIXME: Perhaps they deserve an #ifdef LINUX
3005 memset(lpCommProp,0,sizeof(COMMPROP));
3006 lpCommProp->wPacketLength = 1;
3007 lpCommProp->wPacketVersion = 1;
3008 lpCommProp->dwServiceMask = SP_SERIALCOMM;
3009 lpCommProp->dwReserved1 = 0;
3010 lpCommProp->dwMaxTxQueue = 4096;
3011 lpCommProp->dwMaxRxQueue = 4096;
3012 lpCommProp->dwMaxBaud = BAUD_115200;
3013 lpCommProp->dwProvSubType = PST_RS232;
3014 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
3015 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
3016 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
3017 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
3018 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
3019 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
3020 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
3021 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
3022 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
3023 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
3024 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
3026 return TRUE;
3029 /***********************************************************************
3030 * FIXME:
3031 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
3032 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
3033 * This is dependent on the type of COMM port, but since it is doubtful
3034 * anybody will get around to implementing support for fancy serial
3035 * ports in WINE, this is hardcoded for the time being. The name of
3036 * this DLL should be stored in and read from the system registry in
3037 * the hive HKEY_LOCAL_MACHINE, key
3038 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
3039 * where ???? is the port number... that is determined by PNP
3040 * The DLL should be loaded when the COMM port is opened, and closed
3041 * when the COMM port is closed. - MJM 20 June 2000
3042 ***********************************************************************/
3043 static CHAR lpszSerialUI[] = "serialui.dll";
3046 /***********************************************************************
3047 * CommConfigDialogA (KERNEL32.140)
3049 * Raises a dialog that allows the user to configure a comm port.
3050 * Fills the COMMCONFIG struct with information specified by the user.
3051 * This function should call a similar routine in the COMM driver...
3053 * RETURNS
3055 * TRUE on success, FALSE on failure
3056 * If successful, the lpCommConfig structure will contain a new
3057 * configuration for the comm port, as specified by the user.
3059 * BUGS
3060 * The library with the CommConfigDialog code is never unloaded.
3061 * Perhaps this should be done when the comm port is closed?
3063 BOOL WINAPI CommConfigDialogA(
3064 LPCSTR lpszDevice, /* [in] name of communications device */
3065 HANDLE hWnd, /* [in] parent window for the dialog */
3066 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
3068 FARPROC lpfnCommDialog;
3069 HMODULE hConfigModule;
3070 BOOL r;
3072 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
3074 hConfigModule = LoadLibraryA(lpszSerialUI);
3075 if(!hConfigModule)
3076 return FALSE;
3078 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
3080 if(!lpfnCommDialog)
3081 return FALSE;
3083 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
3085 /* UnloadLibrary(hConfigModule); */
3087 return r;
3090 /***********************************************************************
3091 * CommConfigDialogW (KERNEL32.141)
3093 * see CommConfigDialogA for more info
3095 BOOL WINAPI CommConfigDialogW(
3096 LPCWSTR lpszDevice, /* [in] name of communications device */
3097 HANDLE hWnd, /* [in] parent window for the dialog */
3098 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
3100 BOOL r;
3101 LPSTR lpDeviceA;
3103 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
3104 if(lpDeviceA)
3105 return FALSE;
3106 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
3107 HeapFree( GetProcessHeap(), 0, lpDeviceA );
3108 return r;
3111 /***********************************************************************
3112 * GetCommConfig (KERNEL32.283)
3114 * Fill in the COMMCONFIG structure for the comm port hFile
3116 * RETURNS
3118 * TRUE on success, FALSE on failure
3119 * If successful, lpCommConfig contains the comm port configuration.
3121 * BUGS
3123 * The signature is missing a the parameter for the size of the COMMCONFIG
3124 * structure/buffer it should be
3125 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
3127 BOOL WINAPI GetCommConfig(
3128 HANDLE hFile, /* [in] The communications device. */
3129 LPCOMMCONFIG lpCommConfig) /* [out] The communications configuration of the device (if it fits). */
3130 #if 0 /* FIXME: Why is this "commented" out? */
3131 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
3132 afterwards the number of bytes copied to the buffer or
3133 the needed size of the buffer. */
3134 #endif
3136 BOOL r;
3138 TRACE("(%x %p)\n",hFile,lpCommConfig);
3140 if(lpCommConfig == NULL)
3141 return FALSE;
3143 lpCommConfig->dwSize = sizeof(COMMCONFIG);
3144 lpCommConfig->wVersion = 1;
3145 lpCommConfig->wReserved = 0;
3146 r = GetCommState(hFile,&lpCommConfig->dcb);
3147 lpCommConfig->dwProviderSubType = PST_RS232;
3148 lpCommConfig->dwProviderOffset = 0;
3149 lpCommConfig->dwProviderSize = 0;
3151 return r;
3154 /***********************************************************************
3155 * SetCommConfig (KERNEL32.617)
3157 * Sets the configuration of the commications device.
3159 * RETURNS
3161 * True on success, false if the handle was bad is not a communications device.
3163 BOOL WINAPI SetCommConfig(
3164 HANDLE hFile, /* [in] The communications device. */
3165 LPCOMMCONFIG lpCommConfig) /* [in] The desired configuration. */
3167 TRACE("(%x %p)\n",hFile,lpCommConfig);
3168 return SetCommState(hFile,&lpCommConfig->dcb);
3171 /***********************************************************************
3172 * SetDefaultCommConfigA (KERNEL32.638)
3174 * Initializes the default configuration for the specified communication
3175 * device. (ascii)
3177 * RETURNS
3179 * True if the device was found and the defaults set, false otherwise
3181 BOOL WINAPI SetDefaultCommConfigA(
3182 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
3183 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
3184 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
3186 FARPROC lpfnSetDefaultCommConfig;
3187 HMODULE hConfigModule;
3188 BOOL r;
3190 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
3192 hConfigModule = LoadLibraryA(lpszSerialUI);
3193 if(!hConfigModule)
3194 return FALSE;
3196 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
3198 if(! lpfnSetDefaultCommConfig)
3199 return TRUE;
3201 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
3203 /* UnloadLibrary(hConfigModule); */
3205 return r;
3209 /***********************************************************************
3210 * SetDefaultCommConfigW (KERNEL32.639)
3212 * Initializes the default configuration for the specified
3213 * communication device. (unicode)
3215 * RETURNS
3218 BOOL WINAPI SetDefaultCommConfigW(
3219 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
3220 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
3221 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
3223 BOOL r;
3224 LPSTR lpDeviceA;
3226 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
3228 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
3229 if(lpDeviceA)
3230 return FALSE;
3231 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
3232 HeapFree( GetProcessHeap(), 0, lpDeviceA );
3233 return r;
3237 /***********************************************************************
3238 * GetDefaultCommConfigA (KERNEL32.313)
3240 * Acquires the default configuration of the specified communication device. (unicode)
3242 * RETURNS
3244 * True on successful reading of the default configuration,
3245 * if the device is not found or the buffer is too small.
3247 BOOL WINAPI GetDefaultCommConfigA(
3248 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
3249 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
3250 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
3251 afterwards the number of bytes copied to the buffer or
3252 the needed size of the buffer. */
3254 LPDCB lpdcb = &(lpCC->dcb);
3255 char temp[40];
3257 if (strncasecmp(lpszName,"COM",3)) {
3258 ERR("not implemented for <%s>\n", lpszName);
3259 return FALSE;
3262 if (!ValidCOMPort(lpszName[3]-'1'))
3263 return FALSE;
3265 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
3266 if (*lpdwSize < sizeof(COMMCONFIG)) {
3267 *lpdwSize = sizeof(COMMCONFIG);
3268 return FALSE;
3271 *lpdwSize = sizeof(COMMCONFIG);
3273 lpCC->dwSize = sizeof(COMMCONFIG);
3274 lpCC->wVersion = 1;
3275 lpCC->dwProviderSubType = PST_RS232;
3276 lpCC->dwProviderOffset = 0L;
3277 lpCC->dwProviderSize = 0L;
3279 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
3280 FIXME("setting %s as default\n", temp);
3282 return BuildCommDCBA( temp, lpdcb);
3285 /**************************************************************************
3286 * GetDefaultCommConfigW (KERNEL32.314)
3288 * Acquires the default configuration of the specified communication device. (unicode)
3290 * RETURNS
3292 * True on successful reading of the default configuration,
3293 * if the device is not found or the buffer is too small.
3295 BOOL WINAPI GetDefaultCommConfigW(
3296 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
3297 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
3298 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
3299 afterwards the number of bytes copied to the buffer or
3300 the needed size of the buffer. */
3302 BOOL ret = FALSE;
3303 LPSTR lpszNameA;
3305 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
3306 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
3307 if (lpszNameA)
3309 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
3310 HeapFree( GetProcessHeap(), 0, lpszNameA );
3312 return ret;