Release 960506
[wine/multimedia.git] / misc / comm.c
blob73811a921cdfda0e4a5320acce04bac5aa6a1231
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 #ifdef TIOCM_DTR
356 case CLRDTR:
357 port.c_cflag &= TIOCM_DTR;
358 break;
359 #endif
361 #ifdef TIOCM_RTS
362 case CLRRTS:
363 port.c_cflag &= TIOCM_RTS;
364 break;
365 #endif
367 #ifdef CRTSCTS
368 case SETDTR:
369 port.c_cflag |= CRTSCTS;
370 break;
372 case SETRTS:
373 port.c_cflag |= CRTSCTS;
374 break;
375 #endif
377 case SETXOFF:
378 port.c_iflag |= IXOFF;
379 break;
381 case SETXON:
382 port.c_iflag |= IXON;
383 break;
385 default:
386 fprintf(stderr,
387 "EscapeCommFunction fd: %d, unknown function: %d\n",
388 fd, nFunction);
389 break;
392 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
393 commerror = WinError();
394 return -1;
395 } else {
396 commerror = 0;
397 return 0;
401 int FlushComm(int fd, int fnQueue)
403 int queue;
405 dprintf_comm(stddeb,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
406 switch (fnQueue) {
407 case 0:
408 queue = TCOFLUSH;
409 break;
410 case 1:
411 queue = TCIFLUSH;
412 break;
413 default:
414 fprintf(stderr,
415 "FlushComm fd: %d, UNKNOWN queue: %d\n",
416 fd, fnQueue);
417 return -1;
420 if (tcflush(fd, fnQueue)) {
421 commerror = WinError();
422 return -1;
423 } else {
424 commerror = 0;
425 return 0;
429 int GetCommError(int fd, COMSTAT *lpStat)
431 int temperror;
433 dprintf_comm(stddeb,
434 "GetCommError: fd %d (current error %d)\n", fd, commerror);
435 temperror = commerror;
436 commerror = 0;
437 return(temperror);
440 UINT * SetCommEventMask(int fd, UINT fuEvtMask)
442 dprintf_comm(stddeb,
443 "SetCommEventMask: fd %d, mask %d\n", fd, fuEvtMask);
444 eventmask |= fuEvtMask;
445 return (UINT *)&eventmask;
448 UINT GetCommEventMask(int fd, int fnEvtClear)
450 dprintf_comm(stddeb,
451 "GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
452 eventmask &= ~fnEvtClear;
453 return eventmask;
456 int SetCommState(DCB *lpdcb)
458 struct termios port;
459 struct DosDeviceStruct *ptr;
461 dprintf_comm(stddeb,
462 "SetCommState: fd %d, ptr %p\n", lpdcb->Id, lpdcb);
463 if (tcgetattr(lpdcb->Id, &port) == -1) {
464 commerror = WinError();
465 return -1;
468 port.c_cc[VMIN] = 0;
469 port.c_cc[VTIME] = 1;
471 #ifdef IMAXBEL
472 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
473 #else
474 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
475 #endif
476 port.c_iflag |= (IGNBRK);
478 port.c_oflag &= ~(OPOST);
480 port.c_cflag &= ~(HUPCL);
481 port.c_cflag |= CLOCAL | CREAD;
483 port.c_lflag &= ~(ICANON|ECHO|ISIG);
484 port.c_lflag |= NOFLSH;
486 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
487 commerror = IE_BADID;
488 return -1;
490 if (ptr->baudrate > 0)
491 lpdcb->BaudRate = ptr->baudrate;
492 dprintf_comm(stddeb,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
493 #ifdef CBAUD
494 port.c_cflag &= ~CBAUD;
495 switch (lpdcb->BaudRate) {
496 case 110:
497 case CBR_110:
498 port.c_cflag |= B110;
499 break;
500 case 300:
501 case CBR_300:
502 port.c_cflag |= B300;
503 break;
504 case 600:
505 case CBR_600:
506 port.c_cflag |= B600;
507 break;
508 case 1200:
509 case CBR_1200:
510 port.c_cflag |= B1200;
511 break;
512 case 2400:
513 case CBR_2400:
514 port.c_cflag |= B2400;
515 break;
516 case 4800:
517 case CBR_4800:
518 port.c_cflag |= B4800;
519 break;
520 case 9600:
521 case CBR_9600:
522 port.c_cflag |= B9600;
523 break;
524 case 19200:
525 case CBR_19200:
526 port.c_cflag |= B19200;
527 break;
528 case 38400:
529 case CBR_38400:
530 port.c_cflag |= B38400;
531 break;
532 default:
533 commerror = IE_BAUDRATE;
534 return -1;
536 #else
537 switch (lpdcb->BaudRate) {
538 case 110:
539 case CBR_110:
540 port.c_ospeed = B110;
541 break;
542 case 300:
543 case CBR_300:
544 port.c_ospeed = B300;
545 break;
546 case 600:
547 case CBR_600:
548 port.c_ospeed = B600;
549 break;
550 case 1200:
551 case CBR_1200:
552 port.c_ospeed = B1200;
553 break;
554 case 2400:
555 case CBR_2400:
556 port.c_ospeed = B2400;
557 break;
558 case 4800:
559 case CBR_4800:
560 port.c_ospeed = B4800;
561 break;
562 case 9600:
563 case CBR_9600:
564 port.c_ospeed = B9600;
565 break;
566 case 19200:
567 case CBR_19200:
568 port.c_ospeed = B19200;
569 break;
570 case 38400:
571 case CBR_38400:
572 port.c_ospeed = B38400;
573 break;
574 default:
575 commerror = IE_BAUDRATE;
576 return -1;
578 port.c_ispeed = port.c_ospeed;
579 #endif
580 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
581 port.c_cflag &= ~CSIZE;
582 switch (lpdcb->ByteSize) {
583 case 5:
584 port.c_cflag |= CS5;
585 break;
586 case 6:
587 port.c_cflag |= CS6;
588 break;
589 case 7:
590 port.c_cflag |= CS7;
591 break;
592 case 8:
593 port.c_cflag |= CS8;
594 break;
595 default:
596 commerror = IE_BYTESIZE;
597 return -1;
600 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
601 port.c_cflag &= ~(PARENB | PARODD);
602 if (lpdcb->fParity)
603 switch (lpdcb->Parity) {
604 case NOPARITY:
605 port.c_iflag &= ~INPCK;
606 break;
607 case ODDPARITY:
608 port.c_cflag |= (PARENB | PARODD);
609 port.c_iflag |= INPCK;
610 break;
611 case EVENPARITY:
612 port.c_cflag |= PARENB;
613 port.c_iflag |= INPCK;
614 break;
615 default:
616 commerror = IE_BYTESIZE;
617 return -1;
621 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
622 switch (lpdcb->StopBits) {
623 case ONESTOPBIT:
624 port.c_cflag &= ~CSTOPB;
625 break;
626 case TWOSTOPBITS:
627 port.c_cflag |= CSTOPB;
628 break;
629 default:
630 commerror = IE_BYTESIZE;
631 return -1;
633 #ifdef CRTSCTS
635 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
636 port.c_cflag |= CRTSCTS;
638 if (lpdcb->fDtrDisable)
639 port.c_cflag &= ~CRTSCTS;
640 #endif
641 if (lpdcb->fInX)
642 port.c_iflag |= IXON;
643 if (lpdcb->fOutX)
644 port.c_iflag |= IXOFF;
646 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
647 commerror = WinError();
648 return -1;
649 } else {
650 commerror = 0;
651 return 0;
655 int GetCommState(int fd, DCB *lpdcb)
657 struct termios port;
659 dprintf_comm(stddeb,"GetCommState: fd %d, ptr %p\n", fd, lpdcb);
660 if (tcgetattr(fd, &port) == -1) {
661 commerror = WinError();
662 return -1;
665 lpdcb->Id = fd;
667 #ifdef CBAUD
668 switch (port.c_cflag & CBAUD) {
669 #else
670 switch (port.c_ospeed) {
671 #endif
672 case B110:
673 lpdcb->BaudRate = 110;
674 break;
675 case B300:
676 lpdcb->BaudRate = 300;
677 break;
678 case B600:
679 lpdcb->BaudRate = 600;
680 break;
681 case B1200:
682 lpdcb->BaudRate = 1200;
683 break;
684 case B2400:
685 lpdcb->BaudRate = 2400;
686 break;
687 case B4800:
688 lpdcb->BaudRate = 4800;
689 break;
690 case B9600:
691 lpdcb->BaudRate = 9600;
692 break;
693 case B19200:
694 lpdcb->BaudRate = 19200;
695 break;
696 case B38400:
697 lpdcb->BaudRate = 38400;
698 break;
701 switch (port.c_cflag & CSIZE) {
702 case CS5:
703 lpdcb->ByteSize = 5;
704 break;
705 case CS6:
706 lpdcb->ByteSize = 6;
707 break;
708 case CS7:
709 lpdcb->ByteSize = 7;
710 break;
711 case CS8:
712 lpdcb->ByteSize = 8;
713 break;
716 switch (port.c_cflag & ~(PARENB | PARODD)) {
717 case 0:
718 lpdcb->fParity = NOPARITY;
719 break;
720 case PARENB:
721 lpdcb->fParity = EVENPARITY;
722 break;
723 case (PARENB | PARODD):
724 lpdcb->fParity = ODDPARITY;
725 break;
728 if (port.c_cflag & CSTOPB)
729 lpdcb->StopBits = TWOSTOPBITS;
730 else
731 lpdcb->StopBits = ONESTOPBIT;
733 lpdcb->RlsTimeout = 50;
734 lpdcb->CtsTimeout = 50;
735 lpdcb->DsrTimeout = 50;
736 lpdcb->fNull = 0;
737 lpdcb->fChEvt = 0;
738 lpdcb->fBinary = 1;
739 lpdcb->fDtrDisable = 0;
741 #ifdef CRTSCTS
743 if (port.c_cflag & CRTSCTS) {
744 lpdcb->fDtrflow = 1;
745 lpdcb->fRtsflow = 1;
746 lpdcb->fOutxCtsFlow = 1;
747 lpdcb->fOutxDsrFlow = 1;
748 } else
749 #endif
750 lpdcb->fDtrDisable = 1;
752 if (port.c_iflag & IXON)
753 lpdcb->fInX = 1;
754 else
755 lpdcb->fInX = 0;
757 if (port.c_iflag & IXOFF)
758 lpdcb->fOutX = 1;
759 else
760 lpdcb->fOutX = 0;
762 lpdcb->XonChar =
763 lpdcb->XoffChar =
765 lpdcb->XonLim = 10;
766 lpdcb->XoffLim = 10;
768 commerror = 0;
769 return 0;
772 int TransmitCommChar(int fd, char chTransmit)
774 struct DosDeviceStruct *ptr;
776 dprintf_comm(stddeb,
777 "TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
778 if ((ptr = GetDeviceStruct(fd)) == NULL) {
779 commerror = IE_BADID;
780 return -1;
783 if (ptr->suspended) {
784 commerror = IE_HARDWARE;
785 return -1;
788 if (write(fd, (void *) &chTransmit, 1) == -1) {
789 commerror = WinError();
790 return -1;
791 } else {
792 commerror = 0;
793 return 0;
797 int UngetCommChar(int fd, char chUnget)
799 struct DosDeviceStruct *ptr;
801 dprintf_comm(stddeb,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
802 if ((ptr = GetDeviceStruct(fd)) == NULL) {
803 commerror = IE_BADID;
804 return -1;
807 if (ptr->suspended) {
808 commerror = IE_HARDWARE;
809 return -1;
812 ptr->unget = 1;
813 ptr->unget_byte = chUnget;
815 commerror = 0;
816 return 0;
819 int ReadComm(int fd, LPSTR lpvBuf, int cbRead)
821 int status, length;
822 struct DosDeviceStruct *ptr;
824 dprintf_comm(stddeb,
825 "ReadComm: fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
826 if ((ptr = GetDeviceStruct(fd)) == NULL) {
827 commerror = IE_BADID;
828 return -1;
831 if (ptr->suspended) {
832 commerror = IE_HARDWARE;
833 return -1;
836 if (ptr->unget) {
837 *lpvBuf = ptr->unget_byte;
838 lpvBuf++;
839 ptr->unget = 0;
841 length = 1;
842 } else
843 length = 0;
845 status = read(fd, (void *) lpvBuf, cbRead);
847 if (status == -1) {
848 if (errno != EAGAIN) {
849 commerror = WinError();
850 return -1 - length;
851 } else {
852 commerror = 0;
853 return length;
855 } else {
856 commerror = 0;
857 return length + status;
861 int WriteComm(int fd, LPSTR lpvBuf, int cbWrite)
863 int x, length;
864 struct DosDeviceStruct *ptr;
866 dprintf_comm(stddeb,"WriteComm: fd %d, ptr %p, length %d\n",
867 fd, lpvBuf, cbWrite);
868 if ((ptr = GetDeviceStruct(fd)) == NULL) {
869 commerror = IE_BADID;
870 return -1;
873 if (ptr->suspended) {
874 commerror = IE_HARDWARE;
875 return -1;
878 for (x=0; x != cbWrite ; x++)
879 dprintf_comm(stddeb,"%c", *(lpvBuf + x) );
881 length = write(fd, (void *) lpvBuf, cbWrite);
883 if (length == -1) {
884 commerror = WinError();
885 return -1;
886 } else {
887 commerror = 0;
888 return length;