Release 960225
[wine.git] / misc / comm.c
blob467912d082d1edf330b22fca2b940809bb9d413d
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
3 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <termios.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <ctype.h>
12 #include <sys/stat.h>
13 #if defined(__NetBSD__) || defined(__FreeBSD__)
14 #include <errno.h>
15 #include <sys/ioctl.h>
16 #endif
17 #include <unistd.h>
19 #include "windows.h"
20 #include "comm.h"
21 #include "options.h"
22 #include "stddebug.h"
23 /* #define DEBUG_COMM */
24 /* #undef DEBUG_COMM */
25 #include "debug.h"
27 int commerror = 0, eventmask = 0;
29 struct DosDeviceStruct COM[MAX_PORTS];
30 struct DosDeviceStruct LPT[MAX_PORTS];
32 void COMM_Init(void)
34 int x;
35 char option[10], temp[256], *btemp;
36 struct stat st;
38 for (x=0; x!=MAX_PORTS; x++) {
39 strcpy(option,"COMx");
40 option[3] = '1' + x;
41 option[4] = '\0';
43 PROFILE_GetWineIniString( "serialports", option, "*",
44 temp, sizeof(temp) );
45 if (!strcmp(temp, "*") || *temp == '\0')
46 COM[x].devicename = NULL;
47 else {
48 btemp = strchr(temp,',');
49 if (btemp != NULL) {
50 *btemp++ = '\0';
51 COM[x].baudrate = atoi(btemp);
52 } else {
53 COM[x].baudrate = -1;
55 stat(temp, &st);
56 if (!S_ISCHR(st.st_mode))
57 fprintf(stderr,"comm: can 't use `%s' as %s !\n", temp, option);
58 else
59 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
60 fprintf(stderr,"comm: can't malloc for device info!\n");
61 else {
62 COM[x].fd = 0;
63 strcpy(COM[x].devicename, temp);
65 dprintf_comm(stddeb,
66 "Comm_Init: %s = %s\n", option, COM[x].devicename);
69 strcpy(option, "LPTx");
70 option[3] = '1' + x;
71 option[4] = '\0';
73 PROFILE_GetWineIniString( "parallelports", option, "*",
74 temp, sizeof(temp) );
75 if (!strcmp(temp, "*") || *temp == '\0')
76 LPT[x].devicename = NULL;
77 else {
78 stat(temp, &st);
79 if (!S_ISCHR(st.st_mode))
80 fprintf(stderr,"comm: can 't use `%s' as %s !\n", temp, option);
81 else
82 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
83 fprintf(stderr,"comm: can't malloc for device info!\n");
84 else {
85 LPT[x].fd = 0;
86 strcpy(LPT[x].devicename, temp);
88 dprintf_comm(stddeb,
89 "Comm_Init: %s = %s\n", option, LPT[x].devicename);
96 struct DosDeviceStruct *GetDeviceStruct(int fd)
98 int x;
100 for (x=0; x!=MAX_PORTS; x++) {
101 if (COM[x].fd == fd)
102 return &COM[x];
103 if (LPT[x].fd == fd)
104 return &LPT[x];
107 return NULL;
110 int ValidCOMPort(int x)
112 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
115 int ValidLPTPort(int x)
117 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
120 int WinError(void)
122 dprintf_comm(stddeb, "WinError: errno = %d\n", errno);
123 switch (errno) {
124 default:
125 return CE_IOE;
129 BOOL BuildCommDCB(LPCSTR device, LPDCB lpdcb)
131 /* "COM1:9600,n,8,1" */
132 /* 012345 */
134 int port;
135 char *ptr, temp[256];
137 dprintf_comm(stddeb,
138 "BuildCommDCB: (%s), ptr %p\n", device, lpdcb);
139 commerror = 0;
141 if (!lstrncmpi(device,"COM",3)) {
142 port = device[3] - '0';
145 if (port-- == 0) {
146 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
147 commerror = IE_BADID;
150 if (!ValidCOMPort(port)) {
151 commerror = IE_BADID;
152 return -1;
155 if (!COM[port].fd) {
156 OpenComm(device, 0, 0);
158 lpdcb->Id = COM[port].fd;
160 if (!*(device+4))
161 return 0;
163 if (*(device+4) != ':')
164 return -1;
166 strcpy(temp,device+5);
167 ptr = strtok(temp, ",");
169 if (COM[port].baudrate > 0)
170 lpdcb->BaudRate = COM[port].baudrate;
171 else
172 lpdcb->BaudRate = atoi(ptr);
173 dprintf_comm(stddeb,"BuildCommDCB: baudrate (%d)\n", lpdcb->BaudRate);
175 ptr = strtok(NULL, ",");
176 if (islower(*ptr))
177 *ptr = toupper(*ptr);
179 dprintf_comm(stddeb,"BuildCommDCB: parity (%c)\n", *ptr);
180 switch (*ptr) {
181 case 'N':
182 lpdcb->Parity = NOPARITY;
183 lpdcb->fParity = 0;
184 break;
186 lpdcb->fParity = 1;
188 case 'E':
189 lpdcb->Parity = EVENPARITY;
190 break;
191 case 'M':
192 lpdcb->Parity = MARKPARITY;
193 break;
194 case 'O':
195 lpdcb->Parity = ODDPARITY;
196 break;
197 default:
198 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
199 return -1;
202 ptr = strtok(NULL, ",");
203 dprintf_comm(stddeb, "BuildCommDCB: charsize (%c)\n", *ptr);
204 lpdcb->ByteSize = *ptr - '0';
206 ptr = strtok(NULL, ",");
207 dprintf_comm(stddeb, "BuildCommDCB: stopbits (%c)\n", *ptr);
208 switch (*ptr) {
209 case '1':
210 lpdcb->StopBits = ONESTOPBIT;
211 break;
212 case '2':
213 lpdcb->StopBits = TWOSTOPBITS;
214 break;
215 default:
216 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
217 return -1;
221 return 0;
224 int OpenComm(LPCSTR device, UINT cbInQueue, UINT cbOutQueue)
226 int port, fd;
228 dprintf_comm(stddeb,
229 "OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
230 commerror = 0;
232 if (!lstrncmpi(device,"COM",3)) {
233 port = device[3] - '0';
235 if (port-- == 0) {
236 fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n");
237 commerror = IE_BADID;
240 dprintf_comm(stddeb,
241 "OpenComm: %s = %s\n", device, COM[port].devicename);
243 if (!ValidCOMPort(port)) {
244 commerror = IE_BADID;
245 return -1;
247 if (COM[port].fd) {
248 return COM[port].fd;
251 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
252 if (fd == -1) {
253 commerror = WinError();
254 return -1;
255 } else {
256 COM[port].fd = fd;
257 return fd;
260 else
261 if (!lstrncmpi(device,"LPT",3)) {
262 port = device[3] - '0';
264 if (!ValidLPTPort(port)) {
265 commerror = IE_BADID;
266 return -1;
268 if (LPT[port].fd) {
269 commerror = IE_OPEN;
270 return -1;
273 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
274 if (fd == -1) {
275 commerror = WinError();
276 return -1;
277 } else {
278 LPT[port].fd = fd;
279 return fd;
282 return 0;
285 int CloseComm(int fd)
287 dprintf_comm(stddeb,"CloseComm: fd %d\n", fd);
288 if (close(fd) == -1) {
289 commerror = WinError();
290 return -1;
291 } else {
292 commerror = 0;
293 return 0;
297 int SetCommBreak(int fd)
299 struct DosDeviceStruct *ptr;
301 dprintf_comm(stddeb,"SetCommBreak: fd: %d\n", fd);
302 if ((ptr = GetDeviceStruct(fd)) == NULL) {
303 commerror = IE_BADID;
304 return -1;
307 ptr->suspended = 1;
308 commerror = 0;
309 return 0;
312 int ClearCommBreak(int fd)
314 struct DosDeviceStruct *ptr;
316 dprintf_comm(stddeb,"ClearCommBreak: fd: %d\n", fd);
317 if ((ptr = GetDeviceStruct(fd)) == NULL) {
318 commerror = IE_BADID;
319 return -1;
322 ptr->suspended = 0;
323 commerror = 0;
324 return 0;
327 LONG EscapeCommFunction(int fd, int nFunction)
329 int max;
330 struct termios port;
332 dprintf_comm(stddeb,
333 "EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
334 if (tcgetattr(fd, &port) == -1) {
335 commerror = WinError();
336 return -1;
339 switch (nFunction) {
340 case RESETDEV:
341 break;
343 case GETMAXCOM:
344 for (max = MAX_PORTS;!COM[max].devicename;max--)
346 return max;
347 break;
349 case GETMAXLPT:
350 for (max = MAX_PORTS;!LPT[max].devicename;max--)
352 return 0x80 + max;
353 break;
355 case CLRDTR:
356 port.c_cflag &= TIOCM_DTR;
357 break;
359 case CLRRTS:
360 port.c_cflag &= TIOCM_RTS;
361 break;
363 #ifndef __svr4__
364 case SETDTR:
365 port.c_cflag |= CRTSCTS;
366 break;
368 case SETRTS:
369 port.c_cflag |= CRTSCTS;
370 break;
371 #endif
373 case SETXOFF:
374 port.c_iflag |= IXOFF;
375 break;
377 case SETXON:
378 port.c_iflag |= IXON;
379 break;
381 default:
382 fprintf(stderr,
383 "EscapeCommFunction fd: %d, unknown function: %d\n",
384 fd, nFunction);
385 break;
388 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
389 commerror = WinError();
390 return -1;
391 } else {
392 commerror = 0;
393 return 0;
397 int FlushComm(int fd, int fnQueue)
399 int queue;
401 dprintf_comm(stddeb,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
402 switch (fnQueue) {
403 case 0:
404 queue = TCOFLUSH;
405 break;
406 case 1:
407 queue = TCIFLUSH;
408 break;
409 default:
410 fprintf(stderr,
411 "FlushComm fd: %d, UNKNOWN queue: %d\n",
412 fd, fnQueue);
413 return -1;
416 if (tcflush(fd, fnQueue)) {
417 commerror = WinError();
418 return -1;
419 } else {
420 commerror = 0;
421 return 0;
425 int GetCommError(int fd, COMSTAT FAR *lpStat)
427 int temperror;
429 dprintf_comm(stddeb,
430 "GetCommError: fd %d (current error %d)\n", fd, commerror);
431 temperror = commerror;
432 commerror = 0;
433 return(temperror);
436 UINT FAR* SetCommEventMask(int fd, UINT fuEvtMask)
438 dprintf_comm(stddeb,
439 "SetCommEventMask: fd %d, mask %d\n", fd, fuEvtMask);
440 eventmask |= fuEvtMask;
441 return (UINT *)&eventmask;
444 UINT GetCommEventMask(int fd, int fnEvtClear)
446 dprintf_comm(stddeb,
447 "GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
448 eventmask &= ~fnEvtClear;
449 return eventmask;
452 int SetCommState(DCB FAR *lpdcb)
454 struct termios port;
455 struct DosDeviceStruct *ptr;
457 dprintf_comm(stddeb,
458 "SetCommState: fd %d, ptr %p\n", lpdcb->Id, lpdcb);
459 if (tcgetattr(lpdcb->Id, &port) == -1) {
460 commerror = WinError();
461 return -1;
464 port.c_cc[VMIN] = 0;
465 port.c_cc[VTIME] = 1;
467 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
468 port.c_iflag |= (IGNBRK);
470 port.c_oflag &= ~(OPOST);
472 port.c_cflag &= ~(HUPCL);
473 port.c_cflag |= CLOCAL | CREAD;
475 port.c_lflag &= ~(ICANON|ECHO|ISIG);
476 port.c_lflag |= NOFLSH;
478 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
479 commerror = IE_BADID;
480 return -1;
482 if (ptr->baudrate > 0)
483 lpdcb->BaudRate = ptr->baudrate;
484 dprintf_comm(stddeb,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
485 #ifdef CBAUD
486 port.c_cflag &= ~CBAUD;
487 switch (lpdcb->BaudRate) {
488 case 110:
489 case CBR_110:
490 port.c_cflag |= B110;
491 break;
492 case 300:
493 case CBR_300:
494 port.c_cflag |= B300;
495 break;
496 case 600:
497 case CBR_600:
498 port.c_cflag |= B600;
499 break;
500 case 1200:
501 case CBR_1200:
502 port.c_cflag |= B1200;
503 break;
504 case 2400:
505 case CBR_2400:
506 port.c_cflag |= B2400;
507 break;
508 case 4800:
509 case CBR_4800:
510 port.c_cflag |= B4800;
511 break;
512 case 9600:
513 case CBR_9600:
514 port.c_cflag |= B9600;
515 break;
516 case 19200:
517 case CBR_19200:
518 port.c_cflag |= B19200;
519 break;
520 case 38400:
521 case CBR_38400:
522 port.c_cflag |= B38400;
523 break;
524 default:
525 commerror = IE_BAUDRATE;
526 return -1;
528 #else
529 switch (lpdcb->BaudRate) {
530 case 110:
531 case CBR_110:
532 port.c_ospeed = B110;
533 break;
534 case 300:
535 case CBR_300:
536 port.c_ospeed = B300;
537 break;
538 case 600:
539 case CBR_600:
540 port.c_ospeed = B600;
541 break;
542 case 1200:
543 case CBR_1200:
544 port.c_ospeed = B1200;
545 break;
546 case 2400:
547 case CBR_2400:
548 port.c_ospeed = B2400;
549 break;
550 case 4800:
551 case CBR_4800:
552 port.c_ospeed = B4800;
553 break;
554 case 9600:
555 case CBR_9600:
556 port.c_ospeed = B9600;
557 break;
558 case 19200:
559 case CBR_19200:
560 port.c_ospeed = B19200;
561 break;
562 case 38400:
563 case CBR_38400:
564 port.c_ospeed = B38400;
565 break;
566 default:
567 commerror = IE_BAUDRATE;
568 return -1;
570 port.c_ispeed = port.c_ospeed;
571 #endif
572 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
573 port.c_cflag &= ~CSIZE;
574 switch (lpdcb->ByteSize) {
575 case 5:
576 port.c_cflag |= CS5;
577 break;
578 case 6:
579 port.c_cflag |= CS6;
580 break;
581 case 7:
582 port.c_cflag |= CS7;
583 break;
584 case 8:
585 port.c_cflag |= CS8;
586 break;
587 default:
588 commerror = IE_BYTESIZE;
589 return -1;
592 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
593 port.c_cflag &= ~(PARENB | PARODD);
594 if (lpdcb->fParity)
595 switch (lpdcb->Parity) {
596 case NOPARITY:
597 port.c_iflag &= ~INPCK;
598 break;
599 case ODDPARITY:
600 port.c_cflag |= (PARENB | PARODD);
601 port.c_iflag |= INPCK;
602 break;
603 case EVENPARITY:
604 port.c_cflag |= PARENB;
605 port.c_iflag |= INPCK;
606 break;
607 default:
608 commerror = IE_BYTESIZE;
609 return -1;
613 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
614 switch (lpdcb->StopBits) {
615 case ONESTOPBIT:
616 port.c_cflag &= ~CSTOPB;
617 break;
618 case TWOSTOPBITS:
619 port.c_cflag |= CSTOPB;
620 break;
621 default:
622 commerror = IE_BYTESIZE;
623 return -1;
625 #ifndef __svr4__
627 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
628 port.c_cflag |= CRTSCTS;
630 if (lpdcb->fDtrDisable)
631 port.c_cflag &= ~CRTSCTS;
632 #endif
633 if (lpdcb->fInX)
634 port.c_iflag |= IXON;
635 if (lpdcb->fOutX)
636 port.c_iflag |= IXOFF;
638 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
639 commerror = WinError();
640 return -1;
641 } else {
642 commerror = 0;
643 return 0;
647 int GetCommState(int fd, DCB FAR *lpdcb)
649 struct termios port;
651 dprintf_comm(stddeb,"GetCommState: fd %d, ptr %p\n", fd, lpdcb);
652 if (tcgetattr(fd, &port) == -1) {
653 commerror = WinError();
654 return -1;
657 lpdcb->Id = fd;
659 #ifdef CBAUD
660 switch (port.c_cflag & CBAUD) {
661 #else
662 switch (port.c_ospeed) {
663 #endif
664 case B110:
665 lpdcb->BaudRate = 110;
666 break;
667 case B300:
668 lpdcb->BaudRate = 300;
669 break;
670 case B600:
671 lpdcb->BaudRate = 600;
672 break;
673 case B1200:
674 lpdcb->BaudRate = 1200;
675 break;
676 case B2400:
677 lpdcb->BaudRate = 2400;
678 break;
679 case B4800:
680 lpdcb->BaudRate = 4800;
681 break;
682 case B9600:
683 lpdcb->BaudRate = 9600;
684 break;
685 case B19200:
686 lpdcb->BaudRate = 19200;
687 break;
688 case B38400:
689 lpdcb->BaudRate = 38400;
690 break;
693 switch (port.c_cflag & CSIZE) {
694 case CS5:
695 lpdcb->ByteSize = 5;
696 break;
697 case CS6:
698 lpdcb->ByteSize = 6;
699 break;
700 case CS7:
701 lpdcb->ByteSize = 7;
702 break;
703 case CS8:
704 lpdcb->ByteSize = 8;
705 break;
708 switch (port.c_cflag & ~(PARENB | PARODD)) {
709 case 0:
710 lpdcb->fParity = NOPARITY;
711 break;
712 case PARENB:
713 lpdcb->fParity = EVENPARITY;
714 break;
715 case (PARENB | PARODD):
716 lpdcb->fParity = ODDPARITY;
717 break;
720 if (port.c_cflag & CSTOPB)
721 lpdcb->StopBits = TWOSTOPBITS;
722 else
723 lpdcb->StopBits = ONESTOPBIT;
725 lpdcb->RlsTimeout = 50;
726 lpdcb->CtsTimeout = 50;
727 lpdcb->DsrTimeout = 50;
728 lpdcb->fNull = 0;
729 lpdcb->fChEvt = 0;
730 lpdcb->fBinary = 1;
731 lpdcb->fDtrDisable = 0;
733 #ifndef __svr4__
735 if (port.c_cflag & CRTSCTS) {
736 lpdcb->fDtrflow = 1;
737 lpdcb->fRtsflow = 1;
738 lpdcb->fOutxCtsFlow = 1;
739 lpdcb->fOutxDsrFlow = 1;
740 } else
741 #endif
742 lpdcb->fDtrDisable = 1;
744 if (port.c_iflag & IXON)
745 lpdcb->fInX = 1;
746 else
747 lpdcb->fInX = 0;
749 if (port.c_iflag & IXOFF)
750 lpdcb->fOutX = 1;
751 else
752 lpdcb->fOutX = 0;
754 lpdcb->XonChar =
755 lpdcb->XoffChar =
757 lpdcb->XonLim = 10;
758 lpdcb->XoffLim = 10;
760 commerror = 0;
761 return 0;
764 int TransmitCommChar(int fd, char chTransmit)
766 struct DosDeviceStruct *ptr;
768 dprintf_comm(stddeb,
769 "TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
770 if ((ptr = GetDeviceStruct(fd)) == NULL) {
771 commerror = IE_BADID;
772 return -1;
775 if (ptr->suspended) {
776 commerror = IE_HARDWARE;
777 return -1;
780 if (write(fd, (void *) &chTransmit, 1) == -1) {
781 commerror = WinError();
782 return -1;
783 } else {
784 commerror = 0;
785 return 0;
789 int UngetCommChar(int fd, char chUnget)
791 struct DosDeviceStruct *ptr;
793 dprintf_comm(stddeb,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
794 if ((ptr = GetDeviceStruct(fd)) == NULL) {
795 commerror = IE_BADID;
796 return -1;
799 if (ptr->suspended) {
800 commerror = IE_HARDWARE;
801 return -1;
804 ptr->unget = 1;
805 ptr->unget_byte = chUnget;
807 commerror = 0;
808 return 0;
811 int ReadComm(int fd, LPSTR lpvBuf, int cbRead)
813 int status, length;
814 struct DosDeviceStruct *ptr;
816 dprintf_comm(stddeb,
817 "ReadComm: fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
818 if ((ptr = GetDeviceStruct(fd)) == NULL) {
819 commerror = IE_BADID;
820 return -1;
823 if (ptr->suspended) {
824 commerror = IE_HARDWARE;
825 return -1;
828 if (ptr->unget) {
829 *lpvBuf = ptr->unget_byte;
830 lpvBuf++;
831 ptr->unget = 0;
833 length = 1;
834 } else
835 length = 0;
837 status = read(fd, (void *) lpvBuf, cbRead);
839 if (status == -1) {
840 if (errno != EAGAIN) {
841 commerror = WinError();
842 return -1 - length;
843 } else {
844 commerror = 0;
845 return length;
847 } else {
848 commerror = 0;
849 return length + status;
853 int WriteComm(int fd, LPSTR lpvBuf, int cbWrite)
855 int x, length;
856 struct DosDeviceStruct *ptr;
858 dprintf_comm(stddeb,"WriteComm: fd %d, ptr %p, length %d\n",
859 fd, lpvBuf, cbWrite);
860 if ((ptr = GetDeviceStruct(fd)) == NULL) {
861 commerror = IE_BADID;
862 return -1;
865 if (ptr->suspended) {
866 commerror = IE_HARDWARE;
867 return -1;
870 for (x=0; x != cbWrite ; x++)
871 dprintf_comm(stddeb,"%c", *(lpvBuf + x) );
873 length = write(fd, (void *) lpvBuf, cbWrite);
875 if (length == -1) {
876 commerror = WinError();
877 return -1;
878 } else {
879 commerror = 0;
880 return length;