Release 960728
[wine/multimedia.git] / misc / comm.c
blobb628a2bd790088456940b674630dcc06a302cad3
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <termios.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <ctype.h>
14 #include <sys/stat.h>
15 #if defined(__NetBSD__) || defined(__FreeBSD__)
16 #include <sys/ioctl.h>
17 #endif
18 #include <unistd.h>
20 #include "windows.h"
21 #include "comm.h"
22 #include "options.h"
23 #include "stddebug.h"
24 #include "debug.h"
25 #include "handle32.h"
26 #include "string32.h"
28 int commerror = 0, eventmask = 0;
30 struct DosDeviceStruct COM[MAX_PORTS];
31 struct DosDeviceStruct LPT[MAX_PORTS];
33 void COMM_Init(void)
35 int x;
36 char option[10], temp[256], *btemp;
37 struct stat st;
39 for (x=0; x!=MAX_PORTS; x++) {
40 strcpy(option,"COMx");
41 option[3] = '1' + x;
42 option[4] = '\0';
44 PROFILE_GetWineIniString( "serialports", option, "*",
45 temp, sizeof(temp) );
46 if (!strcmp(temp, "*") || *temp == '\0')
47 COM[x].devicename = NULL;
48 else {
49 btemp = strchr(temp,',');
50 if (btemp != NULL) {
51 *btemp++ = '\0';
52 COM[x].baudrate = atoi(btemp);
53 } else {
54 COM[x].baudrate = -1;
56 stat(temp, &st);
57 if (!S_ISCHR(st.st_mode))
58 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
59 else
60 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
61 fprintf(stderr,"comm: can't malloc for device info!\n");
62 else {
63 COM[x].fd = 0;
64 strcpy(COM[x].devicename, temp);
66 dprintf_comm(stddeb,
67 "Comm_Init: %s = %s\n", option, COM[x].devicename);
70 strcpy(option, "LPTx");
71 option[3] = '1' + x;
72 option[4] = '\0';
74 PROFILE_GetWineIniString( "parallelports", option, "*",
75 temp, sizeof(temp) );
76 if (!strcmp(temp, "*") || *temp == '\0')
77 LPT[x].devicename = NULL;
78 else {
79 stat(temp, &st);
80 if (!S_ISCHR(st.st_mode))
81 fprintf(stderr,"comm: can't use `%s' as %s !\n", temp, option);
82 else
83 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
84 fprintf(stderr,"comm: can't malloc for device info!\n");
85 else {
86 LPT[x].fd = 0;
87 strcpy(LPT[x].devicename, temp);
89 dprintf_comm(stddeb,
90 "Comm_Init: %s = %s\n", option, LPT[x].devicename);
97 struct DosDeviceStruct *GetDeviceStruct(int fd)
99 int x;
101 for (x=0; x!=MAX_PORTS; x++) {
102 if (COM[x].fd == fd)
103 return &COM[x];
104 if (LPT[x].fd == fd)
105 return &LPT[x];
108 return NULL;
111 int ValidCOMPort(int x)
113 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
116 int ValidLPTPort(int x)
118 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
121 int WinError(void)
123 dprintf_comm(stddeb, "WinError: errno = %d\n", errno);
124 switch (errno) {
125 default:
126 return CE_IOE;
130 /**************************************************************************
131 * BuildCommDCB (USER.213)
133 BOOL16 BuildCommDCB16(LPCSTR device, LPDCB16 lpdcb)
135 /* "COM1:9600,n,8,1" */
136 /* 012345 */
137 int port;
138 char *ptr, temp[256];
140 dprintf_comm(stddeb,
141 "BuildCommDCB: (%s), ptr %p\n", device, lpdcb);
142 commerror = 0;
144 if (!lstrncmpi32A(device,"COM",3)) {
145 port = device[3] - '0';
148 if (port-- == 0) {
149 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
150 commerror = IE_BADID;
153 if (!ValidCOMPort(port)) {
154 commerror = IE_BADID;
155 return -1;
158 if (!COM[port].fd) {
159 OpenComm(device, 0, 0);
161 lpdcb->Id = COM[port].fd;
163 if (!*(device+4))
164 return 0;
166 if (*(device+4) != ':')
167 return -1;
169 strcpy(temp,device+5);
170 ptr = strtok(temp, ", ");
172 if (COM[port].baudrate > 0)
173 lpdcb->BaudRate = COM[port].baudrate;
174 else
175 lpdcb->BaudRate = atoi(ptr);
176 dprintf_comm(stddeb,"BuildCommDCB: baudrate (%d)\n", lpdcb->BaudRate);
178 ptr = strtok(NULL, ", ");
179 if (islower(*ptr))
180 *ptr = toupper(*ptr);
182 dprintf_comm(stddeb,"BuildCommDCB: parity (%c)\n", *ptr);
183 lpdcb->fParity = 1;
184 switch (*ptr) {
185 case 'N':
186 lpdcb->Parity = NOPARITY;
187 lpdcb->fParity = 0;
188 break;
189 case 'E':
190 lpdcb->Parity = EVENPARITY;
191 break;
192 case 'M':
193 lpdcb->Parity = MARKPARITY;
194 break;
195 case 'O':
196 lpdcb->Parity = ODDPARITY;
197 break;
198 default:
199 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
200 return -1;
203 ptr = strtok(NULL, ", ");
204 dprintf_comm(stddeb, "BuildCommDCB: charsize (%c)\n", *ptr);
205 lpdcb->ByteSize = *ptr - '0';
207 ptr = strtok(NULL, ", ");
208 dprintf_comm(stddeb, "BuildCommDCB: stopbits (%c)\n", *ptr);
209 switch (*ptr) {
210 case '1':
211 lpdcb->StopBits = ONESTOPBIT;
212 break;
213 case '2':
214 lpdcb->StopBits = TWOSTOPBITS;
215 break;
216 default:
217 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
218 return -1;
222 return 0;
225 /**************************************************************************
226 * BuildCommDCBA (KERNEL32.14)
228 BOOL32 BuildCommDCB32A(LPCSTR device,LPDCB32 lpdcb) {
229 return BuildCommDCBAndTimeouts32A(device,lpdcb,NULL);
232 /**************************************************************************
233 * BuildCommDCBAndTimeoutsA (KERNEL32.15)
235 BOOL32 BuildCommDCBAndTimeouts32A(LPCSTR device, LPDCB32 lpdcb,LPCOMMTIMEOUTS lptimeouts) {
236 int port;
237 char *ptr,*temp;
239 dprintf_comm(stddeb,"BuildCommDCBAndTimeouts32A(%s,%p,%p)\n",device,lpdcb,lptimeouts);
240 commerror = 0;
242 if (!lstrncmpi32A(device,"COM",3)) {
243 port=device[3]-'0';
244 if (port--==0) {
245 fprintf(stderr,"comm:BUG! COM0 can't exists!.\n");
246 return FALSE;
248 if (!ValidCOMPort(port))
249 return FALSE;
250 if (*(device+4)!=':')
251 return FALSE;
252 temp=(LPSTR)(device+5);
253 } else
254 temp=(LPSTR)device;
255 lpdcb->DCBlength = sizeof(DCB32);
256 if (strchr(temp,',')) { /* old style */
257 DCB16 dcb16;
258 BOOL16 ret;
259 char last=temp[strlen(temp)-1];
261 ret=BuildCommDCB16(device,&dcb16);
262 if (!ret)
263 return FALSE;
264 lpdcb->BaudRate = dcb16.BaudRate;
265 lpdcb->ByteSize = dcb16.ByteSize;
266 lpdcb->fBinary = dcb16.fBinary;
267 lpdcb->Parity = dcb16.Parity;
268 lpdcb->fParity = dcb16.fParity;
269 lpdcb->fNull = dcb16.fNull;
270 lpdcb->StopBits = dcb16.StopBits;
271 if (last == 'x') {
272 lpdcb->fInX = TRUE;
273 lpdcb->fOutX = TRUE;
274 lpdcb->fOutxCtsFlow = FALSE;
275 lpdcb->fOutxDsrFlow = FALSE;
276 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
277 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
278 } else if (last=='p') {
279 lpdcb->fInX = FALSE;
280 lpdcb->fOutX = FALSE;
281 lpdcb->fOutxCtsFlow = TRUE;
282 lpdcb->fOutxDsrFlow = TRUE;
283 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
284 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
285 } else {
286 lpdcb->fInX = FALSE;
287 lpdcb->fOutX = FALSE;
288 lpdcb->fOutxCtsFlow = FALSE;
289 lpdcb->fOutxDsrFlow = FALSE;
290 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
291 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
293 lpdcb->XonChar = dcb16.XonChar;
294 lpdcb->XoffChar = dcb16.XoffChar;
295 lpdcb->ErrorChar= dcb16.PeChar;
296 lpdcb->fErrorChar= dcb16.fPeChar;
297 lpdcb->EofChar = dcb16.EofChar;
298 lpdcb->EvtChar = dcb16.EvtChar;
299 lpdcb->XonLim = dcb16.XonLim;
300 lpdcb->XoffLim = dcb16.XoffLim;
301 return TRUE;
303 ptr=strtok(temp," ");
304 while (ptr) {
305 DWORD flag,x;
307 flag=0;
308 if (!strncmp("baud=",ptr,5)) {
309 if (!sscanf(ptr+5,"%ld",&x))
310 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
311 lpdcb->BaudRate = x;
312 flag=1;
314 if (!strncmp("stop=",ptr,5)) {
315 if (!sscanf(ptr+5,"%ld",&x))
316 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
317 lpdcb->StopBits = x;
318 flag=1;
320 if (!strncmp("data=",ptr,5)) {
321 if (!sscanf(ptr+5,"%ld",&x))
322 fprintf(stderr,"BuildCommDCB32A:Couldn't parse %s\n",ptr);
323 lpdcb->ByteSize = x;
324 flag=1;
326 if (!strncmp("parity=",ptr,7)) {
327 lpdcb->fParity = TRUE;
328 switch (ptr[8]) {
329 case 'N':case 'n':
330 lpdcb->fParity = FALSE;
331 lpdcb->Parity = NOPARITY;
332 break;
333 case 'E':case 'e':
334 lpdcb->Parity = EVENPARITY;
335 break;
336 case 'O':case 'o':
337 lpdcb->Parity = ODDPARITY;
338 break;
339 case 'M':case 'm':
340 lpdcb->Parity = MARKPARITY;
341 break;
343 flag=1;
345 if (!flag)
346 fprintf(stderr,"BuildCommDCB32A: Unhandled specifier '%s', please report.\n",ptr);
347 ptr=strtok(NULL," ");
349 if (lpdcb->BaudRate==110)
350 lpdcb->StopBits = 2;
351 return TRUE;
354 /**************************************************************************
355 * BuildCommDCBAndTimeoutsW (KERNEL32.16)
357 BOOL32 BuildCommDCBAndTimeouts32W(
358 LPCWSTR devid,LPDCB32 lpdcb,LPCOMMTIMEOUTS lptimeouts
360 LPSTR devidA;
361 BOOL32 ret;
363 dprintf_comm(stddeb,"BuildCommDCBAndTimeouts32W(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
364 devidA = STRING32_DupUniToAnsi(devid);
365 ret=BuildCommDCBAndTimeouts32A(devidA,lpdcb,lptimeouts);
366 free(devidA);
367 return ret;
370 /**************************************************************************
371 * BuildCommDCBW (KERNEL32.17)
373 BOOL32 BuildCommDCB32W(LPCWSTR devid,LPDCB32 lpdcb) {
374 return BuildCommDCBAndTimeouts32W(devid,lpdcb,NULL);
377 /*****************************************************************************
378 * OpenComm (USER.200)
380 INT16 OpenComm(LPCSTR device,UINT16 cbInQueue,UINT16 cbOutQueue)
382 int port, fd;
384 dprintf_comm(stddeb,
385 "OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
386 commerror = 0;
388 if (!lstrncmpi32A(device,"COM",3)) {
389 port = device[3] - '0';
391 if (port-- == 0) {
392 fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n");
393 commerror = IE_BADID;
396 dprintf_comm(stddeb,
397 "OpenComm: %s = %s\n", device, COM[port].devicename);
399 if (!ValidCOMPort(port)) {
400 commerror = IE_BADID;
401 return -1;
403 if (COM[port].fd) {
404 return COM[port].fd;
407 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
408 if (fd == -1) {
409 commerror = WinError();
410 return -1;
411 } else {
412 COM[port].fd = fd;
413 return fd;
416 else
417 if (!lstrncmpi32A(device,"LPT",3)) {
418 port = device[3] - '0';
420 if (!ValidLPTPort(port)) {
421 commerror = IE_BADID;
422 return -1;
424 if (LPT[port].fd) {
425 commerror = IE_OPEN;
426 return -1;
429 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
430 if (fd == -1) {
431 commerror = WinError();
432 return -1;
433 } else {
434 LPT[port].fd = fd;
435 return fd;
438 return 0;
441 /*****************************************************************************
442 * CloseComm (USER.207)
444 INT16 CloseComm(INT16 fd)
446 dprintf_comm(stddeb,"CloseComm: fd %d\n", fd);
447 if (close(fd) == -1) {
448 commerror = WinError();
449 return -1;
450 } else {
451 commerror = 0;
452 return 0;
456 /*****************************************************************************
457 * SetCommBreak (USER.210)
459 INT16 SetCommBreak16(INT16 fd)
461 struct DosDeviceStruct *ptr;
463 dprintf_comm(stddeb,"SetCommBreak: fd: %d\n", fd);
464 if ((ptr = GetDeviceStruct(fd)) == NULL) {
465 commerror = IE_BADID;
466 return -1;
469 ptr->suspended = 1;
470 commerror = 0;
471 return 0;
474 /*****************************************************************************
475 * SetCommBreak (KERNEL32.449)
477 BOOL32 SetCommBreak32(HANDLE32 hfile)
479 FILE_OBJECT *fob = (FILE_OBJECT*)hfile;
480 int fd = fob->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(HANDLE32 hfile)
518 FILE_OBJECT *fob = (FILE_OBJECT*)hfile;
519 int fd = fob->fd;
520 struct DosDeviceStruct *ptr;
522 dprintf_comm(stddeb,"ClearCommBreak: fd: %d\n", fd);
523 if ((ptr = GetDeviceStruct(fd)) == NULL) {
524 commerror = IE_BADID;
525 return FALSE;
528 ptr->suspended = 0;
529 commerror = 0;
530 return TRUE;
533 /*****************************************************************************
534 * EscapeCommFunction (USER.214)
536 LONG EscapeCommFunction16(UINT16 fd,UINT16 nFunction)
538 int max;
539 struct termios port;
541 dprintf_comm(stddeb,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
542 if (tcgetattr(fd,&port) == -1) {
543 commerror=WinError();
544 return -1;
547 switch (nFunction) {
548 case RESETDEV:
549 break;
551 case GETMAXCOM:
552 for (max = MAX_PORTS;!COM[max].devicename;max--)
554 return max;
555 break;
557 case GETMAXLPT:
558 for (max = MAX_PORTS;!LPT[max].devicename;max--)
560 return 0x80 + max;
561 break;
563 #ifdef TIOCM_DTR
564 case CLRDTR:
565 port.c_cflag &= TIOCM_DTR;
566 break;
567 #endif
569 #ifdef TIOCM_RTS
570 case CLRRTS:
571 port.c_cflag &= TIOCM_RTS;
572 break;
573 #endif
575 #ifdef CRTSCTS
576 case SETDTR:
577 port.c_cflag |= CRTSCTS;
578 break;
580 case SETRTS:
581 port.c_cflag |= CRTSCTS;
582 break;
583 #endif
585 case SETXOFF:
586 port.c_iflag |= IXOFF;
587 break;
589 case SETXON:
590 port.c_iflag |= IXON;
591 break;
593 default:
594 fprintf(stderr,
595 "EscapeCommFunction fd: %d, unknown function: %d\n",
596 fd, nFunction);
597 break;
600 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
601 commerror = WinError();
602 return -1;
603 } else {
604 commerror = 0;
605 return 0;
609 /*****************************************************************************
610 * EscapeCommFunction (KERNEL32.214)
612 BOOL32 EscapeCommFunction32(HANDLE32 hfile,UINT32 nFunction)
614 FILE_OBJECT *fob = (FILE_OBJECT*)hfile;
615 int fd = fob->fd;
616 struct termios port;
617 struct DosDeviceStruct *ptr;
619 dprintf_comm(stddeb,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
620 if (tcgetattr(fd,&port) == -1) {
621 commerror=WinError();
622 return FALSE;
624 if ((ptr = GetDeviceStruct(fd)) == NULL) {
625 commerror = IE_BADID;
626 return FALSE;
629 switch (nFunction) {
630 case RESETDEV:
631 break;
633 #ifdef TIOCM_DTR
634 case CLRDTR:
635 port.c_cflag &= TIOCM_DTR;
636 break;
637 #endif
639 #ifdef TIOCM_RTS
640 case CLRRTS:
641 port.c_cflag &= TIOCM_RTS;
642 break;
643 #endif
645 #ifdef CRTSCTS
646 case SETDTR:
647 port.c_cflag |= CRTSCTS;
648 break;
650 case SETRTS:
651 port.c_cflag |= CRTSCTS;
652 break;
653 #endif
655 case SETXOFF:
656 port.c_iflag |= IXOFF;
657 break;
659 case SETXON:
660 port.c_iflag |= IXON;
661 break;
662 case SETBREAK:
663 ptr->suspended = 1;
664 break;
665 case CLRBREAK:
666 ptr->suspended = 0;
667 break;
668 default:
669 fprintf(stderr,
670 "EscapeCommFunction32 fd: %d, unknown function: %d\n",
671 fd, nFunction);
672 break;
675 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
676 commerror = WinError();
677 return FALSE;
678 } else {
679 commerror = 0;
680 return TRUE;
684 /*****************************************************************************
685 * FlushComm (USER.215)
687 INT16 FlushComm(INT16 fd,INT16 fnQueue)
689 int queue;
691 dprintf_comm(stddeb,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
692 switch (fnQueue) {
693 case 0: queue = TCOFLUSH;
694 break;
695 case 1: queue = TCIFLUSH;
696 break;
697 default:fprintf(stderr,
698 "FlushComm fd: %d, UNKNOWN queue: %d\n",
699 fd, fnQueue);
700 return -1;
702 if (tcflush(fd, fnQueue)) {
703 commerror = WinError();
704 return -1;
705 } else {
706 commerror = 0;
707 return 0;
711 /*****************************************************************************
712 * GetCommError (USER.203)
714 INT16 GetCommError(INT16 fd,LPCOMSTAT lpStat)
716 int temperror;
718 dprintf_comm(stddeb,
719 "GetCommError: fd %d (current error %d)\n", fd, commerror);
720 temperror = commerror;
721 commerror = 0;
722 return(temperror);
725 /*****************************************************************************
726 * ClearCommError (KERNEL32.21)
728 BOOL32 ClearCommError(HANDLE32 hfile,LPDWORD errors,LPCOMSTAT lpStat)
730 int temperror;
731 FILE_OBJECT *fob=(FILE_OBJECT*)hfile;
732 int fd = fob->fd;
734 dprintf_comm(stddeb,
735 "ClearCommError: fd %d (current error %d)\n", fd, commerror);
736 temperror = commerror;
737 commerror = 0;
738 return TRUE;
741 /*****************************************************************************
742 * SetCommEventMask (USER.208)
744 UINT16 *SetCommEventMask(INT16 fd,UINT16 fuEvtMask)
746 dprintf_comm(stddeb,"SetCommEventMask:fd %d,mask %d\n",fd,fuEvtMask);
747 eventmask |= fuEvtMask;
748 return (UINT *)&eventmask; /* FIXME, should be SEGPTR */
751 /*****************************************************************************
752 * GetCommEventMask (USER.209)
754 UINT16 GetCommEventMask(INT16 fd,UINT16 fnEvtClear)
756 dprintf_comm(stddeb,
757 "GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
758 eventmask &= ~fnEvtClear;
759 return eventmask;
762 /*****************************************************************************
763 * GetCommMask (KERNEL32.156)
765 BOOL32 GetCommMask(HANDLE32 hfile,LPDWORD evtmask)
767 FILE_OBJECT *fob=(FILE_OBJECT*)hfile;
768 int fd = fob->fd;
770 dprintf_comm(stddeb,
771 "GetCommMask: fd %d, mask %p\n", fd, evtmask);
772 *evtmask = eventmask;
773 return TRUE;
776 /*****************************************************************************
777 * SetCommMask (KERNEL32.451)
779 BOOL32 SetCommMask(HANDLE32 hfile,DWORD evtmask)
781 FILE_OBJECT *fob=(FILE_OBJECT*)hfile;
782 int fd = fob->fd;
784 dprintf_comm(stddeb,
785 "SetCommMask: fd %d, mask %lx\n", fd, evtmask);
786 eventmask = evtmask;
787 return TRUE;
790 /*****************************************************************************
791 * SetCommState16 (USER.201)
793 INT16 SetCommState16(LPDCB16 lpdcb)
795 struct termios port;
796 struct DosDeviceStruct *ptr;
798 dprintf_comm(stddeb,
799 "SetCommState: fd %d, ptr %p\n", lpdcb->Id, lpdcb);
800 if (tcgetattr(lpdcb->Id, &port) == -1) {
801 commerror = WinError();
802 return -1;
805 port.c_cc[VMIN] = 0;
806 port.c_cc[VTIME] = 1;
808 #ifdef IMAXBEL
809 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
810 #else
811 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
812 #endif
813 port.c_iflag |= (IGNBRK);
815 port.c_oflag &= ~(OPOST);
817 port.c_cflag &= ~(HUPCL);
818 port.c_cflag |= CLOCAL | CREAD;
820 port.c_lflag &= ~(ICANON|ECHO|ISIG);
821 port.c_lflag |= NOFLSH;
823 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
824 commerror = IE_BADID;
825 return -1;
827 if (ptr->baudrate > 0)
828 lpdcb->BaudRate = ptr->baudrate;
829 dprintf_comm(stddeb,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
830 #ifdef CBAUD
831 port.c_cflag &= ~CBAUD;
832 switch (lpdcb->BaudRate) {
833 case 110:
834 case CBR_110:
835 port.c_cflag |= B110;
836 break;
837 case 300:
838 case CBR_300:
839 port.c_cflag |= B300;
840 break;
841 case 600:
842 case CBR_600:
843 port.c_cflag |= B600;
844 break;
845 case 1200:
846 case CBR_1200:
847 port.c_cflag |= B1200;
848 break;
849 case 2400:
850 case CBR_2400:
851 port.c_cflag |= B2400;
852 break;
853 case 4800:
854 case CBR_4800:
855 port.c_cflag |= B4800;
856 break;
857 case 9600:
858 case CBR_9600:
859 port.c_cflag |= B9600;
860 break;
861 case 19200:
862 case CBR_19200:
863 port.c_cflag |= B19200;
864 break;
865 case 38400:
866 case CBR_38400:
867 port.c_cflag |= B38400;
868 break;
869 default:
870 commerror = IE_BAUDRATE;
871 return -1;
873 #else
874 switch (lpdcb->BaudRate) {
875 case 110:
876 case CBR_110:
877 port.c_ospeed = B110;
878 break;
879 case 300:
880 case CBR_300:
881 port.c_ospeed = B300;
882 break;
883 case 600:
884 case CBR_600:
885 port.c_ospeed = B600;
886 break;
887 case 1200:
888 case CBR_1200:
889 port.c_ospeed = B1200;
890 break;
891 case 2400:
892 case CBR_2400:
893 port.c_ospeed = B2400;
894 break;
895 case 4800:
896 case CBR_4800:
897 port.c_ospeed = B4800;
898 break;
899 case 9600:
900 case CBR_9600:
901 port.c_ospeed = B9600;
902 break;
903 case 19200:
904 case CBR_19200:
905 port.c_ospeed = B19200;
906 break;
907 case 38400:
908 case CBR_38400:
909 port.c_ospeed = B38400;
910 break;
911 default:
912 commerror = IE_BAUDRATE;
913 return -1;
915 port.c_ispeed = port.c_ospeed;
916 #endif
917 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
918 port.c_cflag &= ~CSIZE;
919 switch (lpdcb->ByteSize) {
920 case 5:
921 port.c_cflag |= CS5;
922 break;
923 case 6:
924 port.c_cflag |= CS6;
925 break;
926 case 7:
927 port.c_cflag |= CS7;
928 break;
929 case 8:
930 port.c_cflag |= CS8;
931 break;
932 default:
933 commerror = IE_BYTESIZE;
934 return -1;
937 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
938 port.c_cflag &= ~(PARENB | PARODD);
939 if (lpdcb->fParity)
940 switch (lpdcb->Parity) {
941 case NOPARITY:
942 port.c_iflag &= ~INPCK;
943 break;
944 case ODDPARITY:
945 port.c_cflag |= (PARENB | PARODD);
946 port.c_iflag |= INPCK;
947 break;
948 case EVENPARITY:
949 port.c_cflag |= PARENB;
950 port.c_iflag |= INPCK;
951 break;
952 default:
953 commerror = IE_BYTESIZE;
954 return -1;
958 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
959 switch (lpdcb->StopBits) {
960 case ONESTOPBIT:
961 port.c_cflag &= ~CSTOPB;
962 break;
963 case TWOSTOPBITS:
964 port.c_cflag |= CSTOPB;
965 break;
966 default:
967 commerror = IE_BYTESIZE;
968 return -1;
970 #ifdef CRTSCTS
972 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
973 port.c_cflag |= CRTSCTS;
975 if (lpdcb->fDtrDisable)
976 port.c_cflag &= ~CRTSCTS;
977 #endif
978 if (lpdcb->fInX)
979 port.c_iflag |= IXON;
980 if (lpdcb->fOutX)
981 port.c_iflag |= IXOFF;
983 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
984 commerror = WinError();
985 return -1;
986 } else {
987 commerror = 0;
988 return 0;
992 /*****************************************************************************
993 * SetCommState32 (KERNEL32.452)
995 BOOL32 SetCommState32(HANDLE32 hfile,LPDCB32 lpdcb)
997 FILE_OBJECT *fob = (FILE_OBJECT*)hfile;
998 int fd = fob->fd;
999 struct termios port;
1000 struct DosDeviceStruct *ptr;
1002 dprintf_comm(stddeb,"SetCommState: fd %d, ptr %p\n",fd,lpdcb);
1003 if (tcgetattr(fd,&port) == -1) {
1004 commerror = WinError();
1005 return FALSE;
1008 port.c_cc[VMIN] = 0;
1009 port.c_cc[VTIME] = 1;
1011 #ifdef IMAXBEL
1012 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1013 #else
1014 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1015 #endif
1016 port.c_iflag |= (IGNBRK);
1018 port.c_oflag &= ~(OPOST);
1020 port.c_cflag &= ~(HUPCL);
1021 port.c_cflag |= CLOCAL | CREAD;
1023 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1024 port.c_lflag |= NOFLSH;
1026 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1027 commerror = IE_BADID;
1028 return FALSE;
1030 if (ptr->baudrate > 0)
1031 lpdcb->BaudRate = ptr->baudrate;
1032 dprintf_comm(stddeb,"SetCommState: baudrate %ld\n",lpdcb->BaudRate);
1033 #ifdef CBAUD
1034 port.c_cflag &= ~CBAUD;
1035 switch (lpdcb->BaudRate) {
1036 case 110:
1037 case CBR_110:
1038 port.c_cflag |= B110;
1039 break;
1040 case 300:
1041 case CBR_300:
1042 port.c_cflag |= B300;
1043 break;
1044 case 600:
1045 case CBR_600:
1046 port.c_cflag |= B600;
1047 break;
1048 case 1200:
1049 case CBR_1200:
1050 port.c_cflag |= B1200;
1051 break;
1052 case 2400:
1053 case CBR_2400:
1054 port.c_cflag |= B2400;
1055 break;
1056 case 4800:
1057 case CBR_4800:
1058 port.c_cflag |= B4800;
1059 break;
1060 case 9600:
1061 case CBR_9600:
1062 port.c_cflag |= B9600;
1063 break;
1064 case 19200:
1065 case CBR_19200:
1066 port.c_cflag |= B19200;
1067 break;
1068 case 38400:
1069 case CBR_38400:
1070 port.c_cflag |= B38400;
1071 break;
1072 default:
1073 commerror = IE_BAUDRATE;
1074 return FALSE;
1076 #else
1077 switch (lpdcb->BaudRate) {
1078 case 110:
1079 case CBR_110:
1080 port.c_ospeed = B110;
1081 break;
1082 case 300:
1083 case CBR_300:
1084 port.c_ospeed = B300;
1085 break;
1086 case 600:
1087 case CBR_600:
1088 port.c_ospeed = B600;
1089 break;
1090 case 1200:
1091 case CBR_1200:
1092 port.c_ospeed = B1200;
1093 break;
1094 case 2400:
1095 case CBR_2400:
1096 port.c_ospeed = B2400;
1097 break;
1098 case 4800:
1099 case CBR_4800:
1100 port.c_ospeed = B4800;
1101 break;
1102 case 9600:
1103 case CBR_9600:
1104 port.c_ospeed = B9600;
1105 break;
1106 case 19200:
1107 case CBR_19200:
1108 port.c_ospeed = B19200;
1109 break;
1110 case 38400:
1111 case CBR_38400:
1112 port.c_ospeed = B38400;
1113 break;
1114 default:
1115 commerror = IE_BAUDRATE;
1116 return FALSE;
1118 port.c_ispeed = port.c_ospeed;
1119 #endif
1120 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
1121 port.c_cflag &= ~CSIZE;
1122 switch (lpdcb->ByteSize) {
1123 case 5:
1124 port.c_cflag |= CS5;
1125 break;
1126 case 6:
1127 port.c_cflag |= CS6;
1128 break;
1129 case 7:
1130 port.c_cflag |= CS7;
1131 break;
1132 case 8:
1133 port.c_cflag |= CS8;
1134 break;
1135 default:
1136 commerror = IE_BYTESIZE;
1137 return FALSE;
1140 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
1141 port.c_cflag &= ~(PARENB | PARODD);
1142 if (lpdcb->fParity)
1143 switch (lpdcb->Parity) {
1144 case NOPARITY:
1145 port.c_iflag &= ~INPCK;
1146 break;
1147 case ODDPARITY:
1148 port.c_cflag |= (PARENB | PARODD);
1149 port.c_iflag |= INPCK;
1150 break;
1151 case EVENPARITY:
1152 port.c_cflag |= PARENB;
1153 port.c_iflag |= INPCK;
1154 break;
1155 default:
1156 commerror = IE_BYTESIZE;
1157 return FALSE;
1161 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
1162 switch (lpdcb->StopBits) {
1163 case ONESTOPBIT:
1164 port.c_cflag &= ~CSTOPB;
1165 break;
1166 case TWOSTOPBITS:
1167 port.c_cflag |= CSTOPB;
1168 break;
1169 default:
1170 commerror = IE_BYTESIZE;
1171 return FALSE;
1173 #ifdef CRTSCTS
1174 if ( lpdcb->fOutxCtsFlow ||
1175 lpdcb->fDtrControl == DTR_CONTROL_ENABLE||
1176 lpdcb->fRtsControl == RTS_CONTROL_ENABLE
1178 port.c_cflag |= CRTSCTS;
1179 if (lpdcb->fDtrControl == DTR_CONTROL_DISABLE)
1180 port.c_cflag &= ~CRTSCTS;
1182 #endif
1183 if (lpdcb->fInX)
1184 port.c_iflag |= IXON;
1185 if (lpdcb->fOutX)
1186 port.c_iflag |= IXOFF;
1188 if (tcsetattr(fd,TCSADRAIN,&port)==-1) {
1189 commerror = WinError();
1190 return FALSE;
1191 } else {
1192 commerror = 0;
1193 return TRUE;
1198 /*****************************************************************************
1199 * GetCommState (USER.202)
1201 INT16 GetCommState16(INT16 fd, LPDCB16 lpdcb)
1203 struct termios port;
1205 dprintf_comm(stddeb,"GetCommState: fd %d, ptr %p\n", fd, lpdcb);
1206 if (tcgetattr(fd, &port) == -1) {
1207 commerror = WinError();
1208 return -1;
1210 lpdcb->Id = fd;
1211 #ifdef CBAUD
1212 switch (port.c_cflag & CBAUD) {
1213 #else
1214 switch (port.c_ospeed) {
1215 #endif
1216 case B110:
1217 lpdcb->BaudRate = 110;
1218 break;
1219 case B300:
1220 lpdcb->BaudRate = 300;
1221 break;
1222 case B600:
1223 lpdcb->BaudRate = 600;
1224 break;
1225 case B1200:
1226 lpdcb->BaudRate = 1200;
1227 break;
1228 case B2400:
1229 lpdcb->BaudRate = 2400;
1230 break;
1231 case B4800:
1232 lpdcb->BaudRate = 4800;
1233 break;
1234 case B9600:
1235 lpdcb->BaudRate = 9600;
1236 break;
1237 case B19200:
1238 lpdcb->BaudRate = 19200;
1239 break;
1240 case B38400:
1241 lpdcb->BaudRate = 38400;
1242 break;
1245 switch (port.c_cflag & CSIZE) {
1246 case CS5:
1247 lpdcb->ByteSize = 5;
1248 break;
1249 case CS6:
1250 lpdcb->ByteSize = 6;
1251 break;
1252 case CS7:
1253 lpdcb->ByteSize = 7;
1254 break;
1255 case CS8:
1256 lpdcb->ByteSize = 8;
1257 break;
1260 switch (port.c_cflag & ~(PARENB | PARODD)) {
1261 case 0:
1262 lpdcb->fParity = NOPARITY;
1263 break;
1264 case PARENB:
1265 lpdcb->fParity = EVENPARITY;
1266 break;
1267 case (PARENB | PARODD):
1268 lpdcb->fParity = ODDPARITY;
1269 break;
1272 if (port.c_cflag & CSTOPB)
1273 lpdcb->StopBits = TWOSTOPBITS;
1274 else
1275 lpdcb->StopBits = ONESTOPBIT;
1277 lpdcb->RlsTimeout = 50;
1278 lpdcb->CtsTimeout = 50;
1279 lpdcb->DsrTimeout = 50;
1280 lpdcb->fNull = 0;
1281 lpdcb->fChEvt = 0;
1282 lpdcb->fBinary = 1;
1283 lpdcb->fDtrDisable = 0;
1285 #ifdef CRTSCTS
1287 if (port.c_cflag & CRTSCTS) {
1288 lpdcb->fDtrflow = 1;
1289 lpdcb->fRtsflow = 1;
1290 lpdcb->fOutxCtsFlow = 1;
1291 lpdcb->fOutxDsrFlow = 1;
1292 } else
1293 #endif
1294 lpdcb->fDtrDisable = 1;
1296 if (port.c_iflag & IXON)
1297 lpdcb->fInX = 1;
1298 else
1299 lpdcb->fInX = 0;
1301 if (port.c_iflag & IXOFF)
1302 lpdcb->fOutX = 1;
1303 else
1304 lpdcb->fOutX = 0;
1306 lpdcb->XonChar =
1307 lpdcb->XoffChar =
1309 lpdcb->XonLim = 10;
1310 lpdcb->XoffLim = 10;
1312 commerror = 0;
1313 return 0;
1316 /*****************************************************************************
1317 * GetCommState (KERNEL32.159)
1319 BOOL32 GetCommState32(HANDLE32 hfile, LPDCB32 lpdcb)
1321 FILE_OBJECT *fob = (FILE_OBJECT*)hfile;
1322 int fd = fob->fd;
1323 struct termios port;
1326 dprintf_comm(stddeb,"GetCommState32: fd %d, ptr %p\n", fd, lpdcb);
1327 if (tcgetattr(fd, &port) == -1) {
1328 commerror = WinError();
1329 return FALSE;
1331 #ifdef CBAUD
1332 switch (port.c_cflag & CBAUD) {
1333 #else
1334 switch (port.c_ospeed) {
1335 #endif
1336 case B110:
1337 lpdcb->BaudRate = 110;
1338 break;
1339 case B300:
1340 lpdcb->BaudRate = 300;
1341 break;
1342 case B600:
1343 lpdcb->BaudRate = 600;
1344 break;
1345 case B1200:
1346 lpdcb->BaudRate = 1200;
1347 break;
1348 case B2400:
1349 lpdcb->BaudRate = 2400;
1350 break;
1351 case B4800:
1352 lpdcb->BaudRate = 4800;
1353 break;
1354 case B9600:
1355 lpdcb->BaudRate = 9600;
1356 break;
1357 case B19200:
1358 lpdcb->BaudRate = 19200;
1359 break;
1360 case B38400:
1361 lpdcb->BaudRate = 38400;
1362 break;
1365 switch (port.c_cflag & CSIZE) {
1366 case CS5:
1367 lpdcb->ByteSize = 5;
1368 break;
1369 case CS6:
1370 lpdcb->ByteSize = 6;
1371 break;
1372 case CS7:
1373 lpdcb->ByteSize = 7;
1374 break;
1375 case CS8:
1376 lpdcb->ByteSize = 8;
1377 break;
1380 switch (port.c_cflag & ~(PARENB | PARODD)) {
1381 case 0:
1382 lpdcb->fParity = NOPARITY;
1383 break;
1384 case PARENB:
1385 lpdcb->fParity = EVENPARITY;
1386 break;
1387 case (PARENB | PARODD):
1388 lpdcb->fParity = ODDPARITY;
1389 break;
1392 if (port.c_cflag & CSTOPB)
1393 lpdcb->StopBits = TWOSTOPBITS;
1394 else
1395 lpdcb->StopBits = ONESTOPBIT;
1397 lpdcb->fNull = 0;
1398 lpdcb->fBinary = 1;
1400 #ifdef CRTSCTS
1402 if (port.c_cflag & CRTSCTS) {
1403 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1404 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1405 lpdcb->fOutxCtsFlow = 1;
1406 lpdcb->fOutxDsrFlow = 1;
1407 } else
1408 #endif
1410 lpdcb->fDtrControl = DTR_CONTROL_DISABLE;
1411 lpdcb->fRtsControl = RTS_CONTROL_DISABLE;
1413 if (port.c_iflag & IXON)
1414 lpdcb->fInX = 1;
1415 else
1416 lpdcb->fInX = 0;
1418 if (port.c_iflag & IXOFF)
1419 lpdcb->fOutX = 1;
1420 else
1421 lpdcb->fOutX = 0;
1423 lpdcb->XonChar =
1424 lpdcb->XoffChar =
1426 lpdcb->XonLim = 10;
1427 lpdcb->XoffLim = 10;
1429 commerror = 0;
1430 return TRUE;
1433 /*****************************************************************************
1434 * TransmitCommChar (USER.206)
1436 INT16 TransmitCommChar16(INT16 fd,CHAR chTransmit)
1438 struct DosDeviceStruct *ptr;
1440 dprintf_comm(stddeb,
1441 "TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
1442 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1443 commerror = IE_BADID;
1444 return -1;
1447 if (ptr->suspended) {
1448 commerror = IE_HARDWARE;
1449 return -1;
1452 if (write(fd, (void *) &chTransmit, 1) == -1) {
1453 commerror = WinError();
1454 return -1;
1455 } else {
1456 commerror = 0;
1457 return 0;
1461 /*****************************************************************************
1462 * TransmitCommChar (KERNEL32.535)
1464 BOOL32 TransmitCommChar32(HANDLE32 hfile,CHAR chTransmit)
1466 FILE_OBJECT *fob = (FILE_OBJECT*)hfile;
1467 int fd = fob->fd;
1468 struct DosDeviceStruct *ptr;
1470 dprintf_comm(stddeb,"TransmitCommChar32(%d,'%c')\n",fd,chTransmit);
1471 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1472 commerror = IE_BADID;
1473 return FALSE;
1476 if (ptr->suspended) {
1477 commerror = IE_HARDWARE;
1478 return FALSE;
1480 if (write(fd, (void *) &chTransmit, 1) == -1) {
1481 commerror = WinError();
1482 return FALSE;
1483 } else {
1484 commerror = 0;
1485 return TRUE;
1489 /*****************************************************************************
1490 * UngetCommChar (USER.212)
1492 INT16 UngetCommChar(INT16 fd,CHAR chUnget)
1494 struct DosDeviceStruct *ptr;
1496 dprintf_comm(stddeb,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
1497 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1498 commerror = IE_BADID;
1499 return -1;
1502 if (ptr->suspended) {
1503 commerror = IE_HARDWARE;
1504 return -1;
1507 ptr->unget = 1;
1508 ptr->unget_byte = chUnget;
1509 commerror = 0;
1510 return 0;
1513 /*****************************************************************************
1514 * ReadComm (USER.204)
1516 INT16 ReadComm(INT16 fd,LPSTR lpvBuf,INT16 cbRead)
1518 int status, length;
1519 struct DosDeviceStruct *ptr;
1521 dprintf_comm(stddeb,
1522 "ReadComm: fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
1523 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1524 commerror = IE_BADID;
1525 return -1;
1528 if (ptr->suspended) {
1529 commerror = IE_HARDWARE;
1530 return -1;
1533 if (ptr->unget) {
1534 *lpvBuf = ptr->unget_byte;
1535 lpvBuf++;
1536 ptr->unget = 0;
1538 length = 1;
1539 } else
1540 length = 0;
1542 status = read(fd, (void *) lpvBuf, cbRead);
1544 if (status == -1) {
1545 if (errno != EAGAIN) {
1546 commerror = WinError();
1547 return -1 - length;
1548 } else {
1549 commerror = 0;
1550 return length;
1552 } else {
1553 commerror = 0;
1554 return length + status;
1558 /*****************************************************************************
1559 * WriteComm (USER.205)
1561 INT16 WriteComm(INT16 fd, LPSTR lpvBuf, INT16 cbWrite)
1563 int x, length;
1564 struct DosDeviceStruct *ptr;
1566 dprintf_comm(stddeb,"WriteComm: fd %d, ptr %p, length %d\n",
1567 fd, lpvBuf, cbWrite);
1568 if ((ptr = GetDeviceStruct(fd)) == NULL) {
1569 commerror = IE_BADID;
1570 return -1;
1573 if (ptr->suspended) {
1574 commerror = IE_HARDWARE;
1575 return -1;
1578 for (x=0; x != cbWrite ; x++)
1579 dprintf_comm(stddeb,"%c", *(lpvBuf + x) );
1581 length = write(fd, (void *) lpvBuf, cbWrite);
1583 if (length == -1) {
1584 commerror = WinError();
1585 return -1;
1586 } else {
1587 commerror = 0;
1588 return length;
1593 /*****************************************************************************
1594 * GetCommTimeouts (KERNEL32.160)
1596 BOOL32 GetCommTimeouts(HANDLE32 hfile,LPCOMMTIMEOUTS lptimeouts) {
1597 dprintf_comm(stddeb,"GetCommTimeouts(%lx,%p), empty stub.\n",
1598 (DWORD)hfile,lptimeouts
1600 return TRUE;
1603 /*****************************************************************************
1604 * SetCommTimeouts (KERNEL32.453)
1606 BOOL32 SetCommTimeouts(HANDLE32 hfile,LPCOMMTIMEOUTS lptimeouts) {
1607 dprintf_comm(stddeb,"SetCommTimeouts(%lx,%p), empty stub.\n",
1608 (DWORD)hfile,lptimeouts
1610 return TRUE;