2 * "$Id: serial.c 6068 2006-10-27 17:10:34Z 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 "backend-private.h"
39 # include <sys/modem.h>
49 # include <sys/time.h>
51 # include <sys/select.h>
53 # ifdef HAVE_SYS_IOCTL_H
54 # include <sys/ioctl.h>
55 # endif /* HAVE_SYS_IOCTL_H */
60 # ifndef INV_EPP_ECP_PLP
61 # define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */
62 # define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */
63 # define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */
64 # define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */
65 # define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */
66 # endif /* !INV_EPP_ECP_PLP */
71 # define CRTSCTS CNEW_RTSCTS
74 # endif /* CNEW_RTSCTS */
77 #if defined(__APPLE__)
78 # include <CoreFoundation/CoreFoundation.h>
79 # include <IOKit/IOKitLib.h>
80 # include <IOKit/serial/IOSerialKeys.h>
81 # include <IOKit/IOBSD.h>
82 #endif /* __APPLE__ */
84 #if defined(__linux) && defined(TIOCGSERIAL)
85 # include <linux/serial.h>
86 # include <linux/ioctl.h>
87 #endif /* __linux && TIOCGSERIAL */
94 void list_devices(void);
98 * 'main()' - Send a file to the printer or server.
102 * printer-uri job-id user title copies options [file]
105 int /* O - Exit status */
106 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
107 char *argv
[]) /* I - Command-line arguments */
109 char method
[255], /* Method in URI */
110 hostname
[1024], /* Hostname */
111 username
[255], /* Username info (not used) */
112 resource
[1024], /* Resource info (device and options) */
113 *options
, /* Pointer to options */
114 name
[255], /* Name of option */
115 value
[255], /* Value of option */
116 *ptr
; /* Pointer into name or value */
117 int port
; /* Port number (not used) */
118 int copies
; /* Number of copies to print */
119 int print_fd
, /* Print file */
120 device_fd
; /* Serial device */
121 int nfds
; /* Maximum file descriptor value + 1 */
122 fd_set input
, /* Input set for reading */
123 output
; /* Output set for writing */
124 ssize_t print_bytes
, /* Print bytes read */
125 bc_bytes
, /* Backchannel bytes read */
126 total_bytes
, /* Total bytes written */
127 bytes
; /* Bytes written */
128 int dtrdsr
; /* Do dtr/dsr flow control? */
129 int print_size
; /* Size of output buffer for writes */
130 char print_buffer
[8192], /* Print data buffer */
131 *print_ptr
, /* Pointer into print data buffer */
132 bc_buffer
[1024]; /* Back-channel data buffer */
133 struct termios opts
; /* Serial port options */
134 struct termios origopts
; /* Original port options */
135 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
136 struct sigaction action
; /* Actions for POSIX signals */
137 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
141 * Make sure status messages are not buffered...
144 setbuf(stderr
, NULL
);
147 * Ignore SIGPIPE signals...
151 sigset(SIGPIPE
, SIG_IGN
);
152 #elif defined(HAVE_SIGACTION)
153 memset(&action
, 0, sizeof(action
));
154 action
.sa_handler
= SIG_IGN
;
155 sigaction(SIGPIPE
, &action
, NULL
);
157 signal(SIGPIPE
, SIG_IGN
);
158 #endif /* HAVE_SIGSET */
161 * Check command-line...
167 return (CUPS_BACKEND_OK
);
169 else if (argc
< 6 || argc
> 7)
171 fputs("Usage: serial job-id user title copies options [file]\n", stderr
);
172 return (CUPS_BACKEND_FAILED
);
176 * If we have 7 arguments, print the file named on the command-line.
177 * Otherwise, send stdin instead...
188 * Try to open the print file...
191 if ((print_fd
= open(argv
[6], O_RDONLY
)) < 0)
193 perror("ERROR: unable to open print file");
194 return (CUPS_BACKEND_FAILED
);
197 copies
= atoi(argv
[4]);
201 * Extract the device name and options from the URI...
204 httpSeparateURI(HTTP_URI_CODING_ALL
, cupsBackendDeviceURI(argv
),
205 method
, sizeof(method
), username
, sizeof(username
),
206 hostname
, sizeof(hostname
), &port
,
207 resource
, sizeof(resource
));
210 * See if there are any options...
213 if ((options
= strchr(resource
, '?')) != NULL
)
216 * Yup, terminate the device name string and move to the first
217 * character of the options...
224 * Open the serial port device...
227 fputs("STATE: +connecting-to-device\n", stderr
);
231 if ((device_fd
= open(resource
, O_RDWR
| O_NOCTTY
| O_EXCL
|
234 if (getenv("CLASS") != NULL
)
237 * If the CLASS environment variable is set, the job was submitted
238 * to a class and not to a specific queue. In this case, we want
239 * to abort immediately so that the job can be requeued on the next
240 * available printer in the class.
243 fputs("INFO: Unable to open serial port, queuing on next printer in class...\n",
247 * Sleep 5 seconds to keep the job from requeuing too rapidly...
252 return (CUPS_BACKEND_FAILED
);
257 fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr
);
262 fprintf(stderr
, "ERROR: Unable to open serial port device file \"%s\": %s\n",
263 resource
, strerror(errno
));
264 return (CUPS_BACKEND_FAILED
);
268 while (device_fd
< 0);
270 fputs("STATE: -connecting-to-device\n", stderr
);
273 * Set any options provided...
276 tcgetattr(device_fd
, &origopts
);
277 tcgetattr(device_fd
, &opts
);
279 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
);
281 opts
.c_oflag
&= ~OPOST
; /* Don't post-process */
283 print_size
= 96; /* 9600 baud / 10 bits/char / 10Hz */
284 dtrdsr
= 0; /* No dtr/dsr flow control */
294 for (ptr
= name
; *options
&& *options
!= '=';)
295 if (ptr
< (name
+ sizeof(name
) - 1))
307 for (ptr
= value
; *options
&& *options
!= '+' && *options
!= '&';)
308 if (ptr
< (value
+ sizeof(value
) - 1))
312 if (*options
== '+' || *options
== '&')
319 * Process the option...
322 if (!strcasecmp(name
, "baud"))
325 * Set the baud rate...
328 print_size
= atoi(value
) / 100;
331 cfsetispeed(&opts
, atoi(value
));
332 cfsetospeed(&opts
, atoi(value
));
337 cfsetispeed(&opts
, B1200
);
338 cfsetospeed(&opts
, B1200
);
341 cfsetispeed(&opts
, B2400
);
342 cfsetospeed(&opts
, B2400
);
345 cfsetispeed(&opts
, B4800
);
346 cfsetospeed(&opts
, B4800
);
349 cfsetispeed(&opts
, B9600
);
350 cfsetospeed(&opts
, B9600
);
353 cfsetispeed(&opts
, B19200
);
354 cfsetospeed(&opts
, B19200
);
357 cfsetispeed(&opts
, B38400
);
358 cfsetospeed(&opts
, B38400
);
362 cfsetispeed(&opts
, B57600
);
363 cfsetospeed(&opts
, B57600
);
368 cfsetispeed(&opts
, B115200
);
369 cfsetospeed(&opts
, B115200
);
371 # endif /* B115200 */
374 cfsetispeed(&opts
, B230400
);
375 cfsetospeed(&opts
, B230400
);
377 # endif /* B230400 */
379 fprintf(stderr
, "WARNING: Unsupported baud rate %s!\n", value
);
382 #endif /* B19200 == 19200 */
384 else if (!strcasecmp(name
, "bits"))
387 * Set number of data bits...
393 opts
.c_cflag
&= ~CSIZE
;
395 opts
.c_cflag
|= PARENB
;
396 opts
.c_cflag
&= ~PARODD
;
399 opts
.c_cflag
&= ~CSIZE
;
401 opts
.c_cflag
&= ~PARENB
;
405 else if (!strcasecmp(name
, "parity"))
408 * Set parity checking...
411 if (!strcasecmp(value
, "even"))
413 opts
.c_cflag
|= PARENB
;
414 opts
.c_cflag
&= ~PARODD
;
416 else if (!strcasecmp(value
, "odd"))
418 opts
.c_cflag
|= PARENB
;
419 opts
.c_cflag
|= PARODD
;
421 else if (!strcasecmp(value
, "none"))
422 opts
.c_cflag
&= ~PARENB
;
423 else if (!strcasecmp(value
, "space"))
426 * Note: we only support space parity with 7 bits per character...
429 opts
.c_cflag
&= ~CSIZE
;
431 opts
.c_cflag
&= ~PARENB
;
433 else if (!strcasecmp(value
, "mark"))
436 * Note: we only support mark parity with 7 bits per character
440 opts
.c_cflag
&= ~CSIZE
;
442 opts
.c_cflag
&= ~PARENB
;
443 opts
.c_cflag
|= CSTOPB
;
446 else if (!strcasecmp(name
, "flow"))
449 * Set flow control...
452 if (!strcasecmp(value
, "none"))
454 opts
.c_iflag
&= ~(IXON
| IXOFF
);
455 opts
.c_cflag
&= ~CRTSCTS
;
457 else if (!strcasecmp(value
, "soft"))
459 opts
.c_iflag
|= IXON
| IXOFF
;
460 opts
.c_cflag
&= ~CRTSCTS
;
462 else if (!strcasecmp(value
, "hard") ||
463 !strcasecmp(value
, "rtscts"))
465 opts
.c_iflag
&= ~(IXON
| IXOFF
);
466 opts
.c_cflag
|= CRTSCTS
;
468 else if (!strcasecmp(value
, "dtrdsr"))
470 opts
.c_iflag
&= ~(IXON
| IXOFF
);
471 opts
.c_cflag
&= ~CRTSCTS
;
476 else if (!strcasecmp(name
, "stop"))
481 opts
.c_cflag
&= ~CSTOPB
;
485 opts
.c_cflag
|= CSTOPB
;
492 tcsetattr(device_fd
, TCSANOW
, &opts
);
493 fcntl(device_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 * Figure out the maximum file descriptor value to use with select()...
521 nfds
= (print_fd
> device_fd
? print_fd
: device_fd
) + 1;
524 * Finally, send the print file. Ordinarily we would just use the
525 * backendRunLoop() function, however since we need to use smaller
526 * writes and may need to do DSR/DTR flow control, we duplicate much
527 * of the code here instead...
530 if (print_size
> sizeof(print_buffer
))
531 print_size
= sizeof(print_buffer
);
541 fputs("PAGE: 1 1\n", stderr
);
542 lseek(print_fd
, 0, SEEK_SET
);
546 * Now loop until we are out of data from print_fd...
549 for (print_bytes
= 0, print_ptr
= print_buffer
;;)
552 * Use select() to determine whether we have data to copy around...
557 FD_SET(print_fd
, &input
);
558 FD_SET(device_fd
, &input
);
562 FD_SET(device_fd
, &output
);
564 if (select(nfds
, &input
, &output
, NULL
, NULL
) < 0)
565 continue; /* Ignore errors here */
568 * Check if we have back-channel data ready...
571 if (FD_ISSET(device_fd
, &input
))
573 if ((bc_bytes
= read(device_fd
, bc_buffer
, sizeof(bc_buffer
))) > 0)
576 "DEBUG: Received " CUPS_LLFMT
" bytes of back-channel data!\n",
577 CUPS_LLCAST bc_bytes
);
578 cupsBackChannelWrite(bc_buffer
, bc_bytes
, 1.0);
583 * Check if we have print data ready...
586 if (FD_ISSET(print_fd
, &input
))
588 if ((print_bytes
= read(print_fd
, print_buffer
, print_size
)) < 0)
591 * Read error - bail if we don't see EAGAIN or EINTR...
594 if (errno
!= EAGAIN
|| errno
!= EINTR
)
596 perror("ERROR: Unable to read print data");
598 tcsetattr(device_fd
, TCSADRAIN
, &origopts
);
605 return (CUPS_BACKEND_FAILED
);
610 else if (print_bytes
== 0)
613 * End of file, break out of the loop...
619 print_ptr
= print_buffer
;
623 * Check if the device is ready to receive data and we have data to
627 if (print_bytes
&& FD_ISSET(device_fd
, &output
))
632 * Check the port and sleep until DSR is set...
638 if (!ioctl(device_fd
, TIOCMGET
, &status
))
639 if (!(status
& TIOCM_DSR
))
642 * Wait for DSR to go high...
645 fputs("DEBUG: DSR is low; waiting for device...\n", stderr
);
650 * Poll every 100ms...
655 if (ioctl(device_fd
, TIOCMGET
, &status
))
658 while (!(status
& TIOCM_DSR
));
660 fputs("DEBUG: DSR is high; writing to device...\n", stderr
);
664 if ((bytes
= write(device_fd
, print_ptr
, print_bytes
)) < 0)
667 * Write error - bail if we don't see an error we can retry...
670 if (errno
!= EAGAIN
&& errno
!= EINTR
&& errno
!= ENOTTY
)
672 perror("ERROR: Unable to write print data");
674 tcsetattr(device_fd
, TCSADRAIN
, &origopts
);
681 return (CUPS_BACKEND_FAILED
);
686 fprintf(stderr
, "DEBUG: Wrote %d bytes...\n", (int)bytes
);
688 print_bytes
-= bytes
;
690 total_bytes
+= bytes
;
697 * Close the serial port and input file and return...
700 tcsetattr(device_fd
, TCSADRAIN
, &origopts
);
707 return (total_bytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
712 * 'list_devices()' - List all serial devices.
718 #if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
719 static char *funky_hex
= "0123456789abcdefghijklmnopqrstuvwxyz";
720 /* Funky hex numbering used for some *
722 #endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
725 int i
, j
; /* Looping vars */
726 int fd
; /* File descriptor */
727 char device
[255]; /* Device filename */
729 struct serial_struct serinfo
; /* serial port info */
730 # endif /* TIOCGSERIAL */
733 for (i
= 0; i
< 100; i
++)
735 sprintf(device
, "/dev/ttyS%d", i
);
737 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
741 * See if this port exists...
744 serinfo
.reserved_char
[0] = 0;
746 if (!ioctl(fd
, TIOCGSERIAL
, &serinfo
))
748 if (serinfo
.type
== PORT_UNKNOWN
)
758 # endif /* TIOCGSERIAL */
762 # if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
763 printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
766 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
768 # endif /* _ARCH_PPC || powerpc || __powerpc */
772 for (i
= 0; i
< 16; i
++)
774 sprintf(device
, "/dev/usb/ttyUSB%d", i
);
775 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
778 printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
782 sprintf(device
, "/dev/ttyUSB%d", i
);
783 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
786 printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
791 for (i
= 0; i
< 64; i
++)
793 for (j
= 0; j
< 8; j
++)
795 sprintf(device
, "/dev/ttyQ%02de%d", i
, j
);
796 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
799 printf("serial serial:%s?baud=115200 \"Unknown\" "
800 "\"Equinox ESP %d Port #%d\"\n",
806 int i
, j
, n
; /* Looping vars */
807 char device
[255]; /* Device filename */
808 inventory_t
*inv
; /* Hardware inventory info */
812 * IRIX maintains a hardware inventory of most devices...
817 while ((inv
= getinvent()) != NULL
)
819 if (inv
->inv_class
== INV_SERIAL
)
822 * Some sort of serial port...
825 if (inv
->inv_type
== INV_CDSIO
|| inv
->inv_type
== INV_CDSIO_E
)
831 for (n
= 0; n
< 6; n
++)
832 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n",
833 n
+ 5 + 8 * inv
->inv_controller
, inv
->inv_controller
, n
+ 1);
835 else if (inv
->inv_type
== INV_EPC_SERIAL
)
838 * Everest serial port...
841 if (inv
->inv_unit
== 0)
844 i
= 41 + 4 * (int)inv
->inv_controller
;
846 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
847 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n",
848 n
+ i
, n
+ 1, (int)inv
->inv_controller
);
850 else if (inv
->inv_state
> 1)
853 * Standard serial port under IRIX 6.4 and earlier...
856 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
857 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n",
858 n
+ (int)inv
->inv_unit
+ 1, n
+ (int)inv
->inv_unit
+ 1);
863 * Standard serial port under IRIX 6.5 and beyond...
866 printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n",
867 (int)inv
->inv_controller
, (int)inv
->inv_controller
);
875 * Central Data makes serial and parallel "servers" that can be
876 * connected in a number of ways. Look for ports...
879 for (i
= 0; i
< 10; i
++)
880 for (j
= 0; j
< 8; j
++)
881 for (n
= 0; n
< 32; n
++)
883 if (i
== 8) /* EtherLite */
884 sprintf(device
, "/dev/ttydn%d%c", j
, funky_hex
[n
]);
885 else if (i
== 9) /* PCI */
886 sprintf(device
, "/dev/ttydp%d%c", j
, funky_hex
[n
]);
888 sprintf(device
, "/dev/ttyd%d%d%c", i
, j
, funky_hex
[n
]);
890 if (access(device
, 0) == 0)
893 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
896 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n",
899 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
904 int i
, j
, n
; /* Looping vars */
905 char device
[255]; /* Device filename */
909 * Standard serial ports...
912 for (i
= 0; i
< 26; i
++)
914 sprintf(device
, "/dev/cua/%c", 'a' + i
);
915 if (access(device
, 0) == 0)
917 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
920 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
922 # endif /* B115200 */
926 * MAGMA serial ports...
929 for (i
= 0; i
< 40; i
++)
931 sprintf(device
, "/dev/term/%02d", i
);
932 if (access(device
, 0) == 0)
933 printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n",
934 device
, (i
/ 10) + 1, (i
% 10) + 1);
938 * Central Data serial ports...
941 for (i
= 0; i
< 9; i
++)
942 for (j
= 0; j
< 8; j
++)
943 for (n
= 0; n
< 32; n
++)
945 if (i
== 8) /* EtherLite */
946 sprintf(device
, "/dev/sts/ttyN%d%c", j
, funky_hex
[n
]);
948 sprintf(device
, "/dev/sts/tty%c%d%c", i
+ 'C', j
,
951 if (access(device
, 0) == 0)
954 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
957 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
961 #elif defined(__hpux)
962 int i
, j
, n
; /* Looping vars */
963 char device
[255]; /* Device filename */
967 * Standard serial ports...
970 for (i
= 0; i
< 10; i
++)
972 sprintf(device
, "/dev/tty%dp0", i
);
973 if (access(device
, 0) == 0)
974 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
979 * Central Data serial ports...
982 for (i
= 0; i
< 9; i
++)
983 for (j
= 0; j
< 8; j
++)
984 for (n
= 0; n
< 32; n
++)
986 if (i
== 8) /* EtherLite */
987 sprintf(device
, "/dev/ttyN%d%c", j
, funky_hex
[n
]);
989 sprintf(device
, "/dev/tty%c%d%c", i
+ 'C', j
,
992 if (access(device
, 0) == 0)
995 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
998 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
1002 #elif defined(__osf__)
1003 int i
; /* Looping var */
1004 char device
[255]; /* Device filename */
1008 * Standard serial ports...
1011 for (i
= 0; i
< 100; i
++)
1013 sprintf(device
, "/dev/tty%02d", i
);
1014 if (access(device
, 0) == 0)
1015 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
1018 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1019 int i
, j
; /* Looping vars */
1020 int fd
; /* File descriptor */
1021 char device
[255]; /* Device filename */
1028 for (i
= 0; i
< 32; i
++)
1030 sprintf(device
, "/dev/ttyd%c", funky_hex
[i
]);
1031 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1034 printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
1043 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1044 for (j
= 0; j
< 32; j
++)
1046 sprintf(device
, "/dev/ttyc%d%c", i
, funky_hex
[j
]);
1047 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1050 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
1054 sprintf(device
, "/dev/ttyC%d%c", i
, funky_hex
[j
]);
1055 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1058 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
1064 * Digiboard ports...
1067 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1068 for (j
= 0; j
< 32; j
++)
1070 sprintf(device
, "/dev/ttyD%d%c", i
, funky_hex
[j
]);
1071 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1074 printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n",
1083 for (i
= 0; i
< 32; i
++)
1085 sprintf(device
, "/dev/ttyE%c", funky_hex
[i
]);
1086 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1089 printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n",
1098 for (i
= 0; i
< 128; i
++)
1100 sprintf(device
, "/dev/ttyA%d", i
+ 1);
1101 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1104 printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n",
1108 #elif defined(__NetBSD__)
1109 int i
, j
; /* Looping vars */
1110 int fd
; /* File descriptor */
1111 char device
[255]; /* Device filename */
1115 * Standard serial ports...
1118 for (i
= 0; i
< 4; i
++)
1120 sprintf(device
, "/dev/tty%02d", i
);
1121 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1124 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
1130 * Cyclades-Z ports...
1133 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1134 for (j
= 0; j
< 64; j
++)
1136 sprintf(device
, "/dev/ttyCZ%02d%02d", i
, j
);
1137 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1140 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n",
1144 #elif defined(__APPLE__)
1146 * Standard serial ports on MacOS X...
1149 kern_return_t kernResult
;
1150 mach_port_t masterPort
;
1151 io_iterator_t serialPortIterator
;
1152 CFMutableDictionaryRef classesToMatch
;
1153 io_object_t serialService
;
1156 kernResult
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1157 if (KERN_SUCCESS
!= kernResult
)
1161 * Serial devices are instances of class IOSerialBSDClient.
1164 classesToMatch
= IOServiceMatching(kIOSerialBSDServiceValue
);
1165 if (classesToMatch
!= NULL
)
1167 CFDictionarySetValue(classesToMatch
, CFSTR(kIOSerialBSDTypeKey
),
1168 CFSTR(kIOSerialBSDRS232Type
));
1170 kernResult
= IOServiceGetMatchingServices(masterPort
, classesToMatch
,
1171 &serialPortIterator
);
1172 if (kernResult
== KERN_SUCCESS
)
1174 while ((serialService
= IOIteratorNext(serialPortIterator
)))
1176 CFTypeRef serialNameAsCFString
;
1177 CFTypeRef bsdPathAsCFString
;
1178 char serialName
[128];
1183 serialNameAsCFString
=
1184 IORegistryEntryCreateCFProperty(serialService
,
1185 CFSTR(kIOTTYDeviceKey
),
1186 kCFAllocatorDefault
, 0);
1187 if (serialNameAsCFString
)
1189 result
= CFStringGetCString(serialNameAsCFString
, serialName
,
1191 kCFStringEncodingASCII
);
1192 CFRelease(serialNameAsCFString
);
1197 IORegistryEntryCreateCFProperty(serialService
,
1198 CFSTR(kIOCalloutDeviceKey
),
1199 kCFAllocatorDefault
, 0);
1200 if (bsdPathAsCFString
)
1202 result
= CFStringGetCString(bsdPathAsCFString
, bsdPath
,
1204 kCFStringEncodingASCII
);
1205 CFRelease(bsdPathAsCFString
);
1208 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
1209 bsdPath
, serialName
);
1214 IOObjectRelease(serialService
);
1218 * Release the iterator.
1221 IOObjectRelease(serialPortIterator
);
1229 * End of "$Id: serial.c 6068 2006-10-27 17:10:34Z mike $".