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.
48 #ifdef HAVE_SYS_FILIO_H
49 # include <sys/filio.h>
51 #include <sys/ioctl.h>
55 #ifdef HAVE_SYS_MODEM_H
56 # include <sys/modem.h>
58 #ifdef HAVE_SYS_STRTIO_H
59 # include <sys/strtio.h>
63 #include "wine/port.h"
70 #include "debugtools.h"
72 DEFAULT_DEBUG_CHANNEL(comm);
74 #if !defined(TIOCINQ) && defined(FIONREAD)
75 #define TIOCINQ FIONREAD
78 /* window's semi documented modem status register */
79 #define COMM_MSR_OFFSET 35
84 #define MSR_MASK (MSR_CTS|MSR_DSR|MSR_RI|MSR_RLSD)
89 #define CMSPAR 0x40000000 /* stick parity */
94 struct DosDeviceStruct {
95 char *devicename; /* /dev/ttyS0 */
102 int commerror, eventmask;
105 unsigned ibuf_size,ibuf_head,ibuf_tail;
106 unsigned obuf_size,obuf_head,obuf_tail;
108 int wnd, n_read, n_write;
109 HANDLE s_read, s_write;
113 static struct DosDeviceStruct COM[MAX_PORTS];
114 static struct DosDeviceStruct LPT[MAX_PORTS];
115 /* pointers to unknown(==undocumented) comm structure */
116 static LPCVOID *unknown[MAX_PORTS];
117 /* save terminal states */
118 static struct termios m_stat[MAX_PORTS];
120 /* update window's semi documented modem status register */
121 /* see knowledge base Q101417 */
122 static void COMM_MSRUpdate( UCHAR * pMsr, unsigned int mstat)
126 if(mstat & TIOCM_CTS) tmpmsr |= MSR_CTS;
129 if(mstat & TIOCM_DSR) tmpmsr |= MSR_DSR;
132 if(mstat & TIOCM_RI) tmpmsr |= MSR_RI;
135 if(mstat & TIOCM_CAR) tmpmsr |= MSR_RLSD;
137 *pMsr = (*pMsr & ~MSR_MASK) | tmpmsr;
143 char option[10], temp[256], *btemp;
146 for (x=0; x!=MAX_PORTS; x++) {
147 strcpy(option,"COMx");
151 PROFILE_GetWineIniString( "serialports", option, "*",
152 temp, sizeof(temp) );
153 if (!strcmp(temp, "*") || *temp == '\0')
154 COM[x].devicename = NULL;
156 btemp = strchr(temp,',');
159 COM[x].baudrate = atoi(btemp);
161 COM[x].baudrate = -1;
164 if (!S_ISCHR(st.st_mode))
165 WARN("Can't use `%s' as %s !\n", temp, option);
167 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
168 WARN("Can't malloc for device info!\n");
171 strcpy(COM[x].devicename, temp);
173 TRACE("%s = %s\n", option, COM[x].devicename);
176 strcpy(option, "LPTx");
180 PROFILE_GetWineIniString( "parallelports", option, "*",
181 temp, sizeof(temp) );
182 if (!strcmp(temp, "*") || *temp == '\0')
183 LPT[x].devicename = NULL;
186 if (!S_ISCHR(st.st_mode))
187 WARN("Can't use `%s' as %s !\n", temp, option);
189 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
190 WARN("Can't malloc for device info!\n");
193 strcpy(LPT[x].devicename, temp);
195 TRACE("%s = %s\n", option, LPT[x].devicename);
202 static struct DosDeviceStruct *GetDeviceStruct(int fd)
204 if ((fd&0x7F)<=MAX_PORTS) {
205 if (!(fd&FLAG_LPT)) {
218 static int GetCommPort_fd(int fd)
222 for (x=0; x<MAX_PORTS; x++) {
230 static int ValidCOMPort(int x)
232 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
235 static int ValidLPTPort(int x)
237 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
240 static int WinError(void)
242 TRACE("errno = %d\n", errno);
249 static unsigned comm_inbuf(struct DosDeviceStruct *ptr)
251 return ((ptr->ibuf_tail > ptr->ibuf_head) ? ptr->ibuf_size : 0)
252 + ptr->ibuf_head - ptr->ibuf_tail;
255 static unsigned comm_outbuf(struct DosDeviceStruct *ptr)
257 return ((ptr->obuf_tail > ptr->obuf_head) ? ptr->obuf_size : 0)
258 + ptr->obuf_head - ptr->obuf_tail;
261 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
263 unsigned int mstat, okay;
264 okay = ioctl(fd, TIOCMGET, &mstat);
265 if (okay) return okay;
266 if (andy) mstat &= andy;
268 return ioctl(fd, TIOCMSET, &mstat);
271 static void CALLBACK comm_notification( ULONG_PTR private )
273 struct DosDeviceStruct *ptr = (struct DosDeviceStruct *)private;
274 int prev, bleft, len;
276 int cid = GetCommPort_fd(ptr->fd);
278 TRACE("async notification\n");
279 /* read data from comm port */
280 prev = comm_inbuf(ptr);
282 bleft = ((ptr->ibuf_tail > ptr->ibuf_head) ? (ptr->ibuf_tail-1) : ptr->ibuf_size)
284 len = read(ptr->fd, ptr->inbuf + ptr->ibuf_head, bleft?bleft:1);
287 ptr->commerror = CE_RXOVER;
289 /* check for events */
290 if ((ptr->eventmask & EV_RXFLAG) &&
291 memchr(ptr->inbuf + ptr->ibuf_head, ptr->evtchar, len)) {
292 *(WORD*)(unknown[cid]) |= EV_RXFLAG;
295 if (ptr->eventmask & EV_RXCHAR) {
296 *(WORD*)(unknown[cid]) |= EV_RXCHAR;
299 /* advance buffer position */
300 ptr->ibuf_head += len;
301 if (ptr->ibuf_head >= ptr->ibuf_size)
306 /* check for notification */
307 if (ptr->wnd && (ptr->n_read>0) && (prev<ptr->n_read) &&
308 (comm_inbuf(ptr)>=ptr->n_read)) {
309 /* passed the receive notification threshold */
313 /* write any TransmitCommChar character */
315 len = write(ptr->fd, &(ptr->xmit), 1);
316 if (len > 0) ptr->xmit = -1;
318 /* write from output queue */
319 prev = comm_outbuf(ptr);
321 bleft = ((ptr->obuf_tail <= ptr->obuf_head) ? ptr->obuf_head : ptr->obuf_size)
323 len = bleft ? write(ptr->fd, ptr->outbuf + ptr->obuf_tail, bleft) : 0;
325 ptr->obuf_tail += len;
326 if (ptr->obuf_tail >= ptr->obuf_size)
329 if (ptr->obuf_tail == ptr->obuf_head) {
331 SERVICE_Delete( ptr->s_write );
332 ptr->s_write = INVALID_HANDLE_VALUE;
334 if (ptr->eventmask & EV_TXEMPTY) {
335 *(WORD*)(unknown[cid]) |= EV_TXEMPTY;
341 /* check for notification */
342 if (ptr->wnd && (ptr->n_write>0) && (prev>=ptr->n_write) &&
343 (comm_outbuf(ptr)<ptr->n_write)) {
344 /* passed the transmit notification threshold */
348 /* send notifications, if any */
349 if (ptr->wnd && mask) {
350 TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask);
351 if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask);
355 static void comm_waitread(struct DosDeviceStruct *ptr)
357 if (ptr->s_read != INVALID_HANDLE_VALUE) return;
358 ptr->s_read = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
359 GENERIC_READ | SYNCHRONIZE ),
364 static void comm_waitwrite(struct DosDeviceStruct *ptr)
366 if (ptr->s_write != INVALID_HANDLE_VALUE) return;
367 ptr->s_write = SERVICE_AddObject( FILE_DupUnixHandle( ptr->fd,
368 GENERIC_WRITE | SYNCHRONIZE ),
373 /**************************************************************************
374 * BuildCommDCB16 (USER.213)
376 * According to the ECMA-234 (368.3) the function will return FALSE on
377 * success, otherwise it will return -1.
378 * IF THIS IS NOT CORRECT THE RETURNVALUE CHECK IN BuildCommDCBAndTimeoutsA
381 BOOL16 WINAPI BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
383 /* "COM1:96,n,8,1" */
386 char *ptr, temp[256];
388 TRACE("(%s), ptr %p\n", device, lpdcb);
390 if (!strncasecmp(device,"COM",3)) {
391 port = device[3] - '0';
395 ERR("BUG ! COM0 can't exist!\n");
399 if (!ValidCOMPort(port)) {
400 FIXME("invalid COM port %d?\n",port);
404 memset(lpdcb, 0, sizeof(DCB16)); /* initialize */
411 if (*(device+4) != ':')
414 strcpy(temp,device+5);
415 ptr = strtok(temp, ", ");
417 if (COM[port].baudrate > 0)
418 lpdcb->BaudRate = COM[port].baudrate;
422 /* DOS/Windows only compares the first two numbers
423 * and assigns an appropriate baud rate.
424 * You can supply 961324245, it still returns 9600 ! */
427 WARN("Unknown baudrate string '%s' !\n", ptr);
428 return -1; /* error: less than 2 chars */
449 WARN("Unknown baudrate indicator %d !\n", rate);
453 lpdcb->BaudRate = rate;
455 TRACE("baudrate (%d)\n", lpdcb->BaudRate);
457 ptr = strtok(NULL, ", ");
459 *ptr = toupper(*ptr);
461 TRACE("parity (%c)\n", *ptr);
462 lpdcb->fParity = TRUE;
465 lpdcb->Parity = NOPARITY;
466 lpdcb->fParity = FALSE;
469 lpdcb->Parity = EVENPARITY;
472 lpdcb->Parity = MARKPARITY;
475 lpdcb->Parity = ODDPARITY;
478 WARN("Unknown parity `%c'!\n", *ptr);
482 ptr = strtok(NULL, ", ");
483 TRACE("charsize (%c)\n", *ptr);
484 lpdcb->ByteSize = *ptr - '0';
486 ptr = strtok(NULL, ", ");
487 TRACE("stopbits (%c)\n", *ptr);
490 lpdcb->StopBits = ONESTOPBIT;
493 lpdcb->StopBits = TWOSTOPBITS;
496 WARN("Unknown # of stopbits `%c'!\n", *ptr);
504 /*****************************************************************************
505 * OpenComm16 (USER.200)
507 INT16 WINAPI OpenComm16(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
511 TRACE("%s, %d, %d\n", device, cbInQueue, cbOutQueue);
513 if (strlen(device) < 4)
516 port = device[3] - '0';
519 ERR("BUG ! COM0 or LPT0 don't exist !\n");
521 if (!strncasecmp(device,"COM",3)) {
523 TRACE("%s = %s\n", device, COM[port].devicename);
525 if (!ValidCOMPort(port))
531 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
533 ERR("Couldn't open %s ! (%s)\n", COM[port].devicename, strerror(errno));
536 unknown[port] = SEGPTR_ALLOC(40);
537 bzero(unknown[port],40);
539 COM[port].commerror = 0;
540 COM[port].eventmask = 0;
541 COM[port].evtchar = 0; /* FIXME: default? */
542 /* save terminal state */
543 tcgetattr(fd,&m_stat[port]);
544 /* set default parameters */
545 if(COM[port].baudrate>-1){
547 GetCommState16(port, &dcb);
548 dcb.BaudRate=COM[port].baudrate;
550 * databits, parity, stopbits
552 SetCommState16( &dcb);
554 /* init priority characters */
555 COM[port].unget = -1;
557 /* allocate buffers */
558 COM[port].ibuf_size = cbInQueue;
559 COM[port].ibuf_head = COM[port].ibuf_tail = 0;
560 COM[port].obuf_size = cbOutQueue;
561 COM[port].obuf_head = COM[port].obuf_tail = 0;
563 COM[port].inbuf = malloc(cbInQueue);
564 if (COM[port].inbuf) {
565 COM[port].outbuf = malloc(cbOutQueue);
566 if (!COM[port].outbuf)
567 free(COM[port].inbuf);
568 } else COM[port].outbuf = NULL;
569 if (!COM[port].outbuf) {
570 /* not enough memory */
571 tcsetattr(COM[port].fd,TCSANOW,&m_stat[port]);
573 ERR("out of memory\n");
577 COM[port].s_read = INVALID_HANDLE_VALUE;
578 COM[port].s_write = INVALID_HANDLE_VALUE;
579 comm_waitread( &COM[port] );
584 if (!strncasecmp(device,"LPT",3)) {
586 if (!ValidLPTPort(port))
592 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
597 LPT[port].commerror = 0;
598 LPT[port].eventmask = 0;
599 return port|FLAG_LPT;
605 /*****************************************************************************
606 * CloseComm16 (USER.207)
608 INT16 WINAPI CloseComm16(INT16 cid)
610 struct DosDeviceStruct *ptr;
612 TRACE("cid=%d\n", cid);
613 if ((ptr = GetDeviceStruct(cid)) == NULL) {
614 FIXME("no cid=%d found!\n", cid);
617 if (!(cid&FLAG_LPT)) {
619 SEGPTR_FREE(unknown[cid]); /* [LW] */
621 SERVICE_Delete( COM[cid].s_write );
622 SERVICE_Delete( COM[cid].s_read );
627 /* reset modem lines */
628 tcsetattr(ptr->fd,TCSANOW,&m_stat[cid]);
631 if (close(ptr->fd) == -1) {
632 ptr->commerror = WinError();
633 /* FIXME: should we clear ptr->fd here? */
642 /*****************************************************************************
643 * SetCommBreak16 (USER.210)
645 INT16 WINAPI SetCommBreak16(INT16 cid)
647 struct DosDeviceStruct *ptr;
649 TRACE("cid=%d\n", cid);
650 if ((ptr = GetDeviceStruct(cid)) == NULL) {
651 FIXME("no cid=%d found!\n", cid);
660 /*****************************************************************************
661 * ClearCommBreak16 (USER.211)
663 INT16 WINAPI ClearCommBreak16(INT16 cid)
665 struct DosDeviceStruct *ptr;
667 TRACE("cid=%d\n", cid);
668 if (!(ptr = GetDeviceStruct(cid))) {
669 FIXME("no cid=%d found!\n", cid);
677 /*****************************************************************************
678 * EscapeCommFunction16 (USER.214)
680 LONG WINAPI EscapeCommFunction16(UINT16 cid,UINT16 nFunction)
683 struct DosDeviceStruct *ptr;
686 TRACE("cid=%d, function=%d\n", cid, nFunction);
687 if ((nFunction != GETMAXCOM) && (nFunction != GETMAXLPT)) {
688 if ((ptr = GetDeviceStruct(cid)) == NULL) {
689 FIXME("no cid=%d found!\n", cid);
692 if (tcgetattr(ptr->fd,&port) == -1) {
693 TRACE("tcgetattr failed\n");
694 ptr->commerror=WinError();
705 TRACE("GETMAXCOM\n");
706 for (max = MAX_PORTS;!COM[max].devicename;max--)
712 TRACE("GETMAXLPT\n");
713 for (max = MAX_PORTS;!LPT[max].devicename;max--)
715 return FLAG_LPT + max;
719 TRACE("GETBASEIRQ\n");
720 /* FIXME: use tables */
721 /* just fake something for now */
722 if (cid & FLAG_LPT) {
723 /* LPT1: irq 7, LPT2: irq 5 */
724 return (cid & 0x7f) ? 5 : 7;
726 /* COM1: irq 4, COM2: irq 3,
727 COM3: irq 4, COM4: irq 3 */
728 return 4 - (cid & 1);
735 return COMM_WhackModem(ptr->fd, ~TIOCM_DTR, 0);
740 return COMM_WhackModem(ptr->fd, ~TIOCM_RTS, 0);
746 return COMM_WhackModem(ptr->fd, 0, TIOCM_DTR);
752 return COMM_WhackModem(ptr->fd, 0, TIOCM_RTS);
757 port.c_iflag |= IXOFF;
762 port.c_iflag |= IXON;
766 WARN("(cid=%d,nFunction=%d): Unknown function\n",
771 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
772 ptr->commerror = WinError();
780 /*****************************************************************************
781 * FlushComm16 (USER.215)
783 INT16 WINAPI FlushComm16(INT16 cid,INT16 fnQueue)
786 struct DosDeviceStruct *ptr;
788 TRACE("cid=%d, queue=%d\n", cid, fnQueue);
789 if ((ptr = GetDeviceStruct(cid)) == NULL) {
790 FIXME("no cid=%d found!\n", cid);
796 ptr->obuf_tail = ptr->obuf_head;
800 ptr->ibuf_head = ptr->ibuf_tail;
803 WARN("(cid=%d,fnQueue=%d):Unknown queue\n",
807 if (tcflush(ptr->fd, queue)) {
808 ptr->commerror = WinError();
816 /********************************************************************
817 * GetCommError16 (USER.203)
819 INT16 WINAPI GetCommError16(INT16 cid,LPCOMSTAT16 lpStat)
822 struct DosDeviceStruct *ptr;
826 if ((ptr = GetDeviceStruct(cid)) == NULL) {
827 FIXME("no handle for cid = %0x!\n",cid);
831 WARN(" cid %d not comm port\n",cid);
834 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
835 ioctl(ptr->fd,TIOCMGET,&mstat);
836 COMM_MSRUpdate( stol, mstat);
841 lpStat->cbOutQue = comm_outbuf(ptr);
842 lpStat->cbInQue = comm_inbuf(ptr);
844 TRACE("cid %d, error %d, stat %d in %d out %d, stol %x\n",
845 cid, ptr->commerror, lpStat->status, lpStat->cbInQue,
846 lpStat->cbOutQue, *stol);
849 TRACE("cid %d, error %d, lpStat NULL stol %x\n",
850 cid, ptr->commerror, *stol);
852 /* Return any errors and clear it */
853 temperror = ptr->commerror;
858 /*****************************************************************************
859 * SetCommEventMask16 (USER.208)
861 SEGPTR WINAPI SetCommEventMask16(INT16 cid,UINT16 fuEvtMask)
863 struct DosDeviceStruct *ptr;
868 TRACE("cid %d,mask %d\n",cid,fuEvtMask);
869 if ((ptr = GetDeviceStruct(cid)) == NULL) {
870 FIXME("no handle for cid = %0x!\n",cid);
874 ptr->eventmask = fuEvtMask;
876 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
877 WARN(" cid %d not comm port\n",cid);
880 /* it's a COM port ? -> modify flags */
881 stol = (unsigned char *)unknown[cid] + COMM_MSR_OFFSET;
882 repid = ioctl(ptr->fd,TIOCMGET,&mstat);
883 TRACE(" ioctl %d, msr %x at %p %p\n",repid,mstat,stol,unknown[cid]);
884 COMM_MSRUpdate( stol, mstat);
886 TRACE(" modem dcd construct %x\n",*stol);
887 return SEGPTR_GET(unknown[cid]);
890 /*****************************************************************************
891 * GetCommEventMask16 (USER.209)
893 UINT16 WINAPI GetCommEventMask16(INT16 cid,UINT16 fnEvtClear)
895 struct DosDeviceStruct *ptr;
898 TRACE("cid %d, mask %d\n", cid, fnEvtClear);
899 if ((ptr = GetDeviceStruct(cid)) == NULL) {
900 FIXME("no handle for cid = %0x!\n",cid);
904 if ((cid&FLAG_LPT) || !ValidCOMPort(cid)) {
905 WARN(" cid %d not comm port\n",cid);
909 events = *(WORD*)(unknown[cid]) & fnEvtClear;
910 *(WORD*)(unknown[cid]) &= ~fnEvtClear;
914 /*****************************************************************************
915 * SetCommState16 (USER.201)
917 INT16 WINAPI SetCommState16(LPDCB16 lpdcb)
920 struct DosDeviceStruct *ptr;
921 int bytesize, stopbits;
924 TRACE("cid %d, ptr %p\n", lpdcb->Id, lpdcb);
925 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
926 FIXME("no handle for cid = %0x!\n",lpdcb->Id);
929 if (tcgetattr(ptr->fd, &port) == -1) {
930 ptr->commerror = WinError();
935 port.c_cc[VTIME] = 1;
938 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
940 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
942 port.c_iflag |= (IGNBRK);
944 port.c_oflag &= ~(OPOST);
946 port.c_cflag &= ~(HUPCL);
947 port.c_cflag |= CLOCAL | CREAD;
949 port.c_lflag &= ~(ICANON|ECHO|ISIG);
950 port.c_lflag |= NOFLSH;
952 TRACE("baudrate %d\n",lpdcb->BaudRate);
954 port.c_cflag &= ~CBAUD;
955 switch (lpdcb->BaudRate) {
958 port.c_cflag |= B110;
962 port.c_cflag |= B300;
966 port.c_cflag |= B600;
970 port.c_cflag |= B1200;
974 port.c_cflag |= B2400;
978 port.c_cflag |= B4800;
982 port.c_cflag |= B9600;
986 port.c_cflag |= B19200;
990 port.c_cflag |= B38400;
994 port.c_cflag |= B57600;
999 port.c_cflag |= B115200;
1003 ptr->commerror = IE_BAUDRATE;
1006 #elif !defined(__EMX__)
1007 switch (lpdcb->BaudRate) {
1010 port.c_ospeed = B110;
1014 port.c_ospeed = B300;
1018 port.c_ospeed = B600;
1022 port.c_ospeed = B1200;
1026 port.c_ospeed = B2400;
1030 port.c_ospeed = B4800;
1034 port.c_ospeed = B9600;
1038 port.c_ospeed = B19200;
1042 port.c_ospeed = B38400;
1045 ptr->commerror = IE_BAUDRATE;
1048 port.c_ispeed = port.c_ospeed;
1050 bytesize=lpdcb->ByteSize;
1051 stopbits=lpdcb->StopBits;
1053 TRACE("fParity %d Parity %d\n",lpdcb->fParity, lpdcb->Parity);
1055 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1057 port.c_cflag &= ~(PARENB | PARODD);
1060 port.c_iflag |= INPCK;
1062 port.c_iflag &= ~INPCK;
1063 switch (lpdcb->Parity) {
1067 port.c_cflag |= (PARENB | PARODD);
1070 port.c_cflag |= PARENB;
1073 /* Linux defines mark/space (stick) parity */
1075 port.c_cflag |= (PARENB | CMSPAR);
1078 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1081 /* try the POSIX way */
1083 if( stopbits == ONESTOPBIT) {
1084 stopbits = TWOSTOPBITS;
1085 port.c_iflag &= ~INPCK;
1087 ptr->commerror = IE_BYTESIZE;
1094 port.c_iflag &= ~INPCK;
1096 ptr->commerror = IE_BYTESIZE;
1102 ptr->commerror = IE_BYTESIZE;
1106 TRACE("bytesize %d\n",bytesize);
1107 port.c_cflag &= ~CSIZE;
1110 port.c_cflag |= CS5;
1113 port.c_cflag |= CS6;
1116 port.c_cflag |= CS7;
1119 port.c_cflag |= CS8;
1122 ptr->commerror = IE_BYTESIZE;
1126 TRACE("stopbits %d\n",stopbits);
1130 port.c_cflag &= ~CSTOPB;
1132 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1134 port.c_cflag |= CSTOPB;
1137 ptr->commerror = IE_BYTESIZE;
1142 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
1143 port.c_cflag |= CRTSCTS;
1145 if (lpdcb->fDtrDisable)
1146 port.c_cflag &= ~CRTSCTS;
1149 port.c_iflag |= IXON;
1151 port.c_iflag &= ~IXON;
1153 port.c_iflag |= IXOFF;
1155 port.c_iflag &= ~IXOFF;
1157 ptr->evtchar = lpdcb->EvtChar;
1162 if (tcsetattr(ptr->fd, TCSADRAIN, &port) == -1) {
1163 ptr->commerror = WinError();
1171 /*****************************************************************************
1172 * GetCommState16 (USER.202)
1174 INT16 WINAPI GetCommState16(INT16 cid, LPDCB16 lpdcb)
1177 struct DosDeviceStruct *ptr;
1178 struct termios port;
1180 TRACE("cid %d, ptr %p\n", cid, lpdcb);
1181 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1182 FIXME("no handle for cid = %0x!\n",cid);
1185 if (tcgetattr(ptr->fd, &port) == -1) {
1186 ptr->commerror = WinError();
1192 speed = port.c_cflag & CBAUD;
1194 speed = port.c_ospeed;
1198 lpdcb->BaudRate = 110;
1201 lpdcb->BaudRate = 300;
1204 lpdcb->BaudRate = 600;
1207 lpdcb->BaudRate = 1200;
1210 lpdcb->BaudRate = 2400;
1213 lpdcb->BaudRate = 4800;
1216 lpdcb->BaudRate = 9600;
1219 lpdcb->BaudRate = 19200;
1222 lpdcb->BaudRate = 38400;
1226 lpdcb->BaudRate = 57600;
1231 lpdcb->BaudRate = 57601;
1236 switch (port.c_cflag & CSIZE) {
1238 lpdcb->ByteSize = 5;
1241 lpdcb->ByteSize = 6;
1244 lpdcb->ByteSize = 7;
1247 lpdcb->ByteSize = 8;
1251 if(port.c_iflag & INPCK)
1252 lpdcb->fParity = TRUE;
1254 lpdcb->fParity = FALSE;
1256 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1258 switch (port.c_cflag & (PARENB | PARODD))
1262 lpdcb->Parity = NOPARITY;
1265 lpdcb->Parity = EVENPARITY;
1267 case (PARENB | PARODD):
1268 lpdcb->Parity = ODDPARITY;
1271 case (PARENB | CMSPAR):
1272 lpdcb->Parity = MARKPARITY;
1274 case (PARENB | PARODD | CMSPAR):
1275 lpdcb->Parity = SPACEPARITY;
1280 if (port.c_cflag & CSTOPB)
1281 if(lpdcb->ByteSize == 5)
1282 lpdcb->StopBits = ONE5STOPBITS;
1284 lpdcb->StopBits = TWOSTOPBITS;
1286 lpdcb->StopBits = ONESTOPBIT;
1288 lpdcb->RlsTimeout = 50;
1289 lpdcb->CtsTimeout = 50;
1290 lpdcb->DsrTimeout = 50;
1294 lpdcb->fDtrDisable = 0;
1298 if (port.c_cflag & CRTSCTS) {
1299 lpdcb->fDtrflow = 1;
1300 lpdcb->fRtsflow = 1;
1301 lpdcb->fOutxCtsFlow = 1;
1302 lpdcb->fOutxDsrFlow = 1;
1305 lpdcb->fDtrDisable = 1;
1307 if (port.c_iflag & IXON)
1312 if (port.c_iflag & IXOFF)
1321 lpdcb->XoffLim = 10;
1323 lpdcb->EvtChar = ptr->evtchar;
1329 /*****************************************************************************
1330 * TransmitCommChar16 (USER.206)
1332 INT16 WINAPI TransmitCommChar16(INT16 cid,CHAR chTransmit)
1334 struct DosDeviceStruct *ptr;
1336 TRACE("cid %d, data %d \n", cid, chTransmit);
1337 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1338 FIXME("no handle for cid = %0x!\n",cid);
1342 if (ptr->suspended) {
1343 ptr->commerror = IE_HARDWARE;
1347 if (ptr->xmit >= 0) {
1348 /* character already queued */
1349 /* FIXME: which error would Windows return? */
1350 ptr->commerror = CE_TXFULL;
1354 if (ptr->obuf_head == ptr->obuf_tail) {
1355 /* transmit queue empty, try to transmit directly */
1356 if (write(ptr->fd, &chTransmit, 1) == -1) {
1357 /* didn't work, queue it */
1358 ptr->xmit = chTransmit;
1359 comm_waitwrite(ptr);
1362 /* data in queue, let this char be transmitted next */
1363 ptr->xmit = chTransmit;
1364 comm_waitwrite(ptr);
1371 /*****************************************************************************
1372 * UngetCommChar16 (USER.212)
1374 INT16 WINAPI UngetCommChar16(INT16 cid,CHAR chUnget)
1376 struct DosDeviceStruct *ptr;
1378 TRACE("cid %d (char %d)\n", cid, chUnget);
1379 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1380 FIXME("no handle for cid = %0x!\n",cid);
1384 if (ptr->suspended) {
1385 ptr->commerror = IE_HARDWARE;
1389 if (ptr->unget>=0) {
1390 /* character already queued */
1391 /* FIXME: which error would Windows return? */
1392 ptr->commerror = CE_RXOVER;
1396 ptr->unget = chUnget;
1402 /*****************************************************************************
1403 * ReadComm16 (USER.204)
1405 INT16 WINAPI ReadComm16(INT16 cid,LPSTR lpvBuf,INT16 cbRead)
1408 struct DosDeviceStruct *ptr;
1409 LPSTR orgBuf = lpvBuf;
1411 TRACE("cid %d, ptr %p, length %d\n", cid, lpvBuf, cbRead);
1412 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1413 FIXME("no handle for cid = %0x!\n",cid);
1417 if (ptr->suspended) {
1418 ptr->commerror = IE_HARDWARE;
1422 /* read unget character */
1423 if (ptr->unget>=0) {
1424 *lpvBuf++ = ptr->unget;
1431 /* read from receive buffer */
1432 while (length < cbRead) {
1433 status = ((ptr->ibuf_head < ptr->ibuf_tail) ?
1434 ptr->ibuf_size : ptr->ibuf_head) - ptr->ibuf_tail;
1436 if ((cbRead - length) < status)
1437 status = cbRead - length;
1439 memcpy(lpvBuf, ptr->inbuf + ptr->ibuf_tail, status);
1440 ptr->ibuf_tail += status;
1441 if (ptr->ibuf_tail >= ptr->ibuf_size)
1447 TRACE("%.*s\n", length, orgBuf);
1452 /*****************************************************************************
1453 * WriteComm16 (USER.205)
1455 INT16 WINAPI WriteComm16(INT16 cid, LPSTR lpvBuf, INT16 cbWrite)
1458 struct DosDeviceStruct *ptr;
1460 TRACE("cid %d, ptr %p, length %d\n",
1461 cid, lpvBuf, cbWrite);
1462 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1463 FIXME("no handle for cid = %0x!\n",cid);
1467 if (ptr->suspended) {
1468 ptr->commerror = IE_HARDWARE;
1472 TRACE("%.*s\n", cbWrite, lpvBuf );
1475 while (length < cbWrite) {
1476 if ((ptr->obuf_head == ptr->obuf_tail) && (ptr->xmit < 0)) {
1477 /* no data queued, try to write directly */
1478 status = write(ptr->fd, lpvBuf, cbWrite - length);
1485 /* can't write directly, put into transmit buffer */
1486 status = ((ptr->obuf_tail > ptr->obuf_head) ?
1487 (ptr->obuf_tail-1) : ptr->obuf_size) - ptr->obuf_head;
1489 if ((cbWrite - length) < status)
1490 status = cbWrite - length;
1491 memcpy(lpvBuf, ptr->outbuf + ptr->obuf_head, status);
1492 ptr->obuf_head += status;
1493 if (ptr->obuf_head >= ptr->obuf_size)
1497 comm_waitwrite(ptr);
1504 /***********************************************************************
1505 * EnableCommNotification (USER.245)
1507 BOOL16 WINAPI EnableCommNotification16( INT16 cid, HWND16 hwnd,
1508 INT16 cbWriteNotify, INT16 cbOutQueue )
1510 struct DosDeviceStruct *ptr;
1512 TRACE("(%d, %x, %d, %d)\n", cid, hwnd, cbWriteNotify, cbOutQueue);
1513 if ((ptr = GetDeviceStruct(cid)) == NULL) {
1514 FIXME("no handle for cid = %0x!\n",cid);
1518 ptr->n_read = cbWriteNotify;
1519 ptr->n_write = cbOutQueue;
1524 /**************************************************************************
1525 * BuildCommDCBA (KERNEL32.113)
1527 * Updates a device control block data structure with values from an
1528 * ascii device control string. The device control string has two forms
1529 * normal and extended, it must be exclusively in one or the other form.
1533 * True on success, false on an malformed control string.
1535 BOOL WINAPI BuildCommDCBA(
1536 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
1537 LPDCB lpdcb) /* [out] The device control block to be updated. */
1539 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
1542 /**************************************************************************
1543 * BuildCommDCBAndTimeoutsA (KERNEL32.114)
1545 * Updates a device control block data structure with values from an
1546 * ascii device control string. Taking time out values from a time outs
1547 * struct if desired by the control string.
1551 * True on success, false bad handles etc
1553 BOOL WINAPI BuildCommDCBAndTimeoutsA(
1554 LPCSTR device, /* [in] The ascii device control string. */
1555 LPDCB lpdcb, /* [out] The device control block to be updated. */
1556 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
1561 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
1563 if (!strncasecmp(device,"COM",3)) {
1566 ERR("BUG! COM0 can't exist!\n");
1569 if (!ValidCOMPort(port))
1571 if (*(device+4)!=':')
1573 temp=(LPSTR)(device+5);
1577 lpdcb->DCBlength = sizeof(DCB);
1578 if (strchr(temp,',')) { /* old style */
1581 char last=temp[strlen(temp)-1];
1583 ret=BuildCommDCB16(device,&dcb16);
1586 lpdcb->BaudRate = dcb16.BaudRate;
1587 lpdcb->ByteSize = dcb16.ByteSize;
1588 lpdcb->fBinary = dcb16.fBinary;
1589 lpdcb->Parity = dcb16.Parity;
1590 lpdcb->fParity = dcb16.fParity;
1591 lpdcb->fNull = dcb16.fNull;
1592 lpdcb->StopBits = dcb16.StopBits;
1595 lpdcb->fOutX = TRUE;
1596 lpdcb->fOutxCtsFlow = FALSE;
1597 lpdcb->fOutxDsrFlow = FALSE;
1598 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1599 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1600 } else if (last=='p') {
1601 lpdcb->fInX = FALSE;
1602 lpdcb->fOutX = FALSE;
1603 lpdcb->fOutxCtsFlow = TRUE;
1604 lpdcb->fOutxDsrFlow = TRUE;
1605 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
1606 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1608 lpdcb->fInX = FALSE;
1609 lpdcb->fOutX = FALSE;
1610 lpdcb->fOutxCtsFlow = FALSE;
1611 lpdcb->fOutxDsrFlow = FALSE;
1612 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1613 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1615 lpdcb->XonChar = dcb16.XonChar;
1616 lpdcb->XoffChar = dcb16.XoffChar;
1617 lpdcb->ErrorChar= dcb16.PeChar;
1618 lpdcb->fErrorChar= dcb16.fPeChar;
1619 lpdcb->EofChar = dcb16.EofChar;
1620 lpdcb->EvtChar = dcb16.EvtChar;
1621 lpdcb->XonLim = dcb16.XonLim;
1622 lpdcb->XoffLim = dcb16.XoffLim;
1625 ptr=strtok(temp," ");
1630 if (!strncmp("baud=",ptr,5)) {
1631 if (!sscanf(ptr+5,"%ld",&x))
1632 WARN("Couldn't parse %s\n",ptr);
1633 lpdcb->BaudRate = x;
1636 if (!strncmp("stop=",ptr,5)) {
1637 if (!sscanf(ptr+5,"%ld",&x))
1638 WARN("Couldn't parse %s\n",ptr);
1639 lpdcb->StopBits = x;
1642 if (!strncmp("data=",ptr,5)) {
1643 if (!sscanf(ptr+5,"%ld",&x))
1644 WARN("Couldn't parse %s\n",ptr);
1645 lpdcb->ByteSize = x;
1648 if (!strncmp("parity=",ptr,7)) {
1649 lpdcb->fParity = TRUE;
1652 lpdcb->fParity = FALSE;
1653 lpdcb->Parity = NOPARITY;
1656 lpdcb->Parity = EVENPARITY;
1659 lpdcb->Parity = ODDPARITY;
1662 lpdcb->Parity = MARKPARITY;
1668 ERR("Unhandled specifier '%s', please report.\n",ptr);
1669 ptr=strtok(NULL," ");
1671 if (lpdcb->BaudRate==110)
1672 lpdcb->StopBits = 2;
1676 /**************************************************************************
1677 * BuildCommDCBAndTimeoutsW (KERNEL32.115)
1679 * Updates a device control block data structure with values from an
1680 * unicode device control string. Taking time out values from a time outs
1681 * struct if desired by the control string.
1685 * True on success, false bad handles etc.
1687 BOOL WINAPI BuildCommDCBAndTimeoutsW(
1688 LPCWSTR devid, /* [in] The unicode device control string. */
1689 LPDCB lpdcb, /* [out] The device control block to be updated. */
1690 LPCOMMTIMEOUTS lptimeouts) /* [in] The time outs to use if asked to set them by the control string. */
1695 TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
1696 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
1699 ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
1700 HeapFree( GetProcessHeap(), 0, devidA );
1705 /**************************************************************************
1706 * BuildCommDCBW (KERNEL32.116)
1708 * Updates a device control block structure with values from an
1709 * unicode device control string. The device control string has two forms
1710 * normal and extended, it must be exclusively in one or the other form.
1714 * True on success, false on an malformed control string.
1716 BOOL WINAPI BuildCommDCBW(
1717 LPCWSTR devid, /* [in] The unicode device control string. */
1718 LPDCB lpdcb) /* [out] The device control block to be updated. */
1720 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
1723 /* FIXME: having these global for win32 for now */
1726 /*****************************************************************************
1727 * SetCommBreak (KERNEL32.616)
1729 * Halts the transmission of characters to a communications device.
1733 * True on success, and false if the communications device could not be found,
1734 * the control is not supported.
1738 * Only TIOCSBRK and TIOCCBRK are supported.
1740 BOOL WINAPI SetCommBreak(
1741 HANDLE handle) /* [in] The communictions device to suspend. */
1743 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1746 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1748 TRACE("FILE_GetUnixHandle failed\n");
1751 result = ioctl(fd,TIOCSBRK,0);
1755 TRACE("ioctl failed\n");
1756 SetLastError(ERROR_NOT_SUPPORTED);
1761 FIXME("ioctl not available\n");
1762 SetLastError(ERROR_NOT_SUPPORTED);
1767 /*****************************************************************************
1768 * ClearCommBreak (KERNEL32.135)
1770 * Resumes character transmission from a communication device.
1774 * True on success and false if the communications device could not be found.
1778 * Only TIOCSBRK and TIOCCBRK are supported.
1780 BOOL WINAPI ClearCommBreak(
1781 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
1783 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
1786 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1788 TRACE("FILE_GetUnixHandle failed\n");
1791 result = ioctl(fd,TIOCCBRK,0);
1795 TRACE("ioctl failed\n");
1796 SetLastError(ERROR_NOT_SUPPORTED);
1801 FIXME("ioctl not available\n");
1802 SetLastError(ERROR_NOT_SUPPORTED);
1807 /*****************************************************************************
1808 * EscapeCommFunction (KERNEL32.213)
1810 * Directs a communication device to perform an extended function.
1814 * True or requested data on successful completion of the command,
1815 * false if the device is not present cannot execute the command
1816 * or the command failed.
1818 BOOL WINAPI EscapeCommFunction(
1819 HANDLE handle, /* [in] The communication device to perform the extended function. */
1820 UINT nFunction) /* [in] The extended function to be performed. */
1822 int fd,direct=FALSE,result=FALSE;
1823 struct termios port;
1825 TRACE("handle %d, function=%d\n", handle, nFunction);
1826 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1828 FIXME("handle %d not found.\n",handle);
1832 if (tcgetattr(fd,&port) == -1) {
1833 commerror=WinError();
1838 switch (nFunction) {
1847 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
1855 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
1863 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
1871 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
1877 port.c_iflag |= IXOFF;
1882 port.c_iflag |= IXON;
1885 TRACE("setbreak\n");
1888 result = ioctl(fd,TIOCSBRK,0);
1892 TRACE("clrbreak\n");
1895 result = ioctl(fd,TIOCCBRK,0);
1899 WARN("(handle=%d,nFunction=%d): Unknown function\n",
1905 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
1906 commerror = WinError();
1916 commerror=WinError();
1925 /********************************************************************
1926 * PurgeComm (KERNEL32.558)
1928 * Terminates pending operations and/or discards buffers on a
1929 * communication resource.
1933 * True on success and false if the communications handle is bad.
1935 BOOL WINAPI PurgeComm(
1936 HANDLE handle, /* [in] The communication resource to be purged. */
1937 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
1941 TRACE("handle %d, flags %lx\n", handle, flags);
1943 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
1945 FIXME("no handle %d found\n",handle);
1950 ** not exactly sure how these are different
1951 ** Perhaps if we had our own internal queues, one flushes them
1952 ** and the other flushes the kernel's buffers.
1954 if(flags&PURGE_TXABORT)
1955 tcflush(fd,TCOFLUSH);
1956 if(flags&PURGE_RXABORT)
1957 tcflush(fd,TCIFLUSH);
1958 if(flags&PURGE_TXCLEAR)
1959 tcflush(fd,TCOFLUSH);
1960 if(flags&PURGE_RXCLEAR)
1961 tcflush(fd,TCIFLUSH);
1967 /*****************************************************************************
1968 * ClearCommError (KERNEL32.136)
1970 * Enables further I/O operations on a communications resource after
1971 * supplying error and current status information.
1975 * True on success, false if the communication resource handle is bad.
1977 BOOL WINAPI ClearCommError(
1978 HANDLE handle, /* [in] The communication resource with the error. */
1979 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
1980 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
1984 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
1987 FIXME("no handle %d found\n",handle);
1996 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
1997 WARN("ioctl returned error\n");
1999 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
2003 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
2004 WARN("ioctl returned error\n");
2007 TRACE("handle %d cbInQue = %ld cbOutQue = %ld\n",
2008 handle, lpStat->cbInQue, lpStat->cbOutQue);
2017 ** After an asynchronous write opperation, the
2018 ** app will call ClearCommError to see if the
2019 ** results are ready yet. It waits for ERROR_IO_PENDING
2021 commerror = ERROR_IO_PENDING;
2026 /*****************************************************************************
2027 * SetupComm (KERNEL32.677)
2029 * Called after CreateFile to hint to the communication resource to use
2030 * specified sizes for input and output buffers rather than the default values.
2034 * True if successful, false if the communications resource handle is bad.
2040 BOOL WINAPI SetupComm(
2041 HANDLE handle, /* [in] The just created communication resource handle. */
2042 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
2043 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
2047 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
2048 fd=FILE_GetUnixHandle( handle, GENERIC_READ );
2050 FIXME("handle %d not found?\n",handle);
2057 /*****************************************************************************
2058 * GetCommMask (KERNEL32.284)
2060 * Obtain the events associated with a communication device that will cause a call
2061 * WaitCommEvent to return.
2065 * True on success, fail on bad device handle etc.
2067 BOOL WINAPI GetCommMask(
2068 HANDLE handle, /* [in] The communications device. */
2069 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
2073 TRACE("handle %d, mask %p\n", handle, evtmask);
2077 struct get_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2078 req->handle = handle;
2079 if ((ret = !server_call( REQ_GET_SERIAL_INFO )))
2081 if (evtmask) *evtmask = req->eventmask;
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.)
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. */
2105 TRACE("handle %d, mask %lx\n", handle, evtmask);
2109 struct set_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2110 req->handle = handle;
2111 req->flags = SERIALINFO_SET_MASK;
2112 req->eventmask = evtmask;
2113 ret = !server_call( REQ_SET_SERIAL_INFO );
2119 /*****************************************************************************
2120 * SetCommState (KERNEL32.619)
2122 * Re-initializes all hardware and control settings of a communications device,
2123 * with values from a device control block without effecting the input and output
2128 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
2130 BOOL WINAPI SetCommState(
2131 HANDLE handle, /* [in] The communications device. */
2132 LPDCB lpdcb) /* [out] The device control block. */
2134 struct termios port;
2135 int fd, bytesize, stopbits;
2137 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2138 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2139 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2140 (lpdcb->StopBits == ONESTOPBIT)?1:
2141 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2142 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2143 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2145 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2147 FIXME("no handle %d found\n",handle);
2151 if ((tcgetattr(fd,&port)) == -1) {
2152 int save_error = errno;
2153 commerror = WinError();
2155 ERR("tcgetattr error '%s'\n", strerror(save_error));
2159 port.c_cc[VMIN] = 0;
2160 port.c_cc[VTIME] = 1;
2163 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
2165 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
2167 port.c_iflag |= (IGNBRK);
2169 port.c_oflag &= ~(OPOST);
2171 port.c_cflag &= ~(HUPCL);
2172 port.c_cflag |= CLOCAL | CREAD;
2174 port.c_lflag &= ~(ICANON|ECHO|ISIG);
2175 port.c_lflag |= NOFLSH;
2178 ** MJM - removed default baudrate settings
2179 ** TRACE(comm,"baudrate %ld\n",lpdcb->BaudRate);
2182 port.c_cflag &= ~CBAUD;
2183 switch (lpdcb->BaudRate) {
2186 port.c_cflag |= B110;
2190 port.c_cflag |= B300;
2194 port.c_cflag |= B600;
2198 port.c_cflag |= B1200;
2202 port.c_cflag |= B2400;
2206 port.c_cflag |= B4800;
2210 port.c_cflag |= B9600;
2214 port.c_cflag |= B19200;
2218 port.c_cflag |= B38400;
2222 port.c_cflag |= B57600;
2227 port.c_cflag |= B115200;
2232 port.c_cflag |= B230400;
2237 port.c_cflag |= B460800;
2241 commerror = IE_BAUDRATE;
2243 ERR("baudrate %ld\n",lpdcb->BaudRate);
2246 #elif !defined(__EMX__)
2247 switch (lpdcb->BaudRate) {
2250 port.c_ospeed = B110;
2254 port.c_ospeed = B300;
2258 port.c_ospeed = B600;
2262 port.c_ospeed = B1200;
2266 port.c_ospeed = B2400;
2270 port.c_ospeed = B4800;
2274 port.c_ospeed = B9600;
2278 port.c_ospeed = B19200;
2282 port.c_ospeed = B38400;
2285 commerror = IE_BAUDRATE;
2287 ERR("baudrate %ld\n",lpdcb->BaudRate);
2290 port.c_ispeed = port.c_ospeed;
2292 bytesize=lpdcb->ByteSize;
2293 stopbits=lpdcb->StopBits;
2296 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
2298 port.c_cflag &= ~(PARENB | PARODD);
2301 port.c_iflag |= INPCK;
2303 port.c_iflag &= ~INPCK;
2304 switch (lpdcb->Parity) {
2308 port.c_cflag |= (PARENB | PARODD);
2311 port.c_cflag |= PARENB;
2314 /* Linux defines mark/space (stick) parity */
2316 port.c_cflag |= (PARENB | CMSPAR);
2319 port.c_cflag |= (PARENB | PARODD | CMSPAR);
2322 /* try the POSIX way */
2324 if( stopbits == ONESTOPBIT) {
2325 stopbits = TWOSTOPBITS;
2326 port.c_iflag &= ~INPCK;
2328 commerror = IE_BYTESIZE;
2330 ERR("Cannot set MARK Parity\n");
2337 port.c_iflag &= ~INPCK;
2339 commerror = IE_BYTESIZE;
2341 ERR("Cannot set SPACE Parity\n");
2347 commerror = IE_BYTESIZE;
2354 port.c_cflag &= ~CSIZE;
2357 port.c_cflag |= CS5;
2360 port.c_cflag |= CS6;
2363 port.c_cflag |= CS7;
2366 port.c_cflag |= CS8;
2369 commerror = IE_BYTESIZE;
2377 port.c_cflag &= ~CSTOPB;
2379 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
2381 port.c_cflag |= CSTOPB;
2384 commerror = IE_BYTESIZE;
2390 if ( lpdcb->fOutxCtsFlow ||
2391 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2392 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2395 port.c_cflag |= CRTSCTS;
2399 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2401 port.c_cflag &= ~CRTSCTS;
2402 TRACE("~CRTSCTS\n");
2407 port.c_iflag |= IXON;
2409 port.c_iflag &= ~IXON;
2411 port.c_iflag |= IXOFF;
2413 port.c_iflag &= ~IXOFF;
2415 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
2416 int save_error=errno;
2417 commerror = WinError();
2419 ERR("tcsetattr error '%s'\n", strerror(save_error));
2429 /*****************************************************************************
2430 * GetCommState (KERNEL32.287)
2432 * Fills in a device control block with information from a communications device.
2436 * True on success, false if the communication device handle is bad etc
2440 * XonChar and XoffChar are not set.
2442 BOOL WINAPI GetCommState(
2443 HANDLE handle, /* [in] The communications device. */
2444 LPDCB lpdcb) /* [out] The device control block. */
2446 struct termios port;
2449 TRACE("handle %d, ptr %p\n", handle, lpdcb);
2451 fd = FILE_GetUnixHandle( handle, GENERIC_READ );
2454 ERR("FILE_GetUnixHandle failed\n");
2457 if (tcgetattr(fd, &port) == -1) {
2458 int save_error=errno;
2459 ERR("tcgetattr error '%s'\n", strerror(save_error));
2460 commerror = WinError();
2467 speed= (port.c_cflag & CBAUD);
2469 speed= (cfgetospeed(&port));
2473 lpdcb->BaudRate = 110;
2476 lpdcb->BaudRate = 300;
2479 lpdcb->BaudRate = 600;
2482 lpdcb->BaudRate = 1200;
2485 lpdcb->BaudRate = 2400;
2488 lpdcb->BaudRate = 4800;
2491 lpdcb->BaudRate = 9600;
2494 lpdcb->BaudRate = 19200;
2497 lpdcb->BaudRate = 38400;
2501 lpdcb->BaudRate = 57600;
2506 lpdcb->BaudRate = 115200;
2511 lpdcb->BaudRate = 230400;
2516 lpdcb->BaudRate = 460800;
2520 ERR("unknown speed %x \n",speed);
2523 switch (port.c_cflag & CSIZE) {
2525 lpdcb->ByteSize = 5;
2528 lpdcb->ByteSize = 6;
2531 lpdcb->ByteSize = 7;
2534 lpdcb->ByteSize = 8;
2537 ERR("unknown size %x \n",port.c_cflag & CSIZE);
2540 if(port.c_iflag & INPCK)
2541 lpdcb->fParity = TRUE;
2543 lpdcb->fParity = FALSE;
2545 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
2547 switch (port.c_cflag & (PARENB | PARODD))
2551 lpdcb->Parity = NOPARITY;
2554 lpdcb->Parity = EVENPARITY;
2556 case (PARENB | PARODD):
2557 lpdcb->Parity = ODDPARITY;
2560 case (PARENB | CMSPAR):
2561 lpdcb->Parity = MARKPARITY;
2563 case (PARENB | PARODD | CMSPAR):
2564 lpdcb->Parity = SPACEPARITY;
2569 if (port.c_cflag & CSTOPB)
2570 if(lpdcb->ByteSize == 5)
2571 lpdcb->StopBits = ONE5STOPBITS;
2573 lpdcb->StopBits = TWOSTOPBITS;
2575 lpdcb->StopBits = ONESTOPBIT;
2582 if (port.c_cflag & CRTSCTS) {
2583 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
2584 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
2585 lpdcb->fOutxCtsFlow = 1;
2586 lpdcb->fOutxDsrFlow = 1;
2590 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
2591 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
2593 if (port.c_iflag & IXON)
2598 if (port.c_iflag & IXOFF)
2607 lpdcb->XoffLim = 10;
2613 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
2614 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
2615 (lpdcb->StopBits == ONESTOPBIT)?1:
2616 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
2617 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
2618 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
2620 if ( lpdcb->fOutxCtsFlow ||
2621 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
2622 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
2626 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
2627 TRACE("~CRTSCTS\n");
2633 /*****************************************************************************
2634 * TransmitCommChar (KERNEL32.697)
2636 * Transmits a single character in front of any pending characters in the
2637 * output buffer. Usually used to send an interrupt character to a host.
2641 * True if the call succeeded, false if the previous command character to the
2642 * same device has not been sent yet the handle is bad etc.
2648 BOOL WINAPI TransmitCommChar(
2649 HANDLE hComm, /* [in] The communication device in need of a command character. */
2650 CHAR chTransmit) /* [in] The character to transmit. */
2652 FIXME("(%x,'%c'), use win32 handle!\n",hComm,chTransmit);
2656 /*****************************************************************************
2657 * GetCommTimeouts (KERNEL32.288)
2659 * Obtains the request time out values for the communications device.
2663 * True on success, false if communications device handle is bad
2664 * or the target structure is null.
2666 BOOL WINAPI GetCommTimeouts(
2667 HANDLE hComm, /* [in] The communications device. */
2668 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request time outs. */
2672 TRACE("(%x,%p)\n",hComm,lptimeouts);
2676 SetLastError(ERROR_INVALID_PARAMETER);
2682 struct get_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2683 req->handle = hComm;
2684 if ((ret = !server_call( REQ_GET_SERIAL_INFO )))
2686 lptimeouts->ReadIntervalTimeout = req->readinterval;
2687 lptimeouts->ReadTotalTimeoutMultiplier = req->readmult;
2688 lptimeouts->ReadTotalTimeoutConstant = req->readconst;
2689 lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
2690 lptimeouts->WriteTotalTimeoutConstant = req->writeconst;
2697 /*****************************************************************************
2698 * SetCommTimeouts (KERNEL32.620)
2700 * Sets the timeouts used when reading and writing data to/from COMM ports.
2702 * ReadIntervalTimeout
2703 * - converted and passes to linux kernel as c_cc[VTIME]
2704 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
2705 * - used in ReadFile to calculate GetOverlappedResult's timeout
2706 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
2707 * - used in WriteFile to calculate GetOverlappedResult's timeout
2711 * True if the time outs were set, false otherwise.
2713 BOOL WINAPI SetCommTimeouts(
2714 HANDLE hComm, /* [in] handle of COMM device */
2715 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
2719 struct termios tios;
2721 TRACE("(%x,%p)\n",hComm,lptimeouts);
2725 SetLastError(ERROR_INVALID_PARAMETER);
2731 struct set_serial_info_request *req = server_alloc_req( sizeof(*req), 0 );
2732 req->handle = hComm;
2733 req->flags = SERIALINFO_SET_TIMEOUTS;
2734 req->readinterval = lptimeouts->ReadIntervalTimeout ;
2735 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
2736 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
2737 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
2738 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
2739 ret = !server_call( REQ_SET_SERIAL_INFO );
2742 if (!ret) return FALSE;
2744 /* FIXME: move this stuff to the server */
2745 fd = FILE_GetUnixHandle( hComm, GENERIC_READ );
2747 FIXME("no fd for handle = %0x!.\n",hComm);
2751 if (-1==tcgetattr(fd,&tios)) {
2752 FIXME("tcgetattr on fd %d failed!\n",fd);
2755 /* VTIME is in 1/10 seconds */
2756 tios.c_cc[VTIME]= (lptimeouts->ReadIntervalTimeout+99)/100;
2757 if (-1==tcsetattr(fd,0,&tios)) {
2758 FIXME("tcsetattr on fd %d failed!\n",fd);
2765 /***********************************************************************
2766 * GetCommModemStatus (KERNEL32.285)
2768 * Obtains the four control register bits if supported by the hardware.
2772 * True if the communications handle was good and for hardware that
2773 * control register access, false otherwise.
2775 BOOL WINAPI GetCommModemStatus(
2776 HANDLE hFile, /* [in] The communications device. */
2777 LPDWORD lpModemStat) /* [out] The control register bits. */
2779 int fd,mstat, result=FALSE;
2783 fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
2786 result = ioctl(fd, TIOCMGET, &mstat);
2790 WARN("ioctl failed\n");
2794 if (mstat & TIOCM_CTS)
2795 *lpModemStat |= MS_CTS_ON;
2798 if (mstat & TIOCM_DSR)
2799 *lpModemStat |= MS_DSR_ON;
2802 if (mstat & TIOCM_RNG)
2803 *lpModemStat |= MS_RING_ON;
2806 /*FIXME: Not really sure about RLSD UB 990810*/
2807 if (mstat & TIOCM_CAR)
2808 *lpModemStat |= MS_RLSD_ON;
2810 TRACE("%04x -> %s%s%s%s\n", mstat,
2811 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
2812 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
2813 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
2814 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
2821 VOID COMM_WaitCommEventService(void **args)
2823 LPOVERLAPPED lpOverlapped = (LPOVERLAPPED)args[0];
2824 LPDWORD buffer = (LPDWORD)args[1];
2825 DWORD events = (DWORD)args[2];
2827 TRACE("overlapped %p wait complete %p <- %lx\n",lpOverlapped,buffer,events);
2831 lpOverlapped->Internal = STATUS_SUCCESS;
2832 SetEvent( lpOverlapped->hEvent);
2833 CloseHandle(lpOverlapped->InternalHigh);
2836 /***********************************************************************
2837 * WaitCommEvent (KERNEL32.719)
2839 * Wait until something interesting happens on a COMM port.
2840 * Interesting things (events) are set by calling SetCommMask before
2841 * this function is called.
2844 * TRUE if successful
2847 * The set of detected events will be written to *lpdwEventMask
2848 * ERROR_IO_PENDING will be returned the overlapped structure was passed
2851 * Only supports EV_RXCHAR and EV_TXEMPTY
2853 BOOL WINAPI WaitCommEvent(
2854 HANDLE hFile, /* [in] handle of comm port to wait for */
2855 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
2856 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
2862 TRACE("(%x %p %p )\n",hFile, lpdwEvents,lpOverlapped);
2864 /* if there is no overlapped structure, create our own */
2867 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
2871 lpov = lpOverlapped;
2873 /* check that the overlapped structure has a valid event flag */
2874 if ( (lpov->hEvent==0) || (lpov->hEvent == INVALID_HANDLE_VALUE) )
2876 ERR("Couldn't create Event flag for Overlapped structure\n");
2877 SetLastError(ERROR_INVALID_PARAMETER);
2881 ResetEvent(lpov->hEvent);
2883 lpov->Internal = STATUS_PENDING;
2884 lpov->InternalHigh = 0;
2886 lpov->OffsetHigh = 0;
2888 /* start an ASYNCHRONOUS WaitCommEvent */
2891 struct create_async_request *req = server_alloc_req( sizeof(*req), 0 );
2893 req->file_handle = hFile;
2894 req->overlapped = lpov;
2895 req->buffer = lpdwEvents;
2897 req->func = COMM_WaitCommEventService;
2898 req->type = ASYNC_TYPE_WAIT;
2900 ret=server_call( REQ_CREATE_ASYNC );
2902 lpov->InternalHigh = req->ov_handle;
2909 CloseHandle(lpov->hEvent);
2910 TRACE("server call failed.\n");
2914 /* activate the overlapped operation */
2915 lpov->Internal = STATUS_PENDING;
2917 /* wait ourselves if the caller didn't give us an overlapped struct */
2920 GetOverlappedResult(hFile, lpov, NULL, TRUE);
2921 CloseHandle(lpov->hEvent);
2926 /* caller wants overlapped I/O using GetOverlapped result */
2927 SetLastError(ERROR_IO_PENDING);
2934 /***********************************************************************
2935 * GetCommProperties (KERNEL32.286)
2937 * This function fills in a structure with the capabilities of the
2938 * communications port driver.
2942 * TRUE on success, FALSE on failure
2943 * If successful, the lpCommProp structure be filled in with
2944 * properties of the comm port.
2946 BOOL WINAPI GetCommProperties(
2947 HANDLE hFile, /* [in] handle of the comm port */
2948 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
2950 FIXME("(%d %p )\n",hFile,lpCommProp);
2955 * These values should be valid for LINUX's serial driver
2956 * FIXME: Perhaps they deserve an #ifdef LINUX
2958 memset(lpCommProp,0,sizeof(COMMPROP));
2959 lpCommProp->wPacketLength = 1;
2960 lpCommProp->wPacketVersion = 1;
2961 lpCommProp->dwServiceMask = SP_SERIALCOMM;
2962 lpCommProp->dwReserved1 = 0;
2963 lpCommProp->dwMaxTxQueue = 4096;
2964 lpCommProp->dwMaxRxQueue = 4096;
2965 lpCommProp->dwMaxBaud = BAUD_115200;
2966 lpCommProp->dwProvSubType = PST_RS232;
2967 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS ;
2968 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
2969 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
2970 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
2971 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
2972 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
2973 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
2974 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
2975 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
2976 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
2977 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
2982 /***********************************************************************
2984 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
2985 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
2986 * This is dependent on the type of COMM port, but since it is doubtful
2987 * anybody will get around to implementing support for fancy serial
2988 * ports in WINE, this is hardcoded for the time being. The name of
2989 * this DLL should be stored in and read from the system registry in
2990 * the hive HKEY_LOCAL_MACHINE, key
2991 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
2992 * where ???? is the port number... that is determined by PNP
2993 * The DLL should be loaded when the COMM port is opened, and closed
2994 * when the COMM port is closed. - MJM 20 June 2000
2995 ***********************************************************************/
2996 static CHAR lpszSerialUI[] = "serialui.dll";
2999 /***********************************************************************
3000 * CommConfigDialogA (KERNEL32.140)
3002 * Raises a dialog that allows the user to configure a comm port.
3003 * Fills the COMMCONFIG struct with information specified by the user.
3004 * This function should call a similar routine in the COMM driver...
3008 * TRUE on success, FALSE on failure
3009 * If successful, the lpCommConfig structure will contain a new
3010 * configuration for the comm port, as specified by the user.
3013 * The library with the CommConfigDialog code is never unloaded.
3014 * Perhaps this should be done when the comm port is closed?
3016 BOOL WINAPI CommConfigDialogA(
3017 LPCSTR lpszDevice, /* [in] name of communications device */
3018 HANDLE hWnd, /* [in] parent window for the dialog */
3019 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
3021 FARPROC lpfnCommDialog;
3022 HMODULE hConfigModule;
3025 TRACE("(%p %x %p)\n",lpszDevice, hWnd, lpCommConfig);
3027 hConfigModule = LoadLibraryA(lpszSerialUI);
3031 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
3036 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
3038 /* UnloadLibrary(hConfigModule); */
3043 /***********************************************************************
3044 * CommConfigDialogW (KERNEL32.141)
3046 * see CommConfigDialogA for more info
3048 BOOL WINAPI CommConfigDialogW(
3049 LPCWSTR lpszDevice, /* [in] name of communications device */
3050 HANDLE hWnd, /* [in] parent window for the dialog */
3051 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
3056 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
3059 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
3060 HeapFree( GetProcessHeap(), 0, lpDeviceA );
3064 /***********************************************************************
3065 * GetCommConfig (KERNEL32.283)
3067 * Fill in the COMMCONFIG structure for the comm port hFile
3071 * TRUE on success, FALSE on failure
3072 * If successful, lpCommConfig contains the comm port configuration.
3076 * The signature is missing a the parameter for the size of the COMMCONFIG
3077 * structure/buffer it should be
3078 * BOOL WINAPI GetCommConfig(HANDLE hFile,LPCOMMCONFIG lpCommConfig,LPDWORD lpdwSize)
3080 BOOL WINAPI GetCommConfig(
3081 HANDLE hFile, /* [in] The communications device. */
3082 LPCOMMCONFIG lpCommConfig) /* [out] The communications configuration of the device (if it fits). */
3083 #if 0 /* FIXME: Why is this "commented" out? */
3084 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
3085 afterwards the number of bytes copied to the buffer or
3086 the needed size of the buffer. */
3091 TRACE("(%x %p)\n",hFile,lpCommConfig);
3093 if(lpCommConfig == NULL)
3096 lpCommConfig->dwSize = sizeof(COMMCONFIG);
3097 lpCommConfig->wVersion = 1;
3098 lpCommConfig->wReserved = 0;
3099 r = GetCommState(hFile,&lpCommConfig->dcb);
3100 lpCommConfig->dwProviderSubType = PST_RS232;
3101 lpCommConfig->dwProviderOffset = 0;
3102 lpCommConfig->dwProviderSize = 0;
3107 /***********************************************************************
3108 * SetCommConfig (KERNEL32.617)
3110 * Sets the configuration of the commications device.
3114 * True on success, false if the handle was bad is not a communications device.
3116 BOOL WINAPI SetCommConfig(
3117 HANDLE hFile, /* [in] The communications device. */
3118 LPCOMMCONFIG lpCommConfig) /* [in] The desired configuration. */
3120 TRACE("(%x %p)\n",hFile,lpCommConfig);
3121 return SetCommState(hFile,&lpCommConfig->dcb);
3124 /***********************************************************************
3125 * SetDefaultCommConfigA (KERNEL32.638)
3127 * Initializes the default configuration for the specified communication
3132 * True if the device was found and the defaults set, false otherwise
3134 BOOL WINAPI SetDefaultCommConfigA(
3135 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
3136 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
3137 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
3139 FARPROC lpfnSetDefaultCommConfig;
3140 HMODULE hConfigModule;
3143 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
3145 hConfigModule = LoadLibraryA(lpszSerialUI);
3149 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
3151 if(! lpfnSetDefaultCommConfig)
3154 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
3156 /* UnloadLibrary(hConfigModule); */
3162 /***********************************************************************
3163 * SetDefaultCommConfigW (KERNEL32.639)
3165 * Initializes the default configuration for the specified
3166 * communication device. (unicode)
3171 BOOL WINAPI SetDefaultCommConfigW(
3172 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
3173 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
3174 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
3179 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
3181 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
3184 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
3185 HeapFree( GetProcessHeap(), 0, lpDeviceA );
3190 /***********************************************************************
3191 * GetDefaultCommConfigA (KERNEL32.313)
3193 * Acquires the default configuration of the specified communication device. (unicode)
3197 * True on successful reading of the default configuration,
3198 * if the device is not found or the buffer is too small.
3200 BOOL WINAPI GetDefaultCommConfigA(
3201 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
3202 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
3203 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
3204 afterwards the number of bytes copied to the buffer or
3205 the needed size of the buffer. */
3207 LPDCB lpdcb = &(lpCC->dcb);
3210 if (strncasecmp(lpszName,"COM",3)) {
3211 ERR("not implemented for <%s>\n", lpszName);
3215 if (!ValidCOMPort(lpszName[3]-'1'))
3218 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
3219 if (*lpdwSize < sizeof(COMMCONFIG)) {
3220 *lpdwSize = sizeof(COMMCONFIG);
3224 *lpdwSize = sizeof(COMMCONFIG);
3226 lpCC->dwSize = sizeof(COMMCONFIG);
3228 lpCC->dwProviderSubType = PST_RS232;
3229 lpCC->dwProviderOffset = 0L;
3230 lpCC->dwProviderSize = 0L;
3232 (void) sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
3233 FIXME("setting %s as default\n", temp);
3235 return BuildCommDCBA( temp, lpdcb);
3238 /**************************************************************************
3239 * GetDefaultCommConfigW (KERNEL32.314)
3241 * Acquires the default configuration of the specified communication device. (unicode)
3245 * True on successful reading of the default configuration,
3246 * if the device is not found or the buffer is too small.
3248 BOOL WINAPI GetDefaultCommConfigW(
3249 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
3250 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
3251 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
3252 afterwards the number of bytes copied to the buffer or
3253 the needed size of the buffer. */
3258 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
3259 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
3262 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
3263 HeapFree( GetProcessHeap(), 0, lpszNameA );