Release 961222
[wine/multimedia.git] / misc / comm.c
blobea2735dcf0b9f149bada70cec977af856b52a649
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
5 * FIXME: use HFILEs instead of unixfds
6 * the win32 functions here get HFILEs already.
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <termios.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <ctype.h>
16 #include <sys/stat.h>
17 #if defined(__NetBSD__) || defined(__FreeBSD__)
18 #include <sys/ioctl.h>
19 #endif
20 #include <unistd.h>
22 #include "windows.h"
23 #include "comm.h"
24 #include "heap.h"
25 #include "options.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "handle32.h"
30 int commerror = 0, eventmask = 0;
32 struct DosDeviceStruct COM[MAX_PORTS];
33 struct DosDeviceStruct LPT[MAX_PORTS];
35 void COMM_Init(void)
37 int x;
38 char option[10], temp[256], *btemp;
39 struct stat st;
41 for (x=0; x!=MAX_PORTS; x++) {
42 strcpy(option,"COMx");
43 option[3] = '1' + x;
44 option[4] = '\0';
46 PROFILE_GetWineIniString( "serialports", option, "*",
47 temp, sizeof(temp) );
48 if (!strcmp(temp, "*") || *temp == '\0')
49 COM[x].devicename = NULL;
50 else {
51 btemp = strchr(temp,',');
52 if (btemp != NULL) {
53 *btemp++ = '\0';
54 COM[x].baudrate = atoi(btemp);
55 } else {
56 COM[x].baudrate = -1;
58 stat(temp, &st);
59 if (!S_ISCHR(st.st_mode))
60 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
61 else
62 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
63 fprintf(stderr,"comm: can't malloc for device info!\n");
64 else {
65 COM[x].fd = 0;
66 strcpy(COM[x].devicename, temp);
68 dprintf_comm(stddeb,
69 "Comm_Init: %s = %s\n", option, COM[x].devicename);
72 strcpy(option, "LPTx");
73 option[3] = '1' + x;
74 option[4] = '\0';
76 PROFILE_GetWineIniString( "parallelports", option, "*",
77 temp, sizeof(temp) );
78 if (!strcmp(temp, "*") || *temp == '\0')
79 LPT[x].devicename = NULL;
80 else {
81 stat(temp, &st);
82 if (!S_ISCHR(st.st_mode))
83 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
84 else
85 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
86 fprintf(stderr,"comm: can't malloc for device info!\n");
87 else {
88 LPT[x].fd = 0;
89 strcpy(LPT[x].devicename, temp);
91 dprintf_comm(stddeb,
92 "Comm_Init: %s = %s\n", option, LPT[x].devicename);
99 struct DosDeviceStruct *GetDeviceStruct(int fd)
101 int x;
103 for (x=0; x!=MAX_PORTS; x++) {
104 if (COM[x].fd == fd)
105 return &COM[x];
106 if (LPT[x].fd == fd)
107 return &LPT[x];
110 return NULL;
113 int ValidCOMPort(int x)
115 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
118 int ValidLPTPort(int x)
120 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
123 int WinError(void)
125 dprintf_comm(stddeb, "WinError: errno = %d\n", errno);
126 switch (errno) {
127 default:
128 return CE_IOE;
132 /**************************************************************************
133 * BuildCommDCB (USER.213)
135 BOOL16 BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
137 /* "COM1:9600,n,8,1" */
138 /* 012345 */
139 int port;
140 char *ptr, temp[256];
142 dprintf_comm(stddeb,
143 "BuildCommDCB: (%s), ptr %p\n", device, lpdcb);
144 commerror = 0;
146 if (!lstrncmpi32A(device,"COM",3)) {
147 port = device[3] - '0';
150 if (port-- == 0) {
151 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
152 commerror = IE_BADID;
155 if (!ValidCOMPort(port)) {
156 commerror = IE_BADID;
157 return -1;
160 if (!COM[port].fd) {
161 OpenComm(device, 0, 0);
163 lpdcb->Id = COM[port].fd;
165 if (!*(device+4))
166 return 0;
168 if (*(device+4) != ':')
169 return -1;
171 strcpy(temp,device+5);
172 ptr = strtok(temp, ", ");
174 if (COM[port].baudrate > 0)
175 lpdcb->BaudRate = COM[port].baudrate;
176 else
177 lpdcb->BaudRate = atoi(ptr);
178 dprintf_comm(stddeb,"BuildCommDCB: baudrate (%d)\n", lpdcb->BaudRate);
180 ptr = strtok(NULL, ", ");
181 if (islower(*ptr))
182 *ptr = toupper(*ptr);
184 dprintf_comm(stddeb,"BuildCommDCB: parity (%c)\n", *ptr);
185 lpdcb->fParity = 1;
186 switch (*ptr) {
187 case 'N':
188 lpdcb->Parity = NOPARITY;
189 lpdcb->fParity = 0;
190 break;
191 case 'E':
192 lpdcb->Parity = EVENPARITY;
193 break;
194 case 'M':
195 lpdcb->Parity = MARKPARITY;
196 break;
197 case 'O':
198 lpdcb->Parity = ODDPARITY;
199 break;
200 default:
201 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
202 return -1;
205 ptr = strtok(NULL, ", ");
206 dprintf_comm(stddeb, "BuildCommDCB: charsize (%c)\n", *ptr);
207 lpdcb->ByteSize = *ptr - '0';
209 ptr = strtok(NULL, ", ");
210 dprintf_comm(stddeb, "BuildCommDCB: stopbits (%c)\n", *ptr);
211 switch (*ptr) {
212 case '1':
213 lpdcb->StopBits = ONESTOPBIT;
214 break;
215 case '2':
216 lpdcb->StopBits = TWOSTOPBITS;
217 break;
218 default:
219 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
220 return -1;
224 return 0;
227 /**************************************************************************
228 * BuildCommDCBA (KERNEL32.14)
230 BOOL32 BuildCommDCB32A(LPCSTR device,LPDCB32 lpdcb) {
231 return BuildCommDCBAndTimeouts32A(device,lpdcb,NULL);
234 /**************************************************************************
235 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
237 BOOL32 BuildCommDCBAndTimeouts32A(LPCSTR device, LPDCB32 lpdcb,LPCOMMTIMEOUTS lptimeouts) {
238 int port;
239 char *ptr,*temp;
241 dprintf_comm(stddeb,"BuildCommDCBAndTimeouts32A(%s,%p,%p)\n",device,lpdcb,lptimeouts);
242 commerror = 0;
244 if (!lstrncmpi32A(device,"COM",3)) {
245 port=device[3]-'0';
246 if (port--==0) {
247 fprintf(stderr,"comm:BUG! COM0 can't exists!.\n");
248 return FALSE;
250 if (!ValidCOMPort(port))
251 return FALSE;
252 if (*(device+4)!=':')
253 return FALSE;
254 temp=(LPSTR)(device+5);
255 } else
256 temp=(LPSTR)device;
257 lpdcb->DCBlength = sizeof(DCB32);
258 if (strchr(temp,',')) { /* old style */
259 DCB16 dcb16;
260 BOOL16 ret;
261 char last=temp[strlen(temp)-1];
263 ret=BuildCommDCB16(device,&dcb16);
264 if (!ret)
265 return FALSE;
266 lpdcb->BaudRate = dcb16.BaudRate;
267 lpdcb->ByteSize = dcb16.ByteSize;
268 lpdcb->fBinary = dcb16.fBinary;
269 lpdcb->Parity = dcb16.Parity;
270 lpdcb->fParity = dcb16.fParity;
271 lpdcb->fNull = dcb16.fNull;
272 lpdcb->StopBits = dcb16.StopBits;
273 if (last == 'x') {
274 lpdcb->fInX = TRUE;
275 lpdcb->fOutX = TRUE;
276 lpdcb->fOutxCtsFlow = FALSE;
277 lpdcb->fOutxDsrFlow = FALSE;
278 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
279 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
280 } else if (last=='p') {
281 lpdcb->fInX = FALSE;
282 lpdcb->fOutX = FALSE;
283 lpdcb->fOutxCtsFlow = TRUE;
284 lpdcb->fOutxDsrFlow = TRUE;
285 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
286 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
287 } else {
288 lpdcb->fInX = FALSE;
289 lpdcb->fOutX = FALSE;
290 lpdcb->fOutxCtsFlow = FALSE;
291 lpdcb->fOutxDsrFlow = FALSE;
292 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
293 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
295 lpdcb->XonChar = dcb16.XonChar;
296 lpdcb->XoffChar = dcb16.XoffChar;
297 lpdcb->ErrorChar= dcb16.PeChar;
298 lpdcb->fErrorChar= dcb16.fPeChar;
299 lpdcb->EofChar = dcb16.EofChar;
300 lpdcb->EvtChar = dcb16.EvtChar;
301 lpdcb->XonLim = dcb16.XonLim;
302 lpdcb->XoffLim = dcb16.XoffLim;
303 return TRUE;
305 ptr=strtok(temp," ");
306 while (ptr) {
307 DWORD flag,x;
309 flag=0;
310 if (!strncmp("baud=",ptr,5)) {
311 if (!sscanf(ptr+5,"%ld",&x))
312 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
313 lpdcb->BaudRate = x;
314 flag=1;
316 if (!strncmp("stop=",ptr,5)) {
317 if (!sscanf(ptr+5,"%ld",&x))
318 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
319 lpdcb->StopBits = x;
320 flag=1;
322 if (!strncmp("data=",ptr,5)) {
323 if (!sscanf(ptr+5,"%ld",&x))
324 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
325 lpdcb->ByteSize = x;
326 flag=1;
328 if (!strncmp("parity=",ptr,7)) {
329 lpdcb->fParity = TRUE;
330 switch (ptr[8]) {
331 case 'N':case 'n':
332 lpdcb->fParity = FALSE;
333 lpdcb->Parity = NOPARITY;
334 break;
335 case 'E':case 'e':
336 lpdcb->Parity = EVENPARITY;
337 break;
338 case 'O':case 'o':
339 lpdcb->Parity = ODDPARITY;
340 break;
341 case 'M':case 'm':
342 lpdcb->Parity = MARKPARITY;
343 break;
345 flag=1;
347 if (!flag)
348 fprintf(stderr,"BuildCommDCB32A: Unhandled specifier '%s', please report.\n",ptr);
349 ptr=strtok(NULL," ");
351 if (lpdcb->BaudRate==110)
352 lpdcb->StopBits = 2;
353 return TRUE;
356 /**************************************************************************
357 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
359 BOOL32 BuildCommDCBAndTimeouts32W(
360 LPCWSTR devid,LPDCB32 lpdcb,LPCOMMTIMEOUTS lptimeouts
362 LPSTR devidA;
363 BOOL32 ret;
365 dprintf_comm(stddeb,"BuildCommDCBAndTimeouts32W(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
366 devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
367 ret=BuildCommDCBAndTimeouts32A(devidA,lpdcb,lptimeouts);
368 HeapFree( GetProcessHeap(), 0, devidA );
369 return ret;
372 /**************************************************************************
373 * BuildCommDCBW (KERNEL32.17)
375 BOOL32 BuildCommDCB32W(LPCWSTR devid,LPDCB32 lpdcb) {
376 return BuildCommDCBAndTimeouts32W(devid,lpdcb,NULL);
379 /*****************************************************************************
380 * OpenComm (USER.200)
382 INT16 OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
384 int port,fd;
386 dprintf_comm(stddeb,
387 "OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
388 commerror = 0;
390 if (!lstrncmpi32A(device,"COM",3)) {
391 port = device[3] - '0';
393 if (port-- == 0) {
394 fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n");
395 commerror = IE_BADID;
398 dprintf_comm(stddeb,
399 "OpenComm: %s = %s\n", device, COM[port].devicename);
401 if (!ValidCOMPort(port)) {
402 commerror = IE_BADID;
403 return -1;
405 if (COM[port].fd) {
406 return COM[port].fd;
409 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
410 if (fd == -1) {
411 commerror = WinError();
412 return -1;
413 } else {
414 COM[port].fd = fd;
415 return fd;
418 else
419 if (!lstrncmpi32A(device,"LPT",3)) {
420 port = device[3] - '0';
422 if (!ValidLPTPort(port)) {
423 commerror = IE_BADID;
424 return -1;
426 if (LPT[port].fd) {
427 commerror = IE_OPEN;
428 return -1;
431 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
432 if (fd == -1) {
433 commerror = WinError();
434 return -1;
435 } else {
436 LPT[port].fd = fd;
437 return fd;
440 return 0;
443 /*****************************************************************************
444 * CloseComm (USER.207)
446 INT16 CloseComm(INT16 fd)
448 dprintf_comm(stddeb,"CloseComm: fd %d\n", fd);
449 if (close(fd) == -1) {
450 commerror = WinError();
451 return -1;
452 } else {
453 commerror = 0;
454 return 0;
458 /*****************************************************************************
459 * SetCommBreak (USER.210)
461 INT16 SetCommBreak16(INT16 fd)
463 struct DosDeviceStruct *ptr;
465 dprintf_comm(stddeb,"SetCommBreak: fd: %d\n", fd);
466 if ((ptr = GetDeviceStruct(fd)) == NULL) {
467 commerror = IE_BADID;
468 return -1;
471 ptr->suspended = 1;
472 commerror = 0;
473 return 0;
476 /*****************************************************************************
477 * SetCommBreak (KERNEL32.449)
479 BOOL32 SetCommBreak32(INT32 fd)
482 struct DosDeviceStruct *ptr;
484 dprintf_comm(stddeb,"SetCommBreak: fd: %d\n", fd);
485 if ((ptr = GetDeviceStruct(fd)) == NULL) {
486 commerror = IE_BADID;
487 return FALSE;
490 ptr->suspended = 1;
491 commerror = 0;
492 return TRUE;
495 /*****************************************************************************
496 * ClearCommBreak (USER.211)
498 INT16 ClearCommBreak16(INT16 fd)
500 struct DosDeviceStruct *ptr;
502 dprintf_comm(stddeb,"ClearCommBreak: fd: %d\n", fd);
503 if ((ptr = GetDeviceStruct(fd)) == NULL) {
504 commerror = IE_BADID;
505 return -1;
508 ptr->suspended = 0;
509 commerror = 0;
510 return 0;
513 /*****************************************************************************
514 * ClearCommBreak (KERNEL32.20)
516 BOOL32 ClearCommBreak32(INT32 fd)
518 struct DosDeviceStruct *ptr;
520 dprintf_comm(stddeb,"ClearCommBreak: fd: %d\n", fd);
521 if ((ptr = GetDeviceStruct(fd)) == NULL) {
522 commerror = IE_BADID;
523 return FALSE;
526 ptr->suspended = 0;
527 commerror = 0;
528 return TRUE;
531 /*****************************************************************************
532 * EscapeCommFunction (USER.214)
534 LONG EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
536 int max;
537 struct termios port;
539 dprintf_comm(stddeb,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
540 if (tcgetattr(fd,&port) == -1) {
541 commerror=WinError();
542 return -1;
545 switch (nFunction) {
546 case RESETDEV:
547 break;
549 case GETMAXCOM:
550 for (max = MAX_PORTS;!COM[max].devicename;max--)
552 return max;
553 break;
555 case GETMAXLPT:
556 for (max = MAX_PORTS;!LPT[max].devicename;max--)
558 return 0x80 + max;
559 break;
561 #ifdef TIOCM_DTR
562 case CLRDTR:
563 port.c_cflag &= TIOCM_DTR;
564 break;
565 #endif
567 #ifdef TIOCM_RTS
568 case CLRRTS:
569 port.c_cflag &= TIOCM_RTS;
570 break;
571 #endif
573 #ifdef CRTSCTS
574 case SETDTR:
575 port.c_cflag |= CRTSCTS;
576 break;
578 case SETRTS:
579 port.c_cflag |= CRTSCTS;
580 break;
581 #endif
583 case SETXOFF:
584 port.c_iflag |= IXOFF;
585 break;
587 case SETXON:
588 port.c_iflag |= IXON;
589 break;
591 default:
592 fprintf(stderr,
593 "EscapeCommFunction fd: %d, unknown function: %d\n",
594 fd, nFunction);
595 break;
598 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
599 commerror = WinError();
600 return -1;
601 } else {
602 commerror = 0;
603 return 0;
607 /*****************************************************************************
608 * EscapeCommFunction (KERNEL32.214)
610 BOOL32 EscapeCommFunction32(INT32 fd,UINT32 nFunction)
612 struct termios port;
613 struct DosDeviceStruct *ptr;
615 dprintf_comm(stddeb,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
616 if (tcgetattr(fd,&port) == -1) {
617 commerror=WinError();
618 return FALSE;
620 if ((ptr = GetDeviceStruct(fd)) == NULL) {
621 commerror = IE_BADID;
622 return FALSE;
625 switch (nFunction) {
626 case RESETDEV:
627 break;
629 #ifdef TIOCM_DTR
630 case CLRDTR:
631 port.c_cflag &= TIOCM_DTR;
632 break;
633 #endif
635 #ifdef TIOCM_RTS
636 case CLRRTS:
637 port.c_cflag &= TIOCM_RTS;
638 break;
639 #endif
641 #ifdef CRTSCTS
642 case SETDTR:
643 port.c_cflag |= CRTSCTS;
644 break;
646 case SETRTS:
647 port.c_cflag |= CRTSCTS;
648 break;
649 #endif
651 case SETXOFF:
652 port.c_iflag |= IXOFF;
653 break;
655 case SETXON:
656 port.c_iflag |= IXON;
657 break;
658 case SETBREAK:
659 ptr->suspended = 1;
660 break;
661 case CLRBREAK:
662 ptr->suspended = 0;
663 break;
664 default:
665 fprintf(stderr,
666 "EscapeCommFunction32 fd: %d, unknown function: %d\n",
667 fd, nFunction);
668 break;
671 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
672 commerror = WinError();
673 return FALSE;
674 } else {
675 commerror = 0;
676 return TRUE;
680 /*****************************************************************************
681 * FlushComm (USER.215)
683 INT16 FlushComm(INT16 fd,INT16 fnQueue)
685 int queue;
687 dprintf_comm(stddeb,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
688 switch (fnQueue) {
689 case 0: queue = TCOFLUSH;
690 break;
691 case 1: queue = TCIFLUSH;
692 break;
693 default:fprintf(stderr,
694 "FlushComm fd: %d, UNKNOWN queue: %d\n",
695 fd, fnQueue);
696 return -1;
698 if (tcflush(fd, fnQueue)) {
699 commerror = WinError();
700 return -1;
701 } else {
702 commerror = 0;
703 return 0;
707 /*****************************************************************************
708 * GetCommError (USER.203)
710 INT16 GetCommError(INT16 fd,LPCOMSTAT lpStat)
712 int temperror;
714 dprintf_comm(stddeb,
715 "GetCommError: fd %d (current error %d)\n", fd, commerror);
716 temperror = commerror;
717 commerror = 0;
718 return(temperror);
721 /*****************************************************************************
722 * ClearCommError (KERNEL32.21)
724 BOOL32 ClearCommError(INT32 fd,LPDWORD errors,LPCOMSTAT lpStat)
726 int temperror;
728 dprintf_comm(stddeb,
729 "ClearCommError: fd %d (current error %d)\n", fd, commerror);
730 temperror = commerror;
731 commerror = 0;
732 return TRUE;
735 /*****************************************************************************
736 * SetCommEventMask (USER.208)
738 UINT16 *SetCommEventMask(INT16 fd,UINT16 fuEvtMask)
740 dprintf_comm(stddeb,"SetCommEventMask:fd %d,mask %d\n",fd,fuEvtMask);
741 eventmask |= fuEvtMask;
742 return (UINT *)&eventmask; /* FIXME, should be SEGPTR */
745 /*****************************************************************************
746 * GetCommEventMask (USER.209)
748 UINT16 GetCommEventMask(INT16 fd,UINT16 fnEvtClear)
750 dprintf_comm(stddeb,
751 "GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
752 eventmask &= ~fnEvtClear;
753 return eventmask;
756 /*****************************************************************************
757 * GetCommMask (KERNEL32.156)
759 BOOL32 GetCommMask(INT32 fd,LPDWORD evtmask)
761 dprintf_comm(stddeb,
762 "GetCommMask: fd %d, mask %p\n", fd, evtmask);
763 *evtmask = eventmask;
764 return TRUE;
767 /*****************************************************************************
768 * SetCommMask (KERNEL32.451)
770 BOOL32 SetCommMask(INT32 fd,DWORD evtmask)
772 dprintf_comm(stddeb,
773 "SetCommMask: fd %d, mask %lx\n", fd, evtmask);
774 eventmask = evtmask;
775 return TRUE;
778 /*****************************************************************************
779 * SetCommState16 (USER.201)
781 INT16 SetCommState16(LPDCB16 lpdcb)
783 struct termios port;
784 struct DosDeviceStruct *ptr;
786 dprintf_comm(stddeb,
787 "SetCommState: fd %d, ptr %p\n", lpdcb->Id, lpdcb);
788 if (tcgetattr(lpdcb->Id, &port) == -1) {
789 commerror = WinError();
790 return -1;
793 port.c_cc[VMIN] = 0;
794 port.c_cc[VTIME] = 1;
796 #ifdef IMAXBEL
797 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
798 #else
799 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
800 #endif
801 port.c_iflag |= (IGNBRK);
803 port.c_oflag &= ~(OPOST);
805 port.c_cflag &= ~(HUPCL);
806 port.c_cflag |= CLOCAL | CREAD;
808 port.c_lflag &= ~(ICANON|ECHO|ISIG);
809 port.c_lflag |= NOFLSH;
811 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
812 commerror = IE_BADID;
813 return -1;
815 if (ptr->baudrate > 0)
816 lpdcb->BaudRate = ptr->baudrate;
817 dprintf_comm(stddeb,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
818 #ifdef CBAUD
819 port.c_cflag &= ~CBAUD;
820 switch (lpdcb->BaudRate) {
821 case 110:
822 case CBR_110:
823 port.c_cflag |= B110;
824 break;
825 case 300:
826 case CBR_300:
827 port.c_cflag |= B300;
828 break;
829 case 600:
830 case CBR_600:
831 port.c_cflag |= B600;
832 break;
833 case 1200:
834 case CBR_1200:
835 port.c_cflag |= B1200;
836 break;
837 case 2400:
838 case CBR_2400:
839 port.c_cflag |= B2400;
840 break;
841 case 4800:
842 case CBR_4800:
843 port.c_cflag |= B4800;
844 break;
845 case 9600:
846 case CBR_9600:
847 port.c_cflag |= B9600;
848 break;
849 case 19200:
850 case CBR_19200:
851 port.c_cflag |= B19200;
852 break;
853 case 38400:
854 case CBR_38400:
855 port.c_cflag |= B38400;
856 break;
857 default:
858 commerror = IE_BAUDRATE;
859 return -1;
861 #else
862 switch (lpdcb->BaudRate) {
863 case 110:
864 case CBR_110:
865 port.c_ospeed = B110;
866 break;
867 case 300:
868 case CBR_300:
869 port.c_ospeed = B300;
870 break;
871 case 600:
872 case CBR_600:
873 port.c_ospeed = B600;
874 break;
875 case 1200:
876 case CBR_1200:
877 port.c_ospeed = B1200;
878 break;
879 case 2400:
880 case CBR_2400:
881 port.c_ospeed = B2400;
882 break;
883 case 4800:
884 case CBR_4800:
885 port.c_ospeed = B4800;
886 break;
887 case 9600:
888 case CBR_9600:
889 port.c_ospeed = B9600;
890 break;
891 case 19200:
892 case CBR_19200:
893 port.c_ospeed = B19200;
894 break;
895 case 38400:
896 case CBR_38400:
897 port.c_ospeed = B38400;
898 break;
899 default:
900 commerror = IE_BAUDRATE;
901 return -1;
903 port.c_ispeed = port.c_ospeed;
904 #endif
905 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
906 port.c_cflag &= ~CSIZE;
907 switch (lpdcb->ByteSize) {
908 case 5:
909 port.c_cflag |= CS5;
910 break;
911 case 6:
912 port.c_cflag |= CS6;
913 break;
914 case 7:
915 port.c_cflag |= CS7;
916 break;
917 case 8:
918 port.c_cflag |= CS8;
919 break;
920 default:
921 commerror = IE_BYTESIZE;
922 return -1;
925 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
926 port.c_cflag &= ~(PARENB | PARODD);
927 if (lpdcb->fParity)
928 switch (lpdcb->Parity) {
929 case NOPARITY:
930 port.c_iflag &= ~INPCK;
931 break;
932 case ODDPARITY:
933 port.c_cflag |= (PARENB | PARODD);
934 port.c_iflag |= INPCK;
935 break;
936 case EVENPARITY:
937 port.c_cflag |= PARENB;
938 port.c_iflag |= INPCK;
939 break;
940 default:
941 commerror = IE_BYTESIZE;
942 return -1;
946 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
947 switch (lpdcb->StopBits) {
948 case ONESTOPBIT:
949 port.c_cflag &= ~CSTOPB;
950 break;
951 case TWOSTOPBITS:
952 port.c_cflag |= CSTOPB;
953 break;
954 default:
955 commerror = IE_BYTESIZE;
956 return -1;
958 #ifdef CRTSCTS
960 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
961 port.c_cflag |= CRTSCTS;
963 if (lpdcb->fDtrDisable)
964 port.c_cflag &= ~CRTSCTS;
965 #endif
966 if (lpdcb->fInX)
967 port.c_iflag |= IXON;
968 if (lpdcb->fOutX)
969 port.c_iflag |= IXOFF;
971 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
972 commerror = WinError();
973 return -1;
974 } else {
975 commerror = 0;
976 return 0;
980 /*****************************************************************************
981 * SetCommState32 (KERNEL32.452)
983 BOOL32 SetCommState32(INT32 fd,LPDCB32 lpdcb)
985 struct termios port;
986 struct DosDeviceStruct *ptr;
988 dprintf_comm(stddeb,"SetCommState: fd %d, ptr %p\n",fd,lpdcb);
989 if (tcgetattr(fd,&port) == -1) {
990 commerror = WinError();
991 return FALSE;
994 port.c_cc[VMIN] = 0;
995 port.c_cc[VTIME] = 1;
997 #ifdef IMAXBEL
998 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
999 #else
1000 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1001 #endif
1002 port.c_iflag |= (IGNBRK);
1004 port.c_oflag &= ~(OPOST);
1006 port.c_cflag &= ~(HUPCL);
1007 port.c_cflag |= CLOCAL | CREAD;
1009 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1010 port.c_lflag |= NOFLSH;
1012 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1013 commerror = IE_BADID;
1014 return FALSE;
1016 if (ptr->baudrate > 0)
1017 lpdcb->BaudRate = ptr->baudrate;
1018 dprintf_comm(stddeb,"SetCommState: baudrate %ld\n",lpdcb->BaudRate);
1019 #ifdef CBAUD
1020 port.c_cflag &= ~CBAUD;
1021 switch (lpdcb->BaudRate) {
1022 case 110:
1023 case CBR_110:
1024 port.c_cflag |= B110;
1025 break;
1026 case 300:
1027 case CBR_300:
1028 port.c_cflag |= B300;
1029 break;
1030 case 600:
1031 case CBR_600:
1032 port.c_cflag |= B600;
1033 break;
1034 case 1200:
1035 case CBR_1200:
1036 port.c_cflag |= B1200;
1037 break;
1038 case 2400:
1039 case CBR_2400:
1040 port.c_cflag |= B2400;
1041 break;
1042 case 4800:
1043 case CBR_4800:
1044 port.c_cflag |= B4800;
1045 break;
1046 case 9600:
1047 case CBR_9600:
1048 port.c_cflag |= B9600;
1049 break;
1050 case 19200:
1051 case CBR_19200:
1052 port.c_cflag |= B19200;
1053 break;
1054 case 38400:
1055 case CBR_38400:
1056 port.c_cflag |= B38400;
1057 break;
1058 default:
1059 commerror = IE_BAUDRATE;
1060 return FALSE;
1062 #else
1063 switch (lpdcb->BaudRate) {
1064 case 110:
1065 case CBR_110:
1066 port.c_ospeed = B110;
1067 break;
1068 case 300:
1069 case CBR_300:
1070 port.c_ospeed = B300;
1071 break;
1072 case 600:
1073 case CBR_600:
1074 port.c_ospeed = B600;
1075 break;
1076 case 1200:
1077 case CBR_1200:
1078 port.c_ospeed = B1200;
1079 break;
1080 case 2400:
1081 case CBR_2400:
1082 port.c_ospeed = B2400;
1083 break;
1084 case 4800:
1085 case CBR_4800:
1086 port.c_ospeed = B4800;
1087 break;
1088 case 9600:
1089 case CBR_9600:
1090 port.c_ospeed = B9600;
1091 break;
1092 case 19200:
1093 case CBR_19200:
1094 port.c_ospeed = B19200;
1095 break;
1096 case 38400:
1097 case CBR_38400:
1098 port.c_ospeed = B38400;
1099 break;
1100 default:
1101 commerror = IE_BAUDRATE;
1102 return FALSE;
1104 port.c_ispeed = port.c_ospeed;
1105 #endif
1106 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
1107 port.c_cflag &= ~CSIZE;
1108 switch (lpdcb->ByteSize) {
1109 case 5:
1110 port.c_cflag |= CS5;
1111 break;
1112 case 6:
1113 port.c_cflag |= CS6;
1114 break;
1115 case 7:
1116 port.c_cflag |= CS7;
1117 break;
1118 case 8:
1119 port.c_cflag |= CS8;
1120 break;
1121 default:
1122 commerror = IE_BYTESIZE;
1123 return FALSE;
1126 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
1127 port.c_cflag &= ~(PARENB | PARODD);
1128 if (lpdcb->fParity)
1129 switch (lpdcb->Parity) {
1130 case NOPARITY:
1131 port.c_iflag &= ~INPCK;
1132 break;
1133 case ODDPARITY:
1134 port.c_cflag |= (PARENB | PARODD);
1135 port.c_iflag |= INPCK;
1136 break;
1137 case EVENPARITY:
1138 port.c_cflag |= PARENB;
1139 port.c_iflag |= INPCK;
1140 break;
1141 default:
1142 commerror = IE_BYTESIZE;
1143 return FALSE;
1147 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
1148 switch (lpdcb->StopBits) {
1149 case ONESTOPBIT:
1150 port.c_cflag &= ~CSTOPB;
1151 break;
1152 case TWOSTOPBITS:
1153 port.c_cflag |= CSTOPB;
1154 break;
1155 default:
1156 commerror = IE_BYTESIZE;
1157 return FALSE;
1159 #ifdef CRTSCTS
1160 if ( lpdcb->fOutxCtsFlow ||
1161 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1162 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1164 port.c_cflag |= CRTSCTS;
1165 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1166 port.c_cflag &= ~CRTSCTS;
1168 #endif
1169 if (lpdcb->fInX)
1170 port.c_iflag |= IXON;
1171 if (lpdcb->fOutX)
1172 port.c_iflag |= IXOFF;
1174 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1175 commerror = WinError();
1176 return FALSE;
1177 } else {
1178 commerror = 0;
1179 return TRUE;
1184 /*****************************************************************************
1185 * GetCommState (USER.202)
1187 INT16 GetCommState16(INT16 fd, LPDCB16 lpdcb)
1189 struct termios port;
1191 dprintf_comm(stddeb,"GetCommState: fd %d, ptr %p\n", fd, lpdcb);
1192 if (tcgetattr(fd, &port) == -1) {
1193 commerror = WinError();
1194 return -1;
1196 lpdcb->Id = fd;
1197 #ifdef CBAUD
1198 switch (port.c_cflag & CBAUD) {
1199 #else
1200 switch (port.c_ospeed) {
1201 #endif
1202 case B110:
1203 lpdcb->BaudRate = 110;
1204 break;
1205 case B300:
1206 lpdcb->BaudRate = 300;
1207 break;
1208 case B600:
1209 lpdcb->BaudRate = 600;
1210 break;
1211 case B1200:
1212 lpdcb->BaudRate = 1200;
1213 break;
1214 case B2400:
1215 lpdcb->BaudRate = 2400;
1216 break;
1217 case B4800:
1218 lpdcb->BaudRate = 4800;
1219 break;
1220 case B9600:
1221 lpdcb->BaudRate = 9600;
1222 break;
1223 case B19200:
1224 lpdcb->BaudRate = 19200;
1225 break;
1226 case B38400:
1227 lpdcb->BaudRate = 38400;
1228 break;
1231 switch (port.c_cflag & CSIZE) {
1232 case CS5:
1233 lpdcb->ByteSize = 5;
1234 break;
1235 case CS6:
1236 lpdcb->ByteSize = 6;
1237 break;
1238 case CS7:
1239 lpdcb->ByteSize = 7;
1240 break;
1241 case CS8:
1242 lpdcb->ByteSize = 8;
1243 break;
1246 switch (port.c_cflag & ~(PARENB | PARODD)) {
1247 case 0:
1248 lpdcb->fParity = NOPARITY;
1249 break;
1250 case PARENB:
1251 lpdcb->fParity = EVENPARITY;
1252 break;
1253 case (PARENB | PARODD):
1254 lpdcb->fParity = ODDPARITY;
1255 break;
1258 if (port.c_cflag & CSTOPB)
1259 lpdcb->StopBits = TWOSTOPBITS;
1260 else
1261 lpdcb->StopBits = ONESTOPBIT;
1263 lpdcb->RlsTimeout = 50;
1264 lpdcb->CtsTimeout = 50;
1265 lpdcb->DsrTimeout = 50;
1266 lpdcb->fNull = 0;
1267 lpdcb->fChEvt = 0;
1268 lpdcb->fBinary = 1;
1269 lpdcb->fDtrDisable = 0;
1271 #ifdef CRTSCTS
1273 if (port.c_cflag & CRTSCTS) {
1274 lpdcb->fDtrflow = 1;
1275 lpdcb->fRtsflow = 1;
1276 lpdcb->fOutxCtsFlow = 1;
1277 lpdcb->fOutxDsrFlow = 1;
1278 } else
1279 #endif
1280 lpdcb->fDtrDisable = 1;
1282 if (port.c_iflag & IXON)
1283 lpdcb->fInX = 1;
1284 else
1285 lpdcb->fInX = 0;
1287 if (port.c_iflag & IXOFF)
1288 lpdcb->fOutX = 1;
1289 else
1290 lpdcb->fOutX = 0;
1292 lpdcb->XonChar =
1293 lpdcb->XoffChar =
1295 lpdcb->XonLim = 10;
1296 lpdcb->XoffLim = 10;
1298 commerror = 0;
1299 return 0;
1302 /*****************************************************************************
1303 * GetCommState (KERNEL32.159)
1305 BOOL32 GetCommState32(INT32 fd, LPDCB32 lpdcb)
1307 struct termios port;
1310 dprintf_comm(stddeb,"GetCommState32: fd %d, ptr %p\n", fd, lpdcb);
1311 if (tcgetattr(fd, &port) == -1) {
1312 commerror = WinError();
1313 return FALSE;
1315 #ifdef CBAUD
1316 switch (port.c_cflag & CBAUD) {
1317 #else
1318 switch (port.c_ospeed) {
1319 #endif
1320 case B110:
1321 lpdcb->BaudRate = 110;
1322 break;
1323 case B300:
1324 lpdcb->BaudRate = 300;
1325 break;
1326 case B600:
1327 lpdcb->BaudRate = 600;
1328 break;
1329 case B1200:
1330 lpdcb->BaudRate = 1200;
1331 break;
1332 case B2400:
1333 lpdcb->BaudRate = 2400;
1334 break;
1335 case B4800:
1336 lpdcb->BaudRate = 4800;
1337 break;
1338 case B9600:
1339 lpdcb->BaudRate = 9600;
1340 break;
1341 case B19200:
1342 lpdcb->BaudRate = 19200;
1343 break;
1344 case B38400:
1345 lpdcb->BaudRate = 38400;
1346 break;
1349 switch (port.c_cflag & CSIZE) {
1350 case CS5:
1351 lpdcb->ByteSize = 5;
1352 break;
1353 case CS6:
1354 lpdcb->ByteSize = 6;
1355 break;
1356 case CS7:
1357 lpdcb->ByteSize = 7;
1358 break;
1359 case CS8:
1360 lpdcb->ByteSize = 8;
1361 break;
1364 switch (port.c_cflag & ~(PARENB | PARODD)) {
1365 case 0:
1366 lpdcb->fParity = NOPARITY;
1367 break;
1368 case PARENB:
1369 lpdcb->fParity = EVENPARITY;
1370 break;
1371 case (PARENB | PARODD):
1372 lpdcb->fParity = ODDPARITY;
1373 break;
1376 if (port.c_cflag & CSTOPB)
1377 lpdcb->StopBits = TWOSTOPBITS;
1378 else
1379 lpdcb->StopBits = ONESTOPBIT;
1381 lpdcb->fNull = 0;
1382 lpdcb->fBinary = 1;
1384 #ifdef CRTSCTS
1386 if (port.c_cflag & CRTSCTS) {
1387 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1388 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1389 lpdcb->fOutxCtsFlow = 1;
1390 lpdcb->fOutxDsrFlow = 1;
1391 } else
1392 #endif
1394 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1395 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1397 if (port.c_iflag & IXON)
1398 lpdcb->fInX = 1;
1399 else
1400 lpdcb->fInX = 0;
1402 if (port.c_iflag & IXOFF)
1403 lpdcb->fOutX = 1;
1404 else
1405 lpdcb->fOutX = 0;
1407 lpdcb->XonChar =
1408 lpdcb->XoffChar =
1410 lpdcb->XonLim = 10;
1411 lpdcb->XoffLim = 10;
1413 commerror = 0;
1414 return TRUE;
1417 /*****************************************************************************
1418 * TransmitCommChar (USER.206)
1420 INT16 TransmitCommChar16(INT16 fd,CHAR chTransmit)
1422 struct DosDeviceStruct *ptr;
1424 dprintf_comm(stddeb,
1425 "TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
1426 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1427 commerror = IE_BADID;
1428 return -1;
1431 if (ptr->suspended) {
1432 commerror = IE_HARDWARE;
1433 return -1;
1436 if (write(fd, (void *) &chTransmit, 1) == -1) {
1437 commerror = WinError();
1438 return -1;
1439 } else {
1440 commerror = 0;
1441 return 0;
1445 /*****************************************************************************
1446 * TransmitCommChar (KERNEL32.535)
1448 BOOL32 TransmitCommChar32(INT32 fd,CHAR chTransmit)
1450 struct DosDeviceStruct *ptr;
1452 dprintf_comm(stddeb,"TransmitCommChar32(%d,'%c')\n",fd,chTransmit);
1453 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1454 commerror = IE_BADID;
1455 return FALSE;
1458 if (ptr->suspended) {
1459 commerror = IE_HARDWARE;
1460 return FALSE;
1462 if (write(fd, (void *) &chTransmit, 1) == -1) {
1463 commerror = WinError();
1464 return FALSE;
1465 } else {
1466 commerror = 0;
1467 return TRUE;
1471 /*****************************************************************************
1472 * UngetCommChar (USER.212)
1474 INT16 UngetCommChar(INT16 fd,CHAR chUnget)
1476 struct DosDeviceStruct *ptr;
1478 dprintf_comm(stddeb,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
1479 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1480 commerror = IE_BADID;
1481 return -1;
1484 if (ptr->suspended) {
1485 commerror = IE_HARDWARE;
1486 return -1;
1489 ptr->unget = 1;
1490 ptr->unget_byte = chUnget;
1491 commerror = 0;
1492 return 0;
1495 /*****************************************************************************
1496 * ReadComm (USER.204)
1498 INT16 ReadComm(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1500 int status, length;
1501 struct DosDeviceStruct *ptr;
1503 dprintf_comm(stddeb,
1504 "ReadComm: fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1505 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1506 commerror = IE_BADID;
1507 return -1;
1510 if (ptr->suspended) {
1511 commerror = IE_HARDWARE;
1512 return -1;
1515 if (ptr->unget) {
1516 *lpvBuf = ptr->unget_byte;
1517 lpvBuf++;
1518 ptr->unget = 0;
1520 length = 1;
1521 } else
1522 length = 0;
1524 status = read(fd, (void *) lpvBuf, cbRead);
1526 if (status == -1) {
1527 if (errno != EAGAIN) {
1528 commerror = WinError();
1529 return -1 - length;
1530 } else {
1531 commerror = 0;
1532 return length;
1534 } else {
1535 commerror = 0;
1536 return length + status;
1540 /*****************************************************************************
1541 * WriteComm (USER.205)
1543 INT16 WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1545 int x, length;
1546 struct DosDeviceStruct *ptr;
1548 dprintf_comm(stddeb,"WriteComm: fd %d, ptr %p, length %d\n",
1549 fd, lpvBuf, cbWrite);
1550 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1551 commerror = IE_BADID;
1552 return -1;
1555 if (ptr->suspended) {
1556 commerror = IE_HARDWARE;
1557 return -1;
1560 for (x=0; x != cbWrite ; x++)
1561 dprintf_comm(stddeb,"%c", *(lpvBuf + x) );
1563 length = write(fd, (void *) lpvBuf, cbWrite);
1565 if (length == -1) {
1566 commerror = WinError();
1567 return -1;
1568 } else {
1569 commerror = 0;
1570 return length;
1575 /*****************************************************************************
1576 * GetCommTimeouts (KERNEL32.160)
1578 BOOL32 GetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
1579 dprintf_comm(stddeb,"GetCommTimeouts(%x,%p), empty stub.\n",
1580 fd,lptimeouts
1582 return TRUE;
1585 /*****************************************************************************
1586 * SetCommTimeouts (KERNEL32.453)
1588 BOOL32 SetCommTimeouts(INT32 fd,LPCOMMTIMEOUTS lptimeouts) {
1589 dprintf_comm(stddeb,"SetCommTimeouts(%x,%p), empty stub.\n",
1590 fd,lptimeouts
1592 return TRUE;