2 * "$Id: serial.c 5553 2006-05-20 12:22:27Z mike $"
4 * Serial port backend for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * main() - Send a file to the printer or server.
29 * list_devices() - List all serial devices.
33 * Include necessary headers.
36 #include <cups/backend.h>
37 #include <cups/cups.h>
41 #include <cups/string.h>
45 # include <sys/modem.h>
55 # include <sys/time.h>
57 # include <sys/select.h>
59 # ifdef HAVE_SYS_IOCTL_H
60 # include <sys/ioctl.h>
61 # endif /* HAVE_SYS_IOCTL_H */
66 # ifndef INV_EPP_ECP_PLP
67 # define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */
68 # define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */
69 # define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */
70 # define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */
71 # define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */
72 # endif /* !INV_EPP_ECP_PLP */
77 # define CRTSCTS CNEW_RTSCTS
80 # endif /* CNEW_RTSCTS */
83 #if defined(__APPLE__)
84 # include <CoreFoundation/CoreFoundation.h>
85 # include <IOKit/IOKitLib.h>
86 # include <IOKit/serial/IOSerialKeys.h>
87 # include <IOKit/IOBSD.h>
88 #endif /* __APPLE__ */
90 #if defined(__linux) && defined(TIOCGSERIAL)
91 # include <linux/serial.h>
92 # include <linux/ioctl.h>
93 #endif /* __linux && TIOCGSERIAL */
100 void list_devices(void);
104 * 'main()' - Send a file to the printer or server.
108 * printer-uri job-id user title copies options [file]
111 int /* O - Exit status */
112 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
113 char *argv
[]) /* I - Command-line arguments */
115 char method
[255], /* Method in URI */
116 hostname
[1024], /* Hostname */
117 username
[255], /* Username info (not used) */
118 resource
[1024], /* Resource info (device and options) */
119 *options
, /* Pointer to options */
120 name
[255], /* Name of option */
121 value
[255], /* Value of option */
122 *ptr
; /* Pointer into name or value */
123 int port
; /* Port number (not used) */
124 int fp
; /* Print file */
125 int copies
; /* Number of copies to print */
126 int fd
; /* Parallel device */
127 int rbytes
; /* Number of bytes read */
128 int wbytes
; /* Number of bytes written */
129 size_t nbytes
, /* Number of bytes read */
130 tbytes
; /* Total number of bytes written */
131 int dtrdsr
; /* Do dtr/dsr flow control? */
132 int bufsize
; /* Size of output buffer for writes */
133 char buffer
[8192], /* Output buffer */
134 *bufptr
; /* Pointer into buffer */
135 struct termios opts
; /* Serial port options */
136 struct termios origopts
; /* Original port options */
137 fd_set input
, /* Input set for select() */
138 output
; /* Output set for select() */
139 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
140 struct sigaction action
; /* Actions for POSIX signals */
141 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
145 * Make sure status messages are not buffered...
148 setbuf(stderr
, NULL
);
151 * Ignore SIGPIPE signals...
155 sigset(SIGPIPE
, SIG_IGN
);
156 #elif defined(HAVE_SIGACTION)
157 memset(&action
, 0, sizeof(action
));
158 action
.sa_handler
= SIG_IGN
;
159 sigaction(SIGPIPE
, &action
, NULL
);
161 signal(SIGPIPE
, SIG_IGN
);
162 #endif /* HAVE_SIGSET */
165 * Check command-line...
171 return (CUPS_BACKEND_OK
);
173 else if (argc
< 6 || argc
> 7)
175 fputs("Usage: serial job-id user title copies options [file]\n", stderr
);
176 return (CUPS_BACKEND_FAILED
);
180 * If we have 7 arguments, print the file named on the command-line.
181 * Otherwise, send stdin instead...
192 * Try to open the print file...
195 if ((fp
= open(argv
[6], O_RDONLY
)) < 0)
197 perror("ERROR: unable to open print file");
198 return (CUPS_BACKEND_FAILED
);
201 copies
= atoi(argv
[4]);
205 * Extract the device name and options from the URI...
208 httpSeparateURI(HTTP_URI_CODING_ALL
, cupsBackendDeviceURI(argv
),
209 method
, sizeof(method
), username
, sizeof(username
),
210 hostname
, sizeof(hostname
), &port
,
211 resource
, sizeof(resource
));
214 * See if there are any options...
217 if ((options
= strchr(resource
, '?')) != NULL
)
220 * Yup, terminate the device name string and move to the first
221 * character of the options...
228 * Open the serial port device...
231 fputs("STATE: +connecting-to-device\n", stderr
);
235 if ((fd
= open(resource
, O_WRONLY
| O_NOCTTY
| O_EXCL
| O_NDELAY
)) == -1)
237 if (getenv("CLASS") != NULL
)
240 * If the CLASS environment variable is set, the job was submitted
241 * to a class and not to a specific queue. In this case, we want
242 * to abort immediately so that the job can be requeued on the next
243 * available printer in the class.
246 fputs("INFO: Unable to open serial port, queuing on next printer in class...\n",
250 * Sleep 5 seconds to keep the job from requeuing too rapidly...
255 return (CUPS_BACKEND_FAILED
);
260 fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr
);
265 fprintf(stderr
, "ERROR: Unable to open serial port device file \"%s\": %s\n",
266 resource
, strerror(errno
));
267 return (CUPS_BACKEND_FAILED
);
273 fputs("STATE: -connecting-to-device\n", stderr
);
276 * Set any options provided...
279 tcgetattr(fd
, &origopts
);
280 tcgetattr(fd
, &opts
);
282 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
); /* Raw mode */
283 opts
.c_oflag
&= ~OPOST
; /* Don't post-process */
285 bufsize
= 96; /* 9600 baud / 10 bits/char / 10Hz */
286 dtrdsr
= 0; /* No dtr/dsr flow control */
295 for (ptr
= name
; *options
&& *options
!= '=';)
296 if (ptr
< (name
+ sizeof(name
) - 1))
308 for (ptr
= value
; *options
&& *options
!= '+' && *options
!= '&';)
309 if (ptr
< (value
+ sizeof(value
) - 1))
313 if (*options
== '+' || *options
== '&')
320 * Process the option...
323 if (!strcasecmp(name
, "baud"))
326 * Set the baud rate...
329 bufsize
= atoi(value
) / 100;
332 cfsetispeed(&opts
, atoi(value
));
333 cfsetospeed(&opts
, atoi(value
));
338 cfsetispeed(&opts
, B1200
);
339 cfsetospeed(&opts
, B1200
);
342 cfsetispeed(&opts
, B2400
);
343 cfsetospeed(&opts
, B2400
);
346 cfsetispeed(&opts
, B4800
);
347 cfsetospeed(&opts
, B4800
);
350 cfsetispeed(&opts
, B9600
);
351 cfsetospeed(&opts
, B9600
);
354 cfsetispeed(&opts
, B19200
);
355 cfsetospeed(&opts
, B19200
);
358 cfsetispeed(&opts
, B38400
);
359 cfsetospeed(&opts
, B38400
);
363 cfsetispeed(&opts
, B57600
);
364 cfsetospeed(&opts
, B57600
);
369 cfsetispeed(&opts
, B115200
);
370 cfsetospeed(&opts
, B115200
);
372 # endif /* B115200 */
375 cfsetispeed(&opts
, B230400
);
376 cfsetospeed(&opts
, B230400
);
378 # endif /* B230400 */
380 fprintf(stderr
, "WARNING: Unsupported baud rate %s!\n", value
);
383 #endif /* B19200 == 19200 */
385 else if (!strcasecmp(name
, "bits"))
388 * Set number of data bits...
394 opts
.c_cflag
&= ~CSIZE
;
396 opts
.c_cflag
|= PARENB
;
397 opts
.c_cflag
&= ~PARODD
;
400 opts
.c_cflag
&= ~CSIZE
;
402 opts
.c_cflag
&= ~PARENB
;
406 else if (!strcasecmp(name
, "parity"))
409 * Set parity checking...
412 if (!strcasecmp(value
, "even"))
414 opts
.c_cflag
|= PARENB
;
415 opts
.c_cflag
&= ~PARODD
;
417 else if (!strcasecmp(value
, "odd"))
419 opts
.c_cflag
|= PARENB
;
420 opts
.c_cflag
|= PARODD
;
422 else if (!strcasecmp(value
, "none"))
423 opts
.c_cflag
&= ~PARENB
;
424 else if (!strcasecmp(value
, "space"))
427 * Note: we only support space parity with 7 bits per character...
430 opts
.c_cflag
&= ~CSIZE
;
432 opts
.c_cflag
&= ~PARENB
;
434 else if (!strcasecmp(value
, "mark"))
437 * Note: we only support mark parity with 7 bits per character
441 opts
.c_cflag
&= ~CSIZE
;
443 opts
.c_cflag
&= ~PARENB
;
444 opts
.c_cflag
|= CSTOPB
;
447 else if (!strcasecmp(name
, "flow"))
450 * Set flow control...
453 if (!strcasecmp(value
, "none"))
455 opts
.c_iflag
&= ~(IXON
| IXOFF
);
456 opts
.c_cflag
&= ~CRTSCTS
;
458 else if (!strcasecmp(value
, "soft"))
460 opts
.c_iflag
|= IXON
| IXOFF
;
461 opts
.c_cflag
&= ~CRTSCTS
;
463 else if (!strcasecmp(value
, "hard") ||
464 !strcasecmp(value
, "rtscts"))
466 opts
.c_iflag
&= ~(IXON
| IXOFF
);
467 opts
.c_cflag
|= CRTSCTS
;
469 else if (!strcasecmp(value
, "dtrdsr"))
471 opts
.c_iflag
&= ~(IXON
| IXOFF
);
472 opts
.c_cflag
&= ~CRTSCTS
;
477 else if (!strcasecmp(name
, "stop"))
482 opts
.c_cflag
&= ~CSTOPB
;
486 opts
.c_cflag
|= CSTOPB
;
492 tcsetattr(fd
, TCSANOW
, &opts
);
493 fcntl(fd
, F_SETFL
, 0);
496 * Now that we are "connected" to the port, ignore SIGTERM so that we
497 * can finish out any page data the driver sends (e.g. to eject the
498 * current page... Only ignore SIGTERM if we are printing data from
499 * stdin (otherwise you can't cancel raw jobs...)
504 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
505 sigset(SIGTERM
, SIG_IGN
);
506 #elif defined(HAVE_SIGACTION)
507 memset(&action
, 0, sizeof(action
));
509 sigemptyset(&action
.sa_mask
);
510 action
.sa_handler
= SIG_IGN
;
511 sigaction(SIGTERM
, &action
, NULL
);
513 signal(SIGTERM
, SIG_IGN
);
514 #endif /* HAVE_SIGSET */
518 * Finally, send the print file...
521 if (bufsize
> sizeof(buffer
))
522 bufsize
= sizeof(buffer
);
532 fputs("PAGE: 1 1\n", stderr
);
533 lseek(fp
, 0, SEEK_SET
);
539 * Check the port and sleep until DSR is set...
545 if (!ioctl(fd
, TIOCMGET
, &status
))
546 if (!(status
& TIOCM_DSR
))
549 * Wait for DSR to go high...
552 fputs("DEBUG: DSR is low; waiting for device...\n", stderr
);
557 if (ioctl(fd
, TIOCMGET
, &status
))
560 while (!(status
& TIOCM_DSR
));
562 fputs("DEBUG: DSR is high; writing to device...\n", stderr
);
567 while ((nbytes
= read(fp
, buffer
, bufsize
)) > 0)
570 * Write the print data to the printer...
579 * See if we are ready to read or write...
589 while (select(fd
+ 1, &input
, &output
, NULL
, NULL
) < 0);
591 if (FD_ISSET(fd
, &input
))
594 * Read backchannel data...
597 if ((rbytes
= read(fd
, resource
, sizeof(resource
))) > 0)
599 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
601 cupsBackChannelWrite(resource
, rbytes
, 1.0);
605 if (FD_ISSET(fd
, &output
))
608 * Write print data...
611 if ((wbytes
= write(fd
, bufptr
, nbytes
)) < 0)
613 wbytes
= write(fd
, bufptr
, nbytes
);
618 * Check for retryable errors...
621 if (errno
!= EAGAIN
&& errno
!= EINTR
)
623 perror("ERROR: Unable to send print file to printer");
630 * Update count and pointer...
643 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
644 (unsigned long)tbytes
);
649 * Close the serial port and input file and return...
652 tcsetattr(fd
, TCSADRAIN
, &origopts
);
658 return (wbytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
663 * 'list_devices()' - List all serial devices.
669 #if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
670 static char *funky_hex
= "0123456789abcdefghijklmnopqrstuvwxyz";
671 /* Funky hex numbering used for some *
673 #endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
676 int i
, j
; /* Looping vars */
677 int fd
; /* File descriptor */
678 char device
[255]; /* Device filename */
680 struct serial_struct serinfo
; /* serial port info */
681 # endif /* TIOCGSERIAL */
684 for (i
= 0; i
< 100; i
++)
686 sprintf(device
, "/dev/ttyS%d", i
);
688 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
692 * See if this port exists...
695 serinfo
.reserved_char
[0] = 0;
697 if (!ioctl(fd
, TIOCGSERIAL
, &serinfo
))
699 if (serinfo
.type
== PORT_UNKNOWN
)
709 # endif /* TIOCGSERIAL */
713 # if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
714 printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
717 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
719 # endif /* _ARCH_PPC || powerpc || __powerpc */
723 for (i
= 0; i
< 16; i
++)
725 sprintf(device
, "/dev/usb/ttyUSB%d", i
);
726 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
729 printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
734 for (i
= 0; i
< 64; i
++)
736 for (j
= 0; j
< 8; j
++)
738 sprintf(device
, "/dev/ttyQ%02de%d", i
, j
);
739 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
742 printf("serial serial:%s?baud=115200 \"Unknown\" "
743 "\"Equinox ESP %d Port #%d\"\n",
749 int i
, j
, n
; /* Looping vars */
750 char device
[255]; /* Device filename */
751 inventory_t
*inv
; /* Hardware inventory info */
755 * IRIX maintains a hardware inventory of most devices...
760 while ((inv
= getinvent()) != NULL
)
762 if (inv
->inv_class
== INV_SERIAL
)
765 * Some sort of serial port...
768 if (inv
->inv_type
== INV_CDSIO
|| inv
->inv_type
== INV_CDSIO_E
)
774 for (n
= 0; n
< 6; n
++)
775 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n",
776 n
+ 5 + 8 * inv
->inv_controller
, inv
->inv_controller
, n
+ 1);
778 else if (inv
->inv_type
== INV_EPC_SERIAL
)
781 * Everest serial port...
784 if (inv
->inv_unit
== 0)
787 i
= 41 + 4 * (int)inv
->inv_controller
;
789 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
790 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n",
791 n
+ i
, n
+ 1, (int)inv
->inv_controller
);
793 else if (inv
->inv_state
> 1)
796 * Standard serial port under IRIX 6.4 and earlier...
799 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
800 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n",
801 n
+ (int)inv
->inv_unit
+ 1, n
+ (int)inv
->inv_unit
+ 1);
806 * Standard serial port under IRIX 6.5 and beyond...
809 printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n",
810 (int)inv
->inv_controller
, (int)inv
->inv_controller
);
818 * Central Data makes serial and parallel "servers" that can be
819 * connected in a number of ways. Look for ports...
822 for (i
= 0; i
< 10; i
++)
823 for (j
= 0; j
< 8; j
++)
824 for (n
= 0; n
< 32; n
++)
826 if (i
== 8) /* EtherLite */
827 sprintf(device
, "/dev/ttydn%d%c", j
, funky_hex
[n
]);
828 else if (i
== 9) /* PCI */
829 sprintf(device
, "/dev/ttydp%d%c", j
, funky_hex
[n
]);
831 sprintf(device
, "/dev/ttyd%d%d%c", i
, j
, funky_hex
[n
]);
833 if (access(device
, 0) == 0)
836 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
839 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n",
842 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
847 int i
, j
, n
; /* Looping vars */
848 char device
[255]; /* Device filename */
852 * Standard serial ports...
855 for (i
= 0; i
< 26; i
++)
857 sprintf(device
, "/dev/cua/%c", 'a' + i
);
858 if (access(device
, 0) == 0)
860 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
863 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
865 # endif /* B115200 */
869 * MAGMA serial ports...
872 for (i
= 0; i
< 40; i
++)
874 sprintf(device
, "/dev/term/%02d", i
);
875 if (access(device
, 0) == 0)
876 printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n",
877 device
, (i
/ 10) + 1, (i
% 10) + 1);
881 * Central Data serial ports...
884 for (i
= 0; i
< 9; i
++)
885 for (j
= 0; j
< 8; j
++)
886 for (n
= 0; n
< 32; n
++)
888 if (i
== 8) /* EtherLite */
889 sprintf(device
, "/dev/sts/ttyN%d%c", j
, funky_hex
[n
]);
891 sprintf(device
, "/dev/sts/tty%c%d%c", i
+ 'C', j
,
894 if (access(device
, 0) == 0)
897 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
900 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
904 #elif defined(__hpux)
905 int i
, j
, n
; /* Looping vars */
906 char device
[255]; /* Device filename */
910 * Standard serial ports...
913 for (i
= 0; i
< 10; i
++)
915 sprintf(device
, "/dev/tty%dp0", i
);
916 if (access(device
, 0) == 0)
917 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
922 * Central Data serial ports...
925 for (i
= 0; i
< 9; i
++)
926 for (j
= 0; j
< 8; j
++)
927 for (n
= 0; n
< 32; n
++)
929 if (i
== 8) /* EtherLite */
930 sprintf(device
, "/dev/ttyN%d%c", j
, funky_hex
[n
]);
932 sprintf(device
, "/dev/tty%c%d%c", i
+ 'C', j
,
935 if (access(device
, 0) == 0)
938 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
941 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
945 #elif defined(__osf__)
946 int i
; /* Looping var */
947 char device
[255]; /* Device filename */
951 * Standard serial ports...
954 for (i
= 0; i
< 100; i
++)
956 sprintf(device
, "/dev/tty%02d", i
);
957 if (access(device
, 0) == 0)
958 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
961 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
962 int i
, j
; /* Looping vars */
963 int fd
; /* File descriptor */
964 char device
[255]; /* Device filename */
971 for (i
= 0; i
< 32; i
++)
973 sprintf(device
, "/dev/ttyd%c", funky_hex
[i
]);
974 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
977 printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
986 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
987 for (j
= 0; j
< 32; j
++)
989 sprintf(device
, "/dev/ttyc%d%c", i
, funky_hex
[j
]);
990 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
993 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
997 sprintf(device
, "/dev/ttyC%d%c", i
, funky_hex
[j
]);
998 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1001 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
1007 * Digiboard ports...
1010 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1011 for (j
= 0; j
< 32; j
++)
1013 sprintf(device
, "/dev/ttyD%d%c", i
, funky_hex
[j
]);
1014 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1017 printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n",
1026 for (i
= 0; i
< 32; i
++)
1028 sprintf(device
, "/dev/ttyE%c", funky_hex
[i
]);
1029 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1032 printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n",
1041 for (i
= 0; i
< 128; i
++)
1043 sprintf(device
, "/dev/ttyA%d", i
+ 1);
1044 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1047 printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n",
1051 #elif defined(__NetBSD__)
1052 int i
, j
; /* Looping vars */
1053 int fd
; /* File descriptor */
1054 char device
[255]; /* Device filename */
1058 * Standard serial ports...
1061 for (i
= 0; i
< 4; i
++)
1063 sprintf(device
, "/dev/tty%02d", i
);
1064 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1067 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
1073 * Cyclades-Z ports...
1076 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1077 for (j
= 0; j
< 64; j
++)
1079 sprintf(device
, "/dev/ttyCZ%02d%02d", i
, j
);
1080 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1083 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n",
1087 #elif defined(__APPLE__)
1089 * Standard serial ports on MacOS X...
1092 kern_return_t kernResult
;
1093 mach_port_t masterPort
;
1094 io_iterator_t serialPortIterator
;
1095 CFMutableDictionaryRef classesToMatch
;
1096 io_object_t serialService
;
1099 kernResult
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1100 if (KERN_SUCCESS
!= kernResult
)
1104 * Serial devices are instances of class IOSerialBSDClient.
1107 classesToMatch
= IOServiceMatching(kIOSerialBSDServiceValue
);
1108 if (classesToMatch
!= NULL
)
1110 CFDictionarySetValue(classesToMatch
, CFSTR(kIOSerialBSDTypeKey
),
1111 CFSTR(kIOSerialBSDRS232Type
));
1113 kernResult
= IOServiceGetMatchingServices(masterPort
, classesToMatch
,
1114 &serialPortIterator
);
1115 if (kernResult
== KERN_SUCCESS
)
1117 while ((serialService
= IOIteratorNext(serialPortIterator
)))
1119 CFTypeRef serialNameAsCFString
;
1120 CFTypeRef bsdPathAsCFString
;
1121 char serialName
[128];
1126 serialNameAsCFString
=
1127 IORegistryEntryCreateCFProperty(serialService
,
1128 CFSTR(kIOTTYDeviceKey
),
1129 kCFAllocatorDefault
, 0);
1130 if (serialNameAsCFString
)
1132 result
= CFStringGetCString(serialNameAsCFString
, serialName
,
1134 kCFStringEncodingASCII
);
1135 CFRelease(serialNameAsCFString
);
1140 IORegistryEntryCreateCFProperty(serialService
,
1141 CFSTR(kIOCalloutDeviceKey
),
1142 kCFAllocatorDefault
, 0);
1143 if (bsdPathAsCFString
)
1145 result
= CFStringGetCString(bsdPathAsCFString
, bsdPath
,
1147 kCFStringEncodingASCII
);
1148 CFRelease(bsdPathAsCFString
);
1151 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
1152 bsdPath
, serialName
);
1157 IOObjectRelease(serialService
);
1161 * Release the iterator.
1164 IOObjectRelease(serialPortIterator
);
1172 * End of "$Id: serial.c 5553 2006-05-20 12:22:27Z mike $".