Release 940420
[wine/multimedia.git] / misc / comm.c
blob0a51b77d60043e2e8bedce23c27bd7563f7db68c
1 /*
2 * DEC 93 Erik Bos (erik@trashcan.hacktic.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 "wine.h"
20 #include "windows.h"
22 #define DEBUG_COMM
24 #define MAX_PORTS 16
26 int commerror = 0, eventmask = 0;
28 struct DosDeviceStruct {
29 char *devicename; /* /dev/cua1 */
30 int fd;
31 int suspended;
32 int unget;
33 int unget_byte;
36 struct DosDeviceStruct COM[MAX_PORTS];
37 struct DosDeviceStruct LPT[MAX_PORTS];
39 void Comm_DeInit(void);
41 void Comm_Init(void)
43 int x, serial = 0, parallel = 0;
44 char option[10], temp[256];
45 struct stat st;
47 for (x=0; x!=MAX_PORTS; x++) {
48 strcpy(option,"COMx");
49 option[3] = '0' + x;
50 option[4] = '\0';
52 GetPrivateProfileString("serialports", option, "*", temp, sizeof(temp), WINE_INI);
53 if (!strcmp(temp, "*") || *temp == '\0')
54 COM[serial].devicename = NULL;
55 else {
56 stat(temp, &st);
57 if (!S_ISCHR(st.st_mode))
58 fprintf(stderr,"comm: can 't use `%s' as COM%d !\n", temp, x);
59 else
60 if ((COM[serial].devicename = malloc(strlen(temp)+1)) == NULL)
61 fprintf(stderr,"comm: can't malloc for device info!\n");
62 else {
63 COM[serial].fd = 0;
64 strcpy(COM[serial].devicename, temp);
65 serial++;
69 strcpy(option, "LPTx");
70 option[3] = '0' + x;
71 option[4] = '\0';
73 GetPrivateProfileString("parallelports", option, "*", temp, sizeof(temp), WINE_INI);
74 if (!strcmp(temp, "*") || *temp == '\0')
75 LPT[parallel].devicename = NULL;
76 else {
77 stat(temp, &st);
78 if (!S_ISCHR(st.st_mode))
79 fprintf(stderr,"comm: can 't use `%s' as LPT%d !\n", temp, x);
80 else
81 if ((LPT[parallel].devicename = malloc(strlen(temp)+1)) == NULL)
82 fprintf(stderr,"comm: can't malloc for device info!\n");
83 else {
84 LPT[parallel].fd = 0;
85 strcpy(LPT[parallel].devicename, temp);
86 parallel++;
93 void Comm_DeInit(void)
95 int x;
97 for (x=0; x!=MAX_PORTS; x++) {
99 if (COM[x].devicename) {
100 if (COM[x].fd)
101 close(COM[x].fd);
102 free(COM[x].devicename);
104 if (LPT[x].devicename) {
105 if (LPT[x].fd)
106 close(LPT[x].fd);
107 free(LPT[x].devicename);
112 struct DosDeviceStruct *GetDeviceStruct(int fd)
114 int x;
116 for (x=0; x!=MAX_PORTS; x++) {
117 if (COM[x].fd == fd)
118 return &COM[x];
119 if (LPT[x].fd == fd)
120 return &LPT[x];
123 return NULL;
126 int ValidCOMPort(int x)
128 return(x < MAX_PORTS ? (int) COM[x].devicename : 0);
131 int ValidLPTPort(int x)
133 return(x < MAX_PORTS ? (int) LPT[x].devicename : 0);
136 int WinError(void)
138 perror("comm");
139 switch (errno) {
140 default:
141 return CE_IOE;
145 int BuildCommDCB(LPSTR device, DCB FAR *lpdcb)
147 /* "COM1:9600,n,8,1" */
148 /* 012345 */
150 int port;
151 char *ptr, temp[256];
153 #ifdef DEBUG_COMM
154 fprintf(stderr,"BuildCommDCB: (%s), ptr %d\n", device, (long) lpdcb);
155 #endif
156 commerror = 0;
158 if (!strncmp(device,"COM",3)) {
159 port = device[3] - '0';
162 if (port-- == 0) {
163 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
164 commerror = IE_BADID;
167 if (!ValidCOMPort(port)) {
168 commerror = IE_BADID;
169 return -1;
172 if (!COM[port].fd) {
173 commerror = IE_NOPEN;
174 return -1;
176 lpdcb->Id = COM[port].fd;
178 if (!*(device+4))
179 return 0;
181 if (*(device+4) != ':')
182 return -1;
184 strcpy(temp,device+5);
185 ptr = strtok(temp, ",");
187 fprintf(stderr,"BuildCommDCB: baudrate (%s)\n", ptr);
188 lpdcb->BaudRate = atoi(ptr);
190 ptr = strtok(NULL, ",");
191 if (islower(*ptr))
192 *ptr = toupper(*ptr);
194 fprintf(stderr,"BuildCommDCB: parity (%c)\n", *ptr);
195 switch (*ptr) {
196 case 'N':
197 lpdcb->Parity = NOPARITY;
198 lpdcb->fParity = 0;
199 break;
201 lpdcb->fParity = 1;
203 case 'E':
204 lpdcb->Parity = EVENPARITY;
205 break;
206 case 'M':
207 lpdcb->Parity = MARKPARITY;
208 break;
209 case 'O':
210 lpdcb->Parity = ODDPARITY;
211 break;
212 default:
213 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
214 return -1;
217 ptr = strtok(NULL, ",");
218 fprintf(stderr, "BuildCommDCB: charsize (%c)\n", *ptr);
219 lpdcb->ByteSize = *ptr - '0';
221 ptr = strtok(NULL, ",");
222 fprintf(stderr, "BuildCommDCB: stopbits (%c)\n", *ptr);
223 switch (*ptr) {
224 case '1':
225 lpdcb->StopBits = ONESTOPBIT;
226 break;
227 case '2':
228 lpdcb->StopBits = TWOSTOPBITS;
229 break;
230 default:
231 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
232 return -1;
236 return 0;
239 int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue)
241 int port, fd;
243 #ifdef DEBUG_COMM
244 fprintf(stderr,"OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
245 #endif
247 commerror = 0;
249 if (!strncmp(device,"COM",3)) {
250 port = device[3] - '0';
252 if (port-- == 0) {
253 fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n");
254 commerror = IE_BADID;
257 if (!ValidCOMPort(port)) {
258 commerror = IE_BADID;
259 return -1;
261 if (COM[port].fd) {
262 commerror = IE_OPEN;
263 return -1;
266 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK, 0);
267 if (fd == -1) {
268 commerror = WinError();
269 return -1;
270 } else {
271 COM[port].fd = fd;
272 return fd;
275 else
276 if (!strncmp(device,"LPT",3)) {
277 port = device[3] - '0';
279 if (!ValidLPTPort(port)) {
280 commerror = IE_BADID;
281 return -1;
283 if (LPT[port].fd) {
284 commerror = IE_OPEN;
285 return -1;
288 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
289 if (fd == -1) {
290 commerror = WinError();
291 return -1;
292 } else {
293 LPT[port].fd = fd;
294 return fd;
297 return 0;
300 int CloseComm(int fd)
302 #ifdef DEBUG_COMM
303 fprintf(stderr,"CloseComm: fd %d\n", fd);
304 #endif
306 if (close(fd) == -1) {
307 commerror = WinError();
308 return -1;
309 } else {
310 commerror = 0;
311 return 0;
315 int SetCommBreak(int fd)
317 struct DosDeviceStruct *ptr;
319 #ifdef DEBUG_COMM
320 fprintf(stderr,"SetCommBreak: fd: %d\n", fd);
321 #endif
323 if ((ptr = GetDeviceStruct(fd)) == NULL) {
324 commerror = IE_BADID;
325 return -1;
328 ptr->suspended = 1;
329 commerror = 0;
330 return 0;
333 int ClearCommBreak(int fd)
335 struct DosDeviceStruct *ptr;
337 #ifdef DEBUG_COMM
338 fprintf(stderr,"ClearCommBreak: fd: %d\n", fd);
339 #endif
341 if ((ptr = GetDeviceStruct(fd)) == NULL) {
342 commerror = IE_BADID;
343 return -1;
346 ptr->suspended = 0;
347 commerror = 0;
348 return 0;
351 LONG EscapeCommFunction(int fd, int nFunction)
353 int max;
354 struct termios port;
356 #ifdef DEBUG_COMM
357 fprintf(stderr,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
358 #endif
360 if (tcgetattr(fd, &port) == -1) {
361 commerror = WinError();
362 return -1;
365 switch (nFunction) {
366 case RESETDEV:
367 break;
369 case GETMAXCOM:
370 for (max = 0;COM[max].devicename;max++)
372 return max;
373 break;
375 case GETMAXLPT:
376 for (max = 0;LPT[max].devicename;max++)
378 return 0x80 + max;
379 break;
381 case CLRDTR:
382 port.c_cflag &= TIOCM_DTR;
383 break;
385 case CLRRTS:
386 port.c_cflag &= TIOCM_RTS;
387 break;
389 case SETDTR:
390 port.c_cflag |= CRTSCTS;
391 break;
393 case SETRTS:
394 port.c_cflag |= CRTSCTS;
395 break;
397 case SETXOFF:
398 port.c_iflag |= IXOFF;
399 break;
401 case SETXON:
402 port.c_iflag |= IXON;
403 break;
405 default:
406 fprintf(stderr,"EscapeCommFunction fd: %d, unknown function: %d\n", fd, nFunction);
407 break;
410 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
411 commerror = WinError();
412 return -1;
413 } else {
414 commerror = 0;
415 return 0;
419 int FlushComm(int fd, int fnQueue)
421 int queue;
423 #ifdef DEBUG_COMM
424 fprintf(stderr,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
425 #endif
427 switch (fnQueue) {
428 case 0:
429 queue = TCOFLUSH;
430 break;
431 case 1:
432 queue = TCIFLUSH;
433 break;
434 default:
435 fprintf(stderr,"FlushComm fd: %d, UNKNOWN queue: %d\n", fd, fnQueue);
436 return -1;
439 if (tcflush(fd, fnQueue)) {
440 commerror = WinError();
441 return -1;
442 } else {
443 commerror = 0;
444 return 0;
448 int GetCommError(int fd, COMSTAT FAR *lpStat)
450 #ifdef DEBUG_COMM
451 fprintf(stderr,"GetCommError: fd %d (current error %d)\n", fd, commerror);
452 #endif
454 return(commerror);
457 UINT FAR* SetCommEventMask(int fd, UINT fuEvtMask)
459 #ifdef DEBUG_COMM
460 fprintf(stderr,"SetCommEventMask: fd %d, mask %d\n", fd, fuEvtMask);
461 #endif
463 eventmask |= fuEvtMask;
464 return (UINT *)&eventmask;
467 UINT GetCommEventMask(int fd, int fnEvtClear)
469 #ifdef DEBUG_COMM
470 fprintf(stderr,"GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
471 #endif
472 eventmask &= ~fnEvtClear;
473 return eventmask;
476 int SetCommState(DCB FAR *lpdcb)
478 struct termios port;
480 #ifdef DEBUG_COMM
481 fprintf(stderr,"SetCommState: fd %d, ptr %d\n", lpdcb->Id, (long) lpdcb);
482 #endif
484 if (tcgetattr(lpdcb->Id, &port) == -1) {
485 commerror = WinError();
486 return -1;
489 port.c_cc[VMIN] = 0;
490 port.c_cc[VTIME] = 1;
492 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
493 port.c_iflag |= (IGNBRK);
495 port.c_oflag &= ~(OPOST);
497 port.c_cflag &= ~(HUPCL);
498 port.c_cflag |= CLOCAL | CREAD;
500 port.c_lflag &= ~(ICANON|ECHO|ISIG);
501 port.c_lflag |= NOFLSH;
503 fprintf(stderr,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
504 #ifdef CBAUD
505 port.c_cflag &= ~CBAUD;
506 switch (lpdcb->BaudRate) {
507 case 110:
508 case CBR_110:
509 port.c_cflag |= B110;
510 break;
511 case 300:
512 case CBR_300:
513 port.c_cflag |= B300;
514 break;
515 case 600:
516 case CBR_600:
517 port.c_cflag |= B600;
518 break;
519 case 1200:
520 case CBR_1200:
521 port.c_cflag |= B1200;
522 break;
523 case 2400:
524 case CBR_2400:
525 port.c_cflag |= B2400;
526 break;
527 case 4800:
528 case CBR_4800:
529 port.c_cflag |= B4800;
530 break;
531 case 9600:
532 case CBR_9600:
533 port.c_cflag |= B9600;
534 break;
535 case 19200:
536 case CBR_19200:
537 port.c_cflag |= B19200;
538 break;
539 case 38400:
540 case CBR_38400:
541 port.c_cflag |= B38400;
542 break;
543 default:
544 commerror = IE_BAUDRATE;
545 return -1;
547 #else
548 switch (lpdcb->BaudRate) {
549 case 110:
550 case CBR_110:
551 port.c_ospeed = B110;
552 break;
553 case 300:
554 case CBR_300:
555 port.c_ospeed = B300;
556 break;
557 case 600:
558 case CBR_600:
559 port.c_ospeed = B600;
560 break;
561 case 1200:
562 case CBR_1200:
563 port.c_ospeed = B1200;
564 break;
565 case 2400:
566 case CBR_2400:
567 port.c_ospeed = B2400;
568 break;
569 case 4800:
570 case CBR_4800:
571 port.c_ospeed = B4800;
572 break;
573 case 9600:
574 case CBR_9600:
575 port.c_ospeed = B9600;
576 break;
577 case 19200:
578 case CBR_19200:
579 port.c_ospeed = B19200;
580 break;
581 case 38400:
582 case CBR_38400:
583 port.c_ospeed = B38400;
584 break;
585 default:
586 commerror = IE_BAUDRATE;
587 return -1;
589 port.c_ispeed = port.c_ospeed;
590 #endif
591 fprintf(stderr,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
592 port.c_cflag &= ~CSIZE;
593 switch (lpdcb->ByteSize) {
594 case 5:
595 port.c_cflag |= CS5;
596 break;
597 case 6:
598 port.c_cflag |= CS6;
599 break;
600 case 7:
601 port.c_cflag |= CS7;
602 break;
603 case 8:
604 port.c_cflag |= CS8;
605 break;
606 default:
607 commerror = IE_BYTESIZE;
608 return -1;
611 fprintf(stderr,"SetCommState: parity %d\n",lpdcb->Parity);
612 port.c_cflag &= ~(PARENB | PARODD);
613 if (lpdcb->fParity)
614 switch (lpdcb->Parity) {
615 case NOPARITY:
616 port.c_iflag &= ~INPCK;
617 break;
618 case ODDPARITY:
619 port.c_cflag |= (PARENB | PARODD);
620 port.c_iflag |= INPCK;
621 break;
622 case EVENPARITY:
623 port.c_cflag |= PARENB;
624 port.c_iflag |= INPCK;
625 break;
626 default:
627 commerror = IE_BYTESIZE;
628 return -1;
632 fprintf(stderr,"SetCommState: stopbits %d\n",lpdcb->StopBits);
633 switch (lpdcb->StopBits) {
634 case ONESTOPBIT:
635 port.c_cflag &= ~CSTOPB;
636 break;
637 case TWOSTOPBITS:
638 port.c_cflag |= CSTOPB;
639 break;
640 default:
641 commerror = IE_BYTESIZE;
642 return -1;
645 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
646 port.c_cflag |= CRTSCTS;
648 if (lpdcb->fDtrDisable)
649 port.c_cflag &= ~CRTSCTS;
651 if (lpdcb->fInX)
652 port.c_iflag |= IXON;
653 if (lpdcb->fOutX)
654 port.c_iflag |= IXOFF;
656 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
657 commerror = WinError();
658 return -1;
659 } else {
660 commerror = 0;
661 return 0;
665 int GetCommState(int fd, DCB FAR *lpdcb)
667 struct termios port;
669 #ifdef DEBUG_COMM
670 fprintf(stderr,"GetCommState: fd %d, ptr %d\n", fd, (long) lpdcb);
671 #endif
673 if (tcgetattr(fd, &port) == -1) {
674 commerror = WinError();
675 return -1;
678 lpdcb->Id = fd;
680 #ifdef CBAUD
681 switch (port.c_cflag & CBAUD) {
682 #else
683 switch (port.c_ospeed) {
684 #endif
685 case B110:
686 lpdcb->BaudRate = 110;
687 break;
688 case B300:
689 lpdcb->BaudRate = 300;
690 break;
691 case B600:
692 lpdcb->BaudRate = 600;
693 break;
694 case B1200:
695 lpdcb->BaudRate = 1200;
696 break;
697 case B2400:
698 lpdcb->BaudRate = 2400;
699 break;
700 case B4800:
701 lpdcb->BaudRate = 4800;
702 break;
703 case B9600:
704 lpdcb->BaudRate = 9600;
705 break;
706 case B19200:
707 lpdcb->BaudRate = 19200;
708 break;
709 case B38400:
710 lpdcb->BaudRate = 38400;
711 break;
714 switch (port.c_cflag & CSIZE) {
715 case CS5:
716 lpdcb->ByteSize = 5;
717 break;
718 case CS6:
719 lpdcb->ByteSize = 6;
720 break;
721 case CS7:
722 lpdcb->ByteSize = 7;
723 break;
724 case CS8:
725 lpdcb->ByteSize = 8;
726 break;
729 switch (port.c_cflag & ~(PARENB | PARODD)) {
730 case 0:
731 lpdcb->fParity = NOPARITY;
732 break;
733 case PARENB:
734 lpdcb->fParity = EVENPARITY;
735 break;
736 case (PARENB | PARODD):
737 lpdcb->fParity = ODDPARITY;
738 break;
741 if (port.c_cflag & CSTOPB)
742 lpdcb->StopBits = TWOSTOPBITS;
743 else
744 lpdcb->StopBits = ONESTOPBIT;
746 lpdcb->RlsTimeout = 50;
747 lpdcb->CtsTimeout = 50;
748 lpdcb->DsrTimeout = 50;
749 lpdcb->fNull = 0;
750 lpdcb->fChEvt = 0;
751 lpdcb->fBinary = 1;
753 lpdcb->fDtrDisable = 0;
754 if (port.c_cflag & CRTSCTS) {
755 lpdcb->fDtrflow = 1;
756 lpdcb->fRtsflow = 1;
757 lpdcb->fOutxCtsFlow = 1;
758 lpdcb->fOutxDsrFlow = 1;
759 } else
760 lpdcb->fDtrDisable = 1;
762 if (port.c_iflag & IXON)
763 lpdcb->fInX = 1;
764 else
765 lpdcb->fInX = 0;
767 if (port.c_iflag & IXOFF)
768 lpdcb->fOutX = 1;
769 else
770 lpdcb->fOutX = 0;
772 lpdcb->XonChar =
773 lpdcb->XoffChar =
775 lpdcb->XonLim = 10;
776 lpdcb->XoffLim = 10;
778 commerror = 0;
779 return 0;
782 int TransmitCommChar(int fd, char chTransmit)
784 struct DosDeviceStruct *ptr;
786 #ifdef DEBUG_COMM
787 fprintf(stderr,"TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
788 #endif
790 if ((ptr = GetDeviceStruct(fd)) == NULL) {
791 commerror = IE_BADID;
792 return -1;
795 if (ptr->suspended) {
796 commerror = IE_HARDWARE;
797 return -1;
800 if (write(fd, (void *) &chTransmit, 1) == -1) {
801 commerror = WinError();
802 return -1;
803 } else {
804 commerror = 0;
805 return 0;
809 int UngetCommChar(int fd, char chUnget)
811 struct DosDeviceStruct *ptr;
813 #ifdef DEBUG_COMM
814 fprintf(stderr,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
815 #endif
817 if ((ptr = GetDeviceStruct(fd)) == NULL) {
818 commerror = IE_BADID;
819 return -1;
822 if (ptr->suspended) {
823 commerror = IE_HARDWARE;
824 return -1;
827 ptr->unget = 1;
828 ptr->unget_byte = chUnget;
830 commerror = 0;
831 return 0;
834 int ReadComm(int fd, LPSTR lpvBuf, int cbRead)
836 int status, length;
837 struct DosDeviceStruct *ptr;
839 #ifdef DEBUG_COMM
840 fprintf(stderr,"ReadComm: fd %d, ptr %d, length %d\n", fd, (long) lpvBuf, cbRead);
841 #endif
843 if ((ptr = GetDeviceStruct(fd)) == NULL) {
844 commerror = IE_BADID;
845 return -1;
848 if (ptr->suspended) {
849 commerror = IE_HARDWARE;
850 return -1;
853 if (ptr->unget) {
854 *lpvBuf = ptr->unget_byte;
855 lpvBuf++;
856 ptr->unget = 0;
858 length = 1;
859 } else
860 length = 0;
862 status = read(fd, (void *) lpvBuf, cbRead);
864 if (status == -1) {
865 commerror = WinError();
866 return -1 - length;
867 } else {
868 commerror = 0;
869 return length + status;
873 int WriteComm(int fd, LPSTR lpvBuf, int cbWrite)
875 int x, length;
876 struct DosDeviceStruct *ptr;
878 #ifdef DEBUG_COMM
879 fprintf(stderr,"WriteComm: fd %d, ptr %d, length %d\n", fd, (long) lpvBuf, cbWrite);
880 #endif
882 if ((ptr = GetDeviceStruct(fd)) == NULL) {
883 commerror = IE_BADID;
884 return -1;
887 if (ptr->suspended) {
888 commerror = IE_HARDWARE;
889 return -1;
892 #ifdef DEBUG_COMM
893 for (x=0; x != cbWrite ; x++)
894 fprintf(stderr,"%c", *(lpvBuf + x) );
895 #endif
897 length = write(fd, (void *) lpvBuf, cbWrite);
899 if (length == -1) {
900 commerror = WinError();
901 return -1;
902 } else {
903 commerror = 0;
904 return length;