Release 941122
[wine/multimedia.git] / misc / comm.c
blob49c08cea2a0c5ca0a524f17f9ea8dc0dd1915fc7
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 "wine.h"
20 #include "windows.h"
21 #include "comm.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 GetPrivateProfileString("serialports", option, "*", temp, sizeof(temp), WINE_INI);
44 if (!strcmp(temp, "*") || *temp == '\0')
45 COM[x].devicename = NULL;
46 else {
47 btemp = index(temp,',');
48 if (btemp != NULL) {
49 *btemp++ = '\0';
50 COM[x].baudrate = atoi(btemp);
51 } else {
52 COM[x].baudrate = -1;
54 stat(temp, &st);
55 if (!S_ISCHR(st.st_mode))
56 fprintf(stderr,"comm: can 't use `%s' as %s !\n", temp, option);
57 else
58 if ((COM[x].devicename = malloc(strlen(temp)+1)) == NULL)
59 fprintf(stderr,"comm: can't malloc for device info!\n");
60 else {
61 COM[x].fd = 0;
62 strcpy(COM[x].devicename, temp);
64 dprintf_comm(stddeb,
65 "Comm_Init: %s = %s\n", option, COM[x].devicename);
68 strcpy(option, "LPTx");
69 option[3] = '1' + x;
70 option[4] = '\0';
72 GetPrivateProfileString("parallelports", option, "*", temp, sizeof(temp), WINE_INI);
73 if (!strcmp(temp, "*") || *temp == '\0')
74 LPT[x].devicename = NULL;
75 else {
76 stat(temp, &st);
77 if (!S_ISCHR(st.st_mode))
78 fprintf(stderr,"comm: can 't use `%s' as %s !\n", temp, option);
79 else
80 if ((LPT[x].devicename = malloc(strlen(temp)+1)) == NULL)
81 fprintf(stderr,"comm: can't malloc for device info!\n");
82 else {
83 LPT[x].fd = 0;
84 strcpy(LPT[x].devicename, temp);
86 dprintf_comm(stddeb,
87 "Comm_Init: %s = %s\n", option, LPT[x].devicename);
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 dprintf_comm(stddeb, "WinError: errno = %d\n", errno);
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 dprintf_comm(stddeb,
154 "BuildCommDCB: (%s), ptr %p\n", device, lpdcb);
155 commerror = 0;
157 if (!strncasecmp(device,"COM",3)) {
158 port = device[3] - '0';
161 if (port-- == 0) {
162 fprintf(stderr, "comm: BUG ! COM0 can't exists!.\n");
163 commerror = IE_BADID;
166 if (!ValidCOMPort(port)) {
167 commerror = IE_BADID;
168 return -1;
171 if (!COM[port].fd) {
172 OpenComm(device, 0, 0);
174 lpdcb->Id = COM[port].fd;
176 if (!*(device+4))
177 return 0;
179 if (*(device+4) != ':')
180 return -1;
182 strcpy(temp,device+5);
183 ptr = strtok(temp, ",");
185 if (COM[port].baudrate > 0)
186 lpdcb->BaudRate = COM[port].baudrate;
187 else
188 lpdcb->BaudRate = atoi(ptr);
189 dprintf_comm(stddeb,"BuildCommDCB: baudrate (%d)\n", lpdcb->BaudRate);
191 ptr = strtok(NULL, ",");
192 if (islower(*ptr))
193 *ptr = toupper(*ptr);
195 dprintf_comm(stddeb,"BuildCommDCB: parity (%c)\n", *ptr);
196 switch (*ptr) {
197 case 'N':
198 lpdcb->Parity = NOPARITY;
199 lpdcb->fParity = 0;
200 break;
202 lpdcb->fParity = 1;
204 case 'E':
205 lpdcb->Parity = EVENPARITY;
206 break;
207 case 'M':
208 lpdcb->Parity = MARKPARITY;
209 break;
210 case 'O':
211 lpdcb->Parity = ODDPARITY;
212 break;
213 default:
214 fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
215 return -1;
218 ptr = strtok(NULL, ",");
219 dprintf_comm(stddeb, "BuildCommDCB: charsize (%c)\n", *ptr);
220 lpdcb->ByteSize = *ptr - '0';
222 ptr = strtok(NULL, ",");
223 dprintf_comm(stddeb, "BuildCommDCB: stopbits (%c)\n", *ptr);
224 switch (*ptr) {
225 case '1':
226 lpdcb->StopBits = ONESTOPBIT;
227 break;
228 case '2':
229 lpdcb->StopBits = TWOSTOPBITS;
230 break;
231 default:
232 fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
233 return -1;
237 return 0;
240 int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue)
242 int port, fd;
244 dprintf_comm(stddeb,
245 "OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
246 commerror = 0;
248 if (!strncasecmp(device,"COM",3)) {
249 port = device[3] - '0';
251 if (port-- == 0) {
252 fprintf(stderr, "comm: BUG ! COM0 doesn't exists!.\n");
253 commerror = IE_BADID;
256 dprintf_comm(stddeb,
257 "OpenComm: %s = %s\n", device, COM[port].devicename);
259 if (!ValidCOMPort(port)) {
260 commerror = IE_BADID;
261 return -1;
263 if (COM[port].fd) {
264 return COM[port].fd;
267 fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK);
268 if (fd == -1) {
269 commerror = WinError();
270 return -1;
271 } else {
272 COM[port].fd = fd;
273 return fd;
276 else
277 if (!strncasecmp(device,"LPT",3)) {
278 port = device[3] - '0';
280 if (!ValidLPTPort(port)) {
281 commerror = IE_BADID;
282 return -1;
284 if (LPT[port].fd) {
285 commerror = IE_OPEN;
286 return -1;
289 fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
290 if (fd == -1) {
291 commerror = WinError();
292 return -1;
293 } else {
294 LPT[port].fd = fd;
295 return fd;
298 return 0;
301 int CloseComm(int fd)
303 dprintf_comm(stddeb,"CloseComm: fd %d\n", fd);
304 if (close(fd) == -1) {
305 commerror = WinError();
306 return -1;
307 } else {
308 commerror = 0;
309 return 0;
313 int SetCommBreak(int fd)
315 struct DosDeviceStruct *ptr;
317 dprintf_comm(stddeb,"SetCommBreak: fd: %d\n", fd);
318 if ((ptr = GetDeviceStruct(fd)) == NULL) {
319 commerror = IE_BADID;
320 return -1;
323 ptr->suspended = 1;
324 commerror = 0;
325 return 0;
328 int ClearCommBreak(int fd)
330 struct DosDeviceStruct *ptr;
332 dprintf_comm(stddeb,"ClearCommBreak: fd: %d\n", fd);
333 if ((ptr = GetDeviceStruct(fd)) == NULL) {
334 commerror = IE_BADID;
335 return -1;
338 ptr->suspended = 0;
339 commerror = 0;
340 return 0;
343 LONG EscapeCommFunction(int fd, int nFunction)
345 int max;
346 struct termios port;
348 dprintf_comm(stddeb,
349 "EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
350 if (tcgetattr(fd, &port) == -1) {
351 commerror = WinError();
352 return -1;
355 switch (nFunction) {
356 case RESETDEV:
357 break;
359 case GETMAXCOM:
360 for (max = MAX_PORTS;!COM[max].devicename;max--)
362 return max;
363 break;
365 case GETMAXLPT:
366 for (max = MAX_PORTS;!LPT[max].devicename;max--)
368 return 0x80 + max;
369 break;
371 case CLRDTR:
372 port.c_cflag &= TIOCM_DTR;
373 break;
375 case CLRRTS:
376 port.c_cflag &= TIOCM_RTS;
377 break;
379 case SETDTR:
380 port.c_cflag |= CRTSCTS;
381 break;
383 case SETRTS:
384 port.c_cflag |= CRTSCTS;
385 break;
387 case SETXOFF:
388 port.c_iflag |= IXOFF;
389 break;
391 case SETXON:
392 port.c_iflag |= IXON;
393 break;
395 default:
396 fprintf(stderr,
397 "EscapeCommFunction fd: %d, unknown function: %d\n",
398 fd, nFunction);
399 break;
402 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
403 commerror = WinError();
404 return -1;
405 } else {
406 commerror = 0;
407 return 0;
411 int FlushComm(int fd, int fnQueue)
413 int queue;
415 dprintf_comm(stddeb,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
416 switch (fnQueue) {
417 case 0:
418 queue = TCOFLUSH;
419 break;
420 case 1:
421 queue = TCIFLUSH;
422 break;
423 default:
424 fprintf(stderr,
425 "FlushComm fd: %d, UNKNOWN queue: %d\n",
426 fd, fnQueue);
427 return -1;
430 if (tcflush(fd, fnQueue)) {
431 commerror = WinError();
432 return -1;
433 } else {
434 commerror = 0;
435 return 0;
439 int GetCommError(int fd, COMSTAT FAR *lpStat)
441 int temperror;
443 dprintf_comm(stddeb,
444 "GetCommError: fd %d (current error %d)\n", fd, commerror);
445 temperror = commerror;
446 commerror = 0;
447 return(temperror);
450 UINT FAR* SetCommEventMask(int fd, UINT fuEvtMask)
452 dprintf_comm(stddeb,
453 "SetCommEventMask: fd %d, mask %d\n", fd, fuEvtMask);
454 eventmask |= fuEvtMask;
455 return (UINT *)&eventmask;
458 UINT GetCommEventMask(int fd, int fnEvtClear)
460 dprintf_comm(stddeb,
461 "GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
462 eventmask &= ~fnEvtClear;
463 return eventmask;
466 int SetCommState(DCB FAR *lpdcb)
468 struct termios port;
469 struct DosDeviceStruct *ptr;
471 dprintf_comm(stddeb,
472 "SetCommState: fd %d, ptr %p\n", lpdcb->Id, lpdcb);
473 if (tcgetattr(lpdcb->Id, &port) == -1) {
474 commerror = WinError();
475 return -1;
478 port.c_cc[VMIN] = 0;
479 port.c_cc[VTIME] = 1;
481 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
482 port.c_iflag |= (IGNBRK);
484 port.c_oflag &= ~(OPOST);
486 port.c_cflag &= ~(HUPCL);
487 port.c_cflag |= CLOCAL | CREAD;
489 port.c_lflag &= ~(ICANON|ECHO|ISIG);
490 port.c_lflag |= NOFLSH;
492 if ((ptr = GetDeviceStruct(lpdcb->Id)) == NULL) {
493 commerror = IE_BADID;
494 return -1;
496 if (ptr->baudrate > 0)
497 lpdcb->BaudRate = ptr->baudrate;
498 dprintf_comm(stddeb,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
499 #ifdef CBAUD
500 port.c_cflag &= ~CBAUD;
501 switch (lpdcb->BaudRate) {
502 case 110:
503 case CBR_110:
504 port.c_cflag |= B110;
505 break;
506 case 300:
507 case CBR_300:
508 port.c_cflag |= B300;
509 break;
510 case 600:
511 case CBR_600:
512 port.c_cflag |= B600;
513 break;
514 case 1200:
515 case CBR_1200:
516 port.c_cflag |= B1200;
517 break;
518 case 2400:
519 case CBR_2400:
520 port.c_cflag |= B2400;
521 break;
522 case 4800:
523 case CBR_4800:
524 port.c_cflag |= B4800;
525 break;
526 case 9600:
527 case CBR_9600:
528 port.c_cflag |= B9600;
529 break;
530 case 19200:
531 case CBR_19200:
532 port.c_cflag |= B19200;
533 break;
534 case 38400:
535 case CBR_38400:
536 port.c_cflag |= B38400;
537 break;
538 default:
539 commerror = IE_BAUDRATE;
540 return -1;
542 #else
543 switch (lpdcb->BaudRate) {
544 case 110:
545 case CBR_110:
546 port.c_ospeed = B110;
547 break;
548 case 300:
549 case CBR_300:
550 port.c_ospeed = B300;
551 break;
552 case 600:
553 case CBR_600:
554 port.c_ospeed = B600;
555 break;
556 case 1200:
557 case CBR_1200:
558 port.c_ospeed = B1200;
559 break;
560 case 2400:
561 case CBR_2400:
562 port.c_ospeed = B2400;
563 break;
564 case 4800:
565 case CBR_4800:
566 port.c_ospeed = B4800;
567 break;
568 case 9600:
569 case CBR_9600:
570 port.c_ospeed = B9600;
571 break;
572 case 19200:
573 case CBR_19200:
574 port.c_ospeed = B19200;
575 break;
576 case 38400:
577 case CBR_38400:
578 port.c_ospeed = B38400;
579 break;
580 default:
581 commerror = IE_BAUDRATE;
582 return -1;
584 port.c_ispeed = port.c_ospeed;
585 #endif
586 dprintf_comm(stddeb,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
587 port.c_cflag &= ~CSIZE;
588 switch (lpdcb->ByteSize) {
589 case 5:
590 port.c_cflag |= CS5;
591 break;
592 case 6:
593 port.c_cflag |= CS6;
594 break;
595 case 7:
596 port.c_cflag |= CS7;
597 break;
598 case 8:
599 port.c_cflag |= CS8;
600 break;
601 default:
602 commerror = IE_BYTESIZE;
603 return -1;
606 dprintf_comm(stddeb,"SetCommState: parity %d\n",lpdcb->Parity);
607 port.c_cflag &= ~(PARENB | PARODD);
608 if (lpdcb->fParity)
609 switch (lpdcb->Parity) {
610 case NOPARITY:
611 port.c_iflag &= ~INPCK;
612 break;
613 case ODDPARITY:
614 port.c_cflag |= (PARENB | PARODD);
615 port.c_iflag |= INPCK;
616 break;
617 case EVENPARITY:
618 port.c_cflag |= PARENB;
619 port.c_iflag |= INPCK;
620 break;
621 default:
622 commerror = IE_BYTESIZE;
623 return -1;
627 dprintf_comm(stddeb,"SetCommState: stopbits %d\n",lpdcb->StopBits);
628 switch (lpdcb->StopBits) {
629 case ONESTOPBIT:
630 port.c_cflag &= ~CSTOPB;
631 break;
632 case TWOSTOPBITS:
633 port.c_cflag |= CSTOPB;
634 break;
635 default:
636 commerror = IE_BYTESIZE;
637 return -1;
640 if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
641 port.c_cflag |= CRTSCTS;
643 if (lpdcb->fDtrDisable)
644 port.c_cflag &= ~CRTSCTS;
646 if (lpdcb->fInX)
647 port.c_iflag |= IXON;
648 if (lpdcb->fOutX)
649 port.c_iflag |= IXOFF;
651 if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
652 commerror = WinError();
653 return -1;
654 } else {
655 commerror = 0;
656 return 0;
660 int GetCommState(int fd, DCB FAR *lpdcb)
662 struct termios port;
664 dprintf_comm(stddeb,"GetCommState: fd %d, ptr %p\n", fd, lpdcb);
665 if (tcgetattr(fd, &port) == -1) {
666 commerror = WinError();
667 return -1;
670 lpdcb->Id = fd;
672 #ifdef CBAUD
673 switch (port.c_cflag & CBAUD) {
674 #else
675 switch (port.c_ospeed) {
676 #endif
677 case B110:
678 lpdcb->BaudRate = 110;
679 break;
680 case B300:
681 lpdcb->BaudRate = 300;
682 break;
683 case B600:
684 lpdcb->BaudRate = 600;
685 break;
686 case B1200:
687 lpdcb->BaudRate = 1200;
688 break;
689 case B2400:
690 lpdcb->BaudRate = 2400;
691 break;
692 case B4800:
693 lpdcb->BaudRate = 4800;
694 break;
695 case B9600:
696 lpdcb->BaudRate = 9600;
697 break;
698 case B19200:
699 lpdcb->BaudRate = 19200;
700 break;
701 case B38400:
702 lpdcb->BaudRate = 38400;
703 break;
706 switch (port.c_cflag & CSIZE) {
707 case CS5:
708 lpdcb->ByteSize = 5;
709 break;
710 case CS6:
711 lpdcb->ByteSize = 6;
712 break;
713 case CS7:
714 lpdcb->ByteSize = 7;
715 break;
716 case CS8:
717 lpdcb->ByteSize = 8;
718 break;
721 switch (port.c_cflag & ~(PARENB | PARODD)) {
722 case 0:
723 lpdcb->fParity = NOPARITY;
724 break;
725 case PARENB:
726 lpdcb->fParity = EVENPARITY;
727 break;
728 case (PARENB | PARODD):
729 lpdcb->fParity = ODDPARITY;
730 break;
733 if (port.c_cflag & CSTOPB)
734 lpdcb->StopBits = TWOSTOPBITS;
735 else
736 lpdcb->StopBits = ONESTOPBIT;
738 lpdcb->RlsTimeout = 50;
739 lpdcb->CtsTimeout = 50;
740 lpdcb->DsrTimeout = 50;
741 lpdcb->fNull = 0;
742 lpdcb->fChEvt = 0;
743 lpdcb->fBinary = 1;
745 lpdcb->fDtrDisable = 0;
746 if (port.c_cflag & CRTSCTS) {
747 lpdcb->fDtrflow = 1;
748 lpdcb->fRtsflow = 1;
749 lpdcb->fOutxCtsFlow = 1;
750 lpdcb->fOutxDsrFlow = 1;
751 } else
752 lpdcb->fDtrDisable = 1;
754 if (port.c_iflag & IXON)
755 lpdcb->fInX = 1;
756 else
757 lpdcb->fInX = 0;
759 if (port.c_iflag & IXOFF)
760 lpdcb->fOutX = 1;
761 else
762 lpdcb->fOutX = 0;
764 lpdcb->XonChar =
765 lpdcb->XoffChar =
767 lpdcb->XonLim = 10;
768 lpdcb->XoffLim = 10;
770 commerror = 0;
771 return 0;
774 int TransmitCommChar(int fd, char chTransmit)
776 struct DosDeviceStruct *ptr;
778 dprintf_comm(stddeb,
779 "TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
780 if ((ptr = GetDeviceStruct(fd)) == NULL) {
781 commerror = IE_BADID;
782 return -1;
785 if (ptr->suspended) {
786 commerror = IE_HARDWARE;
787 return -1;
790 if (write(fd, (void *) &chTransmit, 1) == -1) {
791 commerror = WinError();
792 return -1;
793 } else {
794 commerror = 0;
795 return 0;
799 int UngetCommChar(int fd, char chUnget)
801 struct DosDeviceStruct *ptr;
803 dprintf_comm(stddeb,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
804 if ((ptr = GetDeviceStruct(fd)) == NULL) {
805 commerror = IE_BADID;
806 return -1;
809 if (ptr->suspended) {
810 commerror = IE_HARDWARE;
811 return -1;
814 ptr->unget = 1;
815 ptr->unget_byte = chUnget;
817 commerror = 0;
818 return 0;
821 int ReadComm(int fd, LPSTR lpvBuf, int cbRead)
823 int status, length;
824 struct DosDeviceStruct *ptr;
826 dprintf_comm(stddeb,
827 "ReadComm: fd %d, ptr %p, length %d\n", fd, lpvBuf, cbRead);
828 if ((ptr = GetDeviceStruct(fd)) == NULL) {
829 commerror = IE_BADID;
830 return -1;
833 if (ptr->suspended) {
834 commerror = IE_HARDWARE;
835 return -1;
838 if (ptr->unget) {
839 *lpvBuf = ptr->unget_byte;
840 lpvBuf++;
841 ptr->unget = 0;
843 length = 1;
844 } else
845 length = 0;
847 status = read(fd, (void *) lpvBuf, cbRead);
849 if (status == -1) {
850 if (errno != EAGAIN) {
851 commerror = WinError();
852 return -1 - length;
853 } else {
854 commerror = 0;
855 return length;
857 } else {
858 commerror = 0;
859 return length + status;
863 int WriteComm(int fd, LPSTR lpvBuf, int cbWrite)
865 int x, length;
866 struct DosDeviceStruct *ptr;
868 dprintf_comm(stddeb,"WriteComm: fd %d, ptr %p, length %d\n",
869 fd, lpvBuf, cbWrite);
870 if ((ptr = GetDeviceStruct(fd)) == NULL) {
871 commerror = IE_BADID;
872 return -1;
875 if (ptr->suspended) {
876 commerror = IE_HARDWARE;
877 return -1;
880 for (x=0; x != cbWrite ; x++)
881 dprintf_comm(stddeb,"%c", *(lpvBuf + x) );
883 length = write(fd, (void *) lpvBuf, cbWrite);
885 if (length == -1) {
886 commerror = WinError();
887 return -1;
888 } else {
889 commerror = 0;
890 return length;