2 * "$Id: serial.c 5241 2006-03-07 22:07:44Z 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__ */
95 void list_devices(void);
99 * 'main()' - Send a file to the printer or server.
103 * printer-uri job-id user title copies options [file]
106 int /* O - Exit status */
107 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
108 char *argv
[]) /* I - Command-line arguments */
110 char method
[255], /* Method in URI */
111 hostname
[1024], /* Hostname */
112 username
[255], /* Username info (not used) */
113 resource
[1024], /* Resource info (device and options) */
114 *options
, /* Pointer to options */
115 name
[255], /* Name of option */
116 value
[255], /* Value of option */
117 *ptr
; /* Pointer into name or value */
118 int port
; /* Port number (not used) */
119 int fp
; /* Print file */
120 int copies
; /* Number of copies to print */
121 int fd
; /* Parallel device */
122 int rbytes
; /* Number of bytes read */
123 int wbytes
; /* Number of bytes written */
124 size_t nbytes
, /* Number of bytes read */
125 tbytes
; /* Total number of bytes written */
126 int dtrdsr
; /* Do dtr/dsr flow control? */
127 int bufsize
; /* Size of output buffer for writes */
128 char buffer
[8192], /* Output buffer */
129 *bufptr
; /* Pointer into buffer */
130 struct termios opts
; /* Serial port options */
131 struct termios origopts
; /* Original port options */
132 fd_set input
, /* Input set for select() */
133 output
; /* Output set for select() */
134 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
135 struct sigaction action
; /* Actions for POSIX signals */
136 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
140 * Make sure status messages are not buffered...
143 setbuf(stderr
, NULL
);
146 * Ignore SIGPIPE signals...
150 sigset(SIGPIPE
, SIG_IGN
);
151 #elif defined(HAVE_SIGACTION)
152 memset(&action
, 0, sizeof(action
));
153 action
.sa_handler
= SIG_IGN
;
154 sigaction(SIGPIPE
, &action
, NULL
);
156 signal(SIGPIPE
, SIG_IGN
);
157 #endif /* HAVE_SIGSET */
160 * Check command-line...
166 return (CUPS_BACKEND_OK
);
168 else if (argc
< 6 || argc
> 7)
170 fputs("Usage: serial job-id user title copies options [file]\n", stderr
);
171 return (CUPS_BACKEND_FAILED
);
175 * If we have 7 arguments, print the file named on the command-line.
176 * Otherwise, send stdin instead...
187 * Try to open the print file...
190 if ((fp
= open(argv
[6], O_RDONLY
)) < 0)
192 perror("ERROR: unable to open print file");
193 return (CUPS_BACKEND_FAILED
);
196 copies
= atoi(argv
[4]);
200 * Extract the device name and options from the URI...
203 httpSeparateURI(HTTP_URI_CODING_ALL
, cupsBackendDeviceURI(argv
),
204 method
, sizeof(method
), username
, sizeof(username
),
205 hostname
, sizeof(hostname
), &port
,
206 resource
, sizeof(resource
));
209 * See if there are any options...
212 if ((options
= strchr(resource
, '?')) != NULL
)
215 * Yup, terminate the device name string and move to the first
216 * character of the options...
223 * Open the serial port device...
226 fputs("STATE: +connecting-to-device\n", stderr
);
230 if ((fd
= open(resource
, O_WRONLY
| O_NOCTTY
| O_EXCL
| O_NDELAY
)) == -1)
232 if (getenv("CLASS") != NULL
)
235 * If the CLASS environment variable is set, the job was submitted
236 * to a class and not to a specific queue. In this case, we want
237 * to abort immediately so that the job can be requeued on the next
238 * available printer in the class.
241 fputs("INFO: Unable to open serial port, queuing on next printer in class...\n",
245 * Sleep 5 seconds to keep the job from requeuing too rapidly...
250 return (CUPS_BACKEND_FAILED
);
255 fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr
);
260 fprintf(stderr
, "ERROR: Unable to open serial port device file \"%s\": %s\n",
261 resource
, strerror(errno
));
262 return (CUPS_BACKEND_FAILED
);
268 fputs("STATE: -connecting-to-device\n", stderr
);
271 * Set any options provided...
274 tcgetattr(fd
, &origopts
);
275 tcgetattr(fd
, &opts
);
277 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
); /* Raw mode */
278 opts
.c_oflag
&= ~OPOST
; /* Don't post-process */
280 bufsize
= 96; /* 9600 baud / 10 bits/char / 10Hz */
281 dtrdsr
= 0; /* No dtr/dsr flow control */
290 for (ptr
= name
; *options
&& *options
!= '=';)
291 if (ptr
< (name
+ sizeof(name
) - 1))
303 for (ptr
= value
; *options
&& *options
!= '+' && *options
!= '&';)
304 if (ptr
< (value
+ sizeof(value
) - 1))
315 * Process the option...
318 if (!strcasecmp(name
, "baud"))
321 * Set the baud rate...
324 bufsize
= atoi(value
) / 100;
327 cfsetispeed(&opts
, atoi(value
));
328 cfsetospeed(&opts
, atoi(value
));
333 cfsetispeed(&opts
, B1200
);
334 cfsetospeed(&opts
, B1200
);
337 cfsetispeed(&opts
, B2400
);
338 cfsetospeed(&opts
, B2400
);
341 cfsetispeed(&opts
, B4800
);
342 cfsetospeed(&opts
, B4800
);
345 cfsetispeed(&opts
, B9600
);
346 cfsetospeed(&opts
, B9600
);
349 cfsetispeed(&opts
, B19200
);
350 cfsetospeed(&opts
, B19200
);
353 cfsetispeed(&opts
, B38400
);
354 cfsetospeed(&opts
, B38400
);
358 cfsetispeed(&opts
, B57600
);
359 cfsetospeed(&opts
, B57600
);
364 cfsetispeed(&opts
, B115200
);
365 cfsetospeed(&opts
, B115200
);
367 # endif /* B115200 */
370 cfsetispeed(&opts
, B230400
);
371 cfsetospeed(&opts
, B230400
);
373 # endif /* B230400 */
375 fprintf(stderr
, "WARNING: Unsupported baud rate %s!\n", value
);
378 #endif /* B19200 == 19200 */
380 else if (!strcasecmp(name
, "bits"))
383 * Set number of data bits...
389 opts
.c_cflag
&= ~CSIZE
;
391 opts
.c_cflag
|= PARENB
;
392 opts
.c_cflag
&= ~PARODD
;
395 opts
.c_cflag
&= ~CSIZE
;
397 opts
.c_cflag
&= ~PARENB
;
401 else if (!strcasecmp(name
, "parity"))
404 * Set parity checking...
407 if (!strcasecmp(value
, "even"))
409 opts
.c_cflag
|= PARENB
;
410 opts
.c_cflag
&= ~PARODD
;
412 else if (!strcasecmp(value
, "odd"))
414 opts
.c_cflag
|= PARENB
;
415 opts
.c_cflag
|= PARODD
;
417 else if (!strcasecmp(value
, "none"))
418 opts
.c_cflag
&= ~PARENB
;
419 else if (!strcasecmp(value
, "space"))
422 * Note: we only support space parity with 7 bits per character...
425 opts
.c_cflag
&= ~CSIZE
;
427 opts
.c_cflag
&= ~PARENB
;
429 else if (!strcasecmp(value
, "mark"))
432 * Note: we only support mark parity with 7 bits per character
436 opts
.c_cflag
&= ~CSIZE
;
438 opts
.c_cflag
&= ~PARENB
;
439 opts
.c_cflag
|= CSTOPB
;
442 else if (!strcasecmp(name
, "flow"))
445 * Set flow control...
448 if (!strcasecmp(value
, "none"))
450 opts
.c_iflag
&= ~(IXON
| IXOFF
);
451 opts
.c_cflag
&= ~CRTSCTS
;
453 else if (!strcasecmp(value
, "soft"))
455 opts
.c_iflag
|= IXON
| IXOFF
;
456 opts
.c_cflag
&= ~CRTSCTS
;
458 else if (!strcasecmp(value
, "hard") ||
459 !strcasecmp(value
, "rtscts"))
461 opts
.c_iflag
&= ~(IXON
| IXOFF
);
462 opts
.c_cflag
|= CRTSCTS
;
464 else if (!strcasecmp(value
, "dtrdsr"))
466 opts
.c_iflag
&= ~(IXON
| IXOFF
);
467 opts
.c_cflag
&= ~CRTSCTS
;
472 else if (!strcasecmp(name
, "stop"))
477 opts
.c_cflag
&= ~CSTOPB
;
481 opts
.c_cflag
|= CSTOPB
;
487 tcsetattr(fd
, TCSANOW
, &opts
);
488 fcntl(fd
, F_SETFL
, 0);
491 * Now that we are "connected" to the port, ignore SIGTERM so that we
492 * can finish out any page data the driver sends (e.g. to eject the
493 * current page... Only ignore SIGTERM if we are printing data from
494 * stdin (otherwise you can't cancel raw jobs...)
499 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
500 sigset(SIGTERM
, SIG_IGN
);
501 #elif defined(HAVE_SIGACTION)
502 memset(&action
, 0, sizeof(action
));
504 sigemptyset(&action
.sa_mask
);
505 action
.sa_handler
= SIG_IGN
;
506 sigaction(SIGTERM
, &action
, NULL
);
508 signal(SIGTERM
, SIG_IGN
);
509 #endif /* HAVE_SIGSET */
513 * Finally, send the print file...
516 if (bufsize
> sizeof(buffer
))
517 bufsize
= sizeof(buffer
);
527 fputs("PAGE: 1 1\n", stderr
);
528 lseek(fp
, 0, SEEK_SET
);
534 * Check the port and sleep until DSR is set...
540 if (!ioctl(fd
, TIOCMGET
, &status
))
541 if (!(status
& TIOCM_DSR
))
544 * Wait for DSR to go high...
547 fputs("DEBUG: DSR is low; waiting for device...\n", stderr
);
552 if (ioctl(fd
, TIOCMGET
, &status
))
555 while (!(status
& TIOCM_DSR
));
557 fputs("DEBUG: DSR is high; writing to device...\n", stderr
);
562 while ((nbytes
= read(fp
, buffer
, bufsize
)) > 0)
565 * Write the print data to the printer...
574 * See if we are ready to read or write...
584 while (select(fd
+ 1, &input
, &output
, NULL
, NULL
) < 0);
586 if (FD_ISSET(fd
, &input
))
589 * Read backchannel data...
592 if ((rbytes
= read(fd
, resource
, sizeof(resource
))) > 0)
594 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
596 cupsBackChannelWrite(resource
, rbytes
, 1.0);
600 if (FD_ISSET(fd
, &output
))
603 * Write print data...
606 if ((wbytes
= write(fd
, bufptr
, nbytes
)) < 0)
608 wbytes
= write(fd
, bufptr
, nbytes
);
613 * Check for retryable errors...
616 if (errno
!= EAGAIN
&& errno
!= EINTR
)
618 perror("ERROR: Unable to send print file to printer");
625 * Update count and pointer...
638 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
639 (unsigned long)tbytes
);
644 * Close the serial port and input file and return...
647 tcsetattr(fd
, TCSADRAIN
, &origopts
);
653 return (wbytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
658 * 'list_devices()' - List all serial devices.
664 #if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
665 static char *funky_hex
= "0123456789abcdefghijklmnopqrstuvwxyz";
666 /* Funky hex numbering used for some devices */
667 #endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
669 #if defined(__linux) || defined(linux) || defined(__linux__)
670 int i
, j
; /* Looping vars */
671 int fd
; /* File descriptor */
672 char device
[255]; /* Device filename */
675 for (i
= 0; i
< 100; i
++)
677 sprintf(device
, "/dev/ttyS%d", i
);
678 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
681 # if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
682 printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
685 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
687 # endif /* _ARCH_PPC || powerpc || __powerpc */
691 for (i
= 0; i
< 16; i
++)
693 sprintf(device
, "/dev/usb/ttyUSB%d", i
);
694 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
697 printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
702 for (i
= 0; i
< 64; i
++)
704 for (j
= 0; j
< 8; j
++)
706 sprintf(device
, "/dev/ttyQ%02de%d", i
, j
);
707 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
710 printf("serial serial:%s?baud=115200 \"Unknown\" "
711 "\"Equinox ESP %d Port #%d\"\n",
717 int i
, j
, n
; /* Looping vars */
718 char device
[255]; /* Device filename */
719 inventory_t
*inv
; /* Hardware inventory info */
723 * IRIX maintains a hardware inventory of most devices...
728 while ((inv
= getinvent()) != NULL
)
730 if (inv
->inv_class
== INV_SERIAL
)
733 * Some sort of serial port...
736 if (inv
->inv_type
== INV_CDSIO
|| inv
->inv_type
== INV_CDSIO_E
)
742 for (n
= 0; n
< 6; n
++)
743 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n",
744 n
+ 5 + 8 * inv
->inv_controller
, inv
->inv_controller
, n
+ 1);
746 else if (inv
->inv_type
== INV_EPC_SERIAL
)
749 * Everest serial port...
752 if (inv
->inv_unit
== 0)
755 i
= 41 + 4 * (int)inv
->inv_controller
;
757 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
758 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n",
759 n
+ i
, n
+ 1, (int)inv
->inv_controller
);
761 else if (inv
->inv_state
> 1)
764 * Standard serial port under IRIX 6.4 and earlier...
767 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
768 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n",
769 n
+ (int)inv
->inv_unit
+ 1, n
+ (int)inv
->inv_unit
+ 1);
774 * Standard serial port under IRIX 6.5 and beyond...
777 printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n",
778 (int)inv
->inv_controller
, (int)inv
->inv_controller
);
786 * Central Data makes serial and parallel "servers" that can be
787 * connected in a number of ways. Look for ports...
790 for (i
= 0; i
< 10; i
++)
791 for (j
= 0; j
< 8; j
++)
792 for (n
= 0; n
< 32; n
++)
794 if (i
== 8) /* EtherLite */
795 sprintf(device
, "/dev/ttydn%d%c", j
, funky_hex
[n
]);
796 else if (i
== 9) /* PCI */
797 sprintf(device
, "/dev/ttydp%d%c", j
, funky_hex
[n
]);
799 sprintf(device
, "/dev/ttyd%d%d%c", i
, j
, funky_hex
[n
]);
801 if (access(device
, 0) == 0)
804 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
807 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n",
810 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
815 int i
, j
, n
; /* Looping vars */
816 char device
[255]; /* Device filename */
820 * Standard serial ports...
823 for (i
= 0; i
< 26; i
++)
825 sprintf(device
, "/dev/cua/%c", 'a' + i
);
826 if (access(device
, 0) == 0)
828 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
831 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
837 * MAGMA serial ports...
840 for (i
= 0; i
< 40; i
++)
842 sprintf(device
, "/dev/term/%02d", i
);
843 if (access(device
, 0) == 0)
844 printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n",
845 device
, (i
/ 10) + 1, (i
% 10) + 1);
849 * Central Data serial ports...
852 for (i
= 0; i
< 9; i
++)
853 for (j
= 0; j
< 8; j
++)
854 for (n
= 0; n
< 32; n
++)
856 if (i
== 8) /* EtherLite */
857 sprintf(device
, "/dev/sts/ttyN%d%c", j
, funky_hex
[n
]);
859 sprintf(device
, "/dev/sts/tty%c%d%c", i
+ 'C', j
,
862 if (access(device
, 0) == 0)
865 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
868 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
872 #elif defined(__hpux)
873 int i
, j
, n
; /* Looping vars */
874 char device
[255]; /* Device filename */
878 * Standard serial ports...
881 for (i
= 0; i
< 10; i
++)
883 sprintf(device
, "/dev/tty%dp0", i
);
884 if (access(device
, 0) == 0)
885 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
890 * Central Data serial ports...
893 for (i
= 0; i
< 9; i
++)
894 for (j
= 0; j
< 8; j
++)
895 for (n
= 0; n
< 32; n
++)
897 if (i
== 8) /* EtherLite */
898 sprintf(device
, "/dev/ttyN%d%c", j
, funky_hex
[n
]);
900 sprintf(device
, "/dev/tty%c%d%c", i
+ 'C', j
,
903 if (access(device
, 0) == 0)
906 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
909 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
913 #elif defined(__osf__)
914 int i
; /* Looping var */
915 char device
[255]; /* Device filename */
919 * Standard serial ports...
922 for (i
= 0; i
< 100; i
++)
924 sprintf(device
, "/dev/tty%02d", i
);
925 if (access(device
, 0) == 0)
926 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
929 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
930 int i
, j
; /* Looping vars */
931 int fd
; /* File descriptor */
932 char device
[255]; /* Device filename */
939 for (i
= 0; i
< 32; i
++)
941 sprintf(device
, "/dev/ttyd%c", funky_hex
[i
]);
942 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
945 printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
954 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
955 for (j
= 0; j
< 32; j
++)
957 sprintf(device
, "/dev/ttyc%d%c", i
, funky_hex
[j
]);
958 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
961 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
965 sprintf(device
, "/dev/ttyC%d%c", i
, funky_hex
[j
]);
966 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
969 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
978 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
979 for (j
= 0; j
< 32; j
++)
981 sprintf(device
, "/dev/ttyD%d%c", i
, funky_hex
[j
]);
982 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
985 printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n",
994 for (i
= 0; i
< 32; i
++)
996 sprintf(device
, "/dev/ttyE%c", funky_hex
[i
]);
997 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1000 printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n",
1009 for (i
= 0; i
< 128; i
++)
1011 sprintf(device
, "/dev/ttyA%d", i
+ 1);
1012 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1015 printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n",
1019 #elif defined(__NetBSD__)
1020 int i
, j
; /* Looping vars */
1021 int fd
; /* File descriptor */
1022 char device
[255]; /* Device filename */
1026 * Standard serial ports...
1029 for (i
= 0; i
< 4; i
++)
1031 sprintf(device
, "/dev/tty%02d", i
);
1032 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1035 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
1041 * Cyclades-Z ports...
1044 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1045 for (j
= 0; j
< 64; j
++)
1047 sprintf(device
, "/dev/ttyCZ%02d%02d", i
, j
);
1048 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1051 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n",
1055 #elif defined(__APPLE__)
1057 * Standard serial ports on MacOS X...
1060 kern_return_t kernResult
;
1061 mach_port_t masterPort
;
1062 io_iterator_t serialPortIterator
;
1063 CFMutableDictionaryRef classesToMatch
;
1064 io_object_t serialService
;
1066 printf("serial serial \"Unknown\" \"Serial Printer (serial)\"\n");
1068 kernResult
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1069 if (KERN_SUCCESS
!= kernResult
)
1073 * Serial devices are instances of class IOSerialBSDClient.
1076 classesToMatch
= IOServiceMatching(kIOSerialBSDServiceValue
);
1077 if (classesToMatch
!= NULL
)
1079 CFDictionarySetValue(classesToMatch
, CFSTR(kIOSerialBSDTypeKey
),
1080 CFSTR(kIOSerialBSDRS232Type
));
1082 kernResult
= IOServiceGetMatchingServices(masterPort
, classesToMatch
,
1083 &serialPortIterator
);
1084 if (kernResult
== KERN_SUCCESS
)
1086 while ((serialService
= IOIteratorNext(serialPortIterator
)))
1088 CFTypeRef serialNameAsCFString
;
1089 CFTypeRef bsdPathAsCFString
;
1090 char serialName
[128];
1095 serialNameAsCFString
=
1096 IORegistryEntryCreateCFProperty(serialService
,
1097 CFSTR(kIOTTYDeviceKey
),
1098 kCFAllocatorDefault
, 0);
1099 if (serialNameAsCFString
)
1101 result
= CFStringGetCString(serialNameAsCFString
, serialName
,
1103 kCFStringEncodingASCII
);
1104 CFRelease(serialNameAsCFString
);
1109 IORegistryEntryCreateCFProperty(serialService
,
1110 CFSTR(kIOCalloutDeviceKey
),
1111 kCFAllocatorDefault
, 0);
1112 if (bsdPathAsCFString
)
1114 result
= CFStringGetCString(bsdPathAsCFString
, bsdPath
,
1116 kCFStringEncodingASCII
);
1117 CFRelease(bsdPathAsCFString
);
1120 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", bsdPath
,
1126 IOObjectRelease(serialService
);
1129 IOObjectRelease(serialPortIterator
); /* Release the iterator. */
1137 * End of "$Id: serial.c 5241 2006-03-07 22:07:44Z mike $".