2 * "$Id: serial.c 7647 2008-06-16 17:39:40Z mike $"
4 * Serial port backend for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * "LICENSE" which should have been included with this file. If this
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * main() - Send a file to the printer or server.
20 * list_devices() - List all serial devices.
21 * side_cb() - Handle side-channel requests...
25 * Include necessary headers.
28 #include "backend-private.h"
31 # include <sys/modem.h>
41 # include <sys/time.h>
43 # include <sys/select.h>
45 # ifdef HAVE_SYS_IOCTL_H
46 # include <sys/ioctl.h>
47 # endif /* HAVE_SYS_IOCTL_H */
52 # ifndef INV_EPP_ECP_PLP
53 # define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */
54 # define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */
55 # define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */
56 # define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */
57 # define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */
58 # endif /* !INV_EPP_ECP_PLP */
63 # define CRTSCTS CNEW_RTSCTS
66 # endif /* CNEW_RTSCTS */
69 #if defined(__APPLE__)
70 # include <CoreFoundation/CoreFoundation.h>
71 # include <IOKit/IOKitLib.h>
72 # include <IOKit/serial/IOSerialKeys.h>
73 # include <IOKit/IOBSD.h>
74 #endif /* __APPLE__ */
76 #if defined(__linux) && defined(TIOCGSERIAL)
77 # include <linux/serial.h>
78 # include <linux/ioctl.h>
79 #endif /* __linux && TIOCGSERIAL */
86 static void list_devices(void);
87 static int side_cb(int print_fd
, int device_fd
, int use_bc
);
91 * 'main()' - Send a file to the printer or server.
95 * printer-uri job-id user title copies options [file]
98 int /* O - Exit status */
99 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
100 char *argv
[]) /* I - Command-line arguments */
102 char method
[255], /* Method in URI */
103 hostname
[1024], /* Hostname */
104 username
[255], /* Username info (not used) */
105 resource
[1024], /* Resource info (device and options) */
106 *options
, /* Pointer to options */
107 *name
, /* Name of option */
108 *value
, /* Value of option */
109 sep
; /* Option separator */
110 int port
; /* Port number (not used) */
111 int copies
; /* Number of copies to print */
112 int side_eof
= 0, /* Saw EOF on side-channel? */
113 print_fd
, /* Print file */
114 device_fd
; /* Serial device */
115 int nfds
; /* Maximum file descriptor value + 1 */
116 fd_set input
, /* Input set for reading */
117 output
; /* Output set for writing */
118 ssize_t print_bytes
, /* Print bytes read */
119 bc_bytes
, /* Backchannel bytes read */
120 total_bytes
, /* Total bytes written */
121 bytes
; /* Bytes written */
122 int dtrdsr
; /* Do dtr/dsr flow control? */
123 int print_size
; /* Size of output buffer for writes */
124 char print_buffer
[8192], /* Print data buffer */
125 *print_ptr
, /* Pointer into print data buffer */
126 bc_buffer
[1024]; /* Back-channel data buffer */
127 struct termios opts
; /* Serial port options */
128 struct termios origopts
; /* Original port options */
129 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
130 struct sigaction action
; /* Actions for POSIX signals */
131 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
135 * Make sure status messages are not buffered...
138 setbuf(stderr
, NULL
);
141 * Ignore SIGPIPE signals...
145 sigset(SIGPIPE
, SIG_IGN
);
146 #elif defined(HAVE_SIGACTION)
147 memset(&action
, 0, sizeof(action
));
148 action
.sa_handler
= SIG_IGN
;
149 sigaction(SIGPIPE
, &action
, NULL
);
151 signal(SIGPIPE
, SIG_IGN
);
152 #endif /* HAVE_SIGSET */
155 * Check command-line...
161 return (CUPS_BACKEND_OK
);
163 else if (argc
< 6 || argc
> 7)
165 _cupsLangPrintf(stderr
,
166 _("Usage: %s job-id user title copies options [file]\n"),
168 return (CUPS_BACKEND_FAILED
);
172 * If we have 7 arguments, print the file named on the command-line.
173 * Otherwise, send stdin instead...
184 * Try to open the print file...
187 if ((print_fd
= open(argv
[6], O_RDONLY
)) < 0)
189 _cupsLangPrintf(stderr
,
190 _("ERROR: Unable to open print file \"%s\": %s\n"),
191 argv
[6], strerror(errno
));
192 return (CUPS_BACKEND_FAILED
);
195 copies
= atoi(argv
[4]);
199 * Extract the device name and options from the URI...
202 httpSeparateURI(HTTP_URI_CODING_ALL
, cupsBackendDeviceURI(argv
),
203 method
, sizeof(method
), username
, sizeof(username
),
204 hostname
, sizeof(hostname
), &port
,
205 resource
, sizeof(resource
));
208 * See if there are any options...
211 if ((options
= strchr(resource
, '?')) != NULL
)
214 * Yup, terminate the device name string and move to the first
215 * character of the options...
222 * Open the serial port device...
225 fputs("STATE: +connecting-to-device\n", stderr
);
229 if ((device_fd
= open(resource
, O_RDWR
| O_NOCTTY
| O_EXCL
|
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 _cupsLangPuts(stderr
,
242 _("INFO: Unable to contact printer, queuing on next "
243 "printer in class...\n"));
246 * Sleep 5 seconds to keep the job from requeuing too rapidly...
251 return (CUPS_BACKEND_FAILED
);
256 _cupsLangPuts(stderr
,
257 _("INFO: Printer busy; will retry in 30 seconds...\n"));
262 _cupsLangPrintf(stderr
,
263 _("ERROR: Unable to open device file \"%s\": %s\n"),
264 resource
, strerror(errno
));
265 return (CUPS_BACKEND_FAILED
);
269 while (device_fd
< 0);
271 fputs("STATE: -connecting-to-device\n", stderr
);
274 * Set any options provided...
277 tcgetattr(device_fd
, &origopts
);
278 tcgetattr(device_fd
, &opts
);
280 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
);
282 opts
.c_oflag
&= ~OPOST
; /* Don't post-process */
284 print_size
= 96; /* 9600 baud / 10 bits/char / 10Hz */
285 dtrdsr
= 0; /* No dtr/dsr flow control */
297 while (*options
&& *options
!= '=' && *options
!= '+' && *options
!= '&')
300 if ((sep
= *options
) != '\0')
311 while (*options
&& *options
!= '+' && *options
!= '&')
321 * Process the option...
324 if (!strcasecmp(name
, "baud"))
327 * Set the baud rate...
330 print_size
= atoi(value
) / 100;
333 cfsetispeed(&opts
, atoi(value
));
334 cfsetospeed(&opts
, atoi(value
));
339 cfsetispeed(&opts
, B1200
);
340 cfsetospeed(&opts
, B1200
);
343 cfsetispeed(&opts
, B2400
);
344 cfsetospeed(&opts
, B2400
);
347 cfsetispeed(&opts
, B4800
);
348 cfsetospeed(&opts
, B4800
);
351 cfsetispeed(&opts
, B9600
);
352 cfsetospeed(&opts
, B9600
);
355 cfsetispeed(&opts
, B19200
);
356 cfsetospeed(&opts
, B19200
);
359 cfsetispeed(&opts
, B38400
);
360 cfsetospeed(&opts
, B38400
);
364 cfsetispeed(&opts
, B57600
);
365 cfsetospeed(&opts
, B57600
);
370 cfsetispeed(&opts
, B115200
);
371 cfsetospeed(&opts
, B115200
);
373 # endif /* B115200 */
376 cfsetispeed(&opts
, B230400
);
377 cfsetospeed(&opts
, B230400
);
379 # endif /* B230400 */
381 _cupsLangPrintf(stderr
, _("WARNING: Unsupported baud rate %s\n"),
385 #endif /* B19200 == 19200 */
387 else if (!strcasecmp(name
, "bits"))
390 * Set number of data bits...
396 opts
.c_cflag
&= ~CSIZE
;
398 opts
.c_cflag
|= PARENB
;
399 opts
.c_cflag
&= ~PARODD
;
402 opts
.c_cflag
&= ~CSIZE
;
404 opts
.c_cflag
&= ~PARENB
;
408 else if (!strcasecmp(name
, "parity"))
411 * Set parity checking...
414 if (!strcasecmp(value
, "even"))
416 opts
.c_cflag
|= PARENB
;
417 opts
.c_cflag
&= ~PARODD
;
419 else if (!strcasecmp(value
, "odd"))
421 opts
.c_cflag
|= PARENB
;
422 opts
.c_cflag
|= PARODD
;
424 else if (!strcasecmp(value
, "none"))
425 opts
.c_cflag
&= ~PARENB
;
426 else if (!strcasecmp(value
, "space"))
429 * Note: we only support space parity with 7 bits per character...
432 opts
.c_cflag
&= ~CSIZE
;
434 opts
.c_cflag
&= ~PARENB
;
436 else if (!strcasecmp(value
, "mark"))
439 * Note: we only support mark parity with 7 bits per character
443 opts
.c_cflag
&= ~CSIZE
;
445 opts
.c_cflag
&= ~PARENB
;
446 opts
.c_cflag
|= CSTOPB
;
449 else if (!strcasecmp(name
, "flow"))
452 * Set flow control...
455 if (!strcasecmp(value
, "none"))
457 opts
.c_iflag
&= ~(IXON
| IXOFF
);
458 opts
.c_cflag
&= ~CRTSCTS
;
460 else if (!strcasecmp(value
, "soft"))
462 opts
.c_iflag
|= IXON
| IXOFF
;
463 opts
.c_cflag
&= ~CRTSCTS
;
465 else if (!strcasecmp(value
, "hard") ||
466 !strcasecmp(value
, "rtscts"))
468 opts
.c_iflag
&= ~(IXON
| IXOFF
);
469 opts
.c_cflag
|= CRTSCTS
;
471 else if (!strcasecmp(value
, "dtrdsr"))
473 opts
.c_iflag
&= ~(IXON
| IXOFF
);
474 opts
.c_cflag
&= ~CRTSCTS
;
479 else if (!strcasecmp(name
, "stop"))
484 opts
.c_cflag
&= ~CSTOPB
;
488 opts
.c_cflag
|= CSTOPB
;
495 tcsetattr(device_fd
, TCSANOW
, &opts
);
496 fcntl(device_fd
, F_SETFL
, 0);
499 * Now that we are "connected" to the port, ignore SIGTERM so that we
500 * can finish out any page data the driver sends (e.g. to eject the
501 * current page... Only ignore SIGTERM if we are printing data from
502 * stdin (otherwise you can't cancel raw jobs...)
507 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
508 sigset(SIGTERM
, SIG_IGN
);
509 #elif defined(HAVE_SIGACTION)
510 memset(&action
, 0, sizeof(action
));
512 sigemptyset(&action
.sa_mask
);
513 action
.sa_handler
= SIG_IGN
;
514 sigaction(SIGTERM
, &action
, NULL
);
516 signal(SIGTERM
, SIG_IGN
);
517 #endif /* HAVE_SIGSET */
521 * Figure out the maximum file descriptor value to use with select()...
524 nfds
= (print_fd
> device_fd
? print_fd
: device_fd
) + 1;
527 * Finally, send the print file. Ordinarily we would just use the
528 * backendRunLoop() function, however since we need to use smaller
529 * writes and may need to do DSR/DTR flow control, we duplicate much
530 * of the code here instead...
533 if (print_size
> sizeof(print_buffer
))
534 print_size
= sizeof(print_buffer
);
544 fputs("PAGE: 1 1\n", stderr
);
545 lseek(print_fd
, 0, SEEK_SET
);
549 * Now loop until we are out of data from print_fd...
552 for (print_bytes
= 0, print_ptr
= print_buffer
;;)
555 * Use select() to determine whether we have data to copy around...
560 FD_SET(print_fd
, &input
);
561 FD_SET(device_fd
, &input
);
562 if (!print_bytes
&& !side_eof
)
563 FD_SET(CUPS_SC_FD
, &input
);
567 FD_SET(device_fd
, &output
);
569 if (select(nfds
, &input
, &output
, NULL
, NULL
) < 0)
570 continue; /* Ignore errors here */
573 * Check if we have a side-channel request ready...
576 if (FD_ISSET(CUPS_SC_FD
, &input
))
579 * Do the side-channel request, then start back over in the select
580 * loop since it may have read from print_fd...
583 if (side_cb(print_fd
, device_fd
, 1))
589 * Check if we have back-channel data ready...
592 if (FD_ISSET(device_fd
, &input
))
594 if ((bc_bytes
= read(device_fd
, bc_buffer
, sizeof(bc_buffer
))) > 0)
597 "DEBUG: Received " CUPS_LLFMT
" bytes of back-channel data\n",
598 CUPS_LLCAST bc_bytes
);
599 cupsBackChannelWrite(bc_buffer
, bc_bytes
, 1.0);
604 * Check if we have print data ready...
607 if (FD_ISSET(print_fd
, &input
))
609 if ((print_bytes
= read(print_fd
, print_buffer
, print_size
)) < 0)
612 * Read error - bail if we don't see EAGAIN or EINTR...
615 if (errno
!= EAGAIN
|| errno
!= EINTR
)
617 _cupsLangPrintError(_("ERROR: Unable to read print data"));
619 tcsetattr(device_fd
, TCSADRAIN
, &origopts
);
626 return (CUPS_BACKEND_FAILED
);
631 else if (print_bytes
== 0)
634 * End of file, break out of the loop...
640 print_ptr
= print_buffer
;
644 * Check if the device is ready to receive data and we have data to
648 if (print_bytes
&& FD_ISSET(device_fd
, &output
))
653 * Check the port and sleep until DSR is set...
659 if (!ioctl(device_fd
, TIOCMGET
, &status
))
660 if (!(status
& TIOCM_DSR
))
663 * Wait for DSR to go high...
666 fputs("DEBUG: DSR is low; waiting for device...\n", stderr
);
671 * Poll every 100ms...
676 if (ioctl(device_fd
, TIOCMGET
, &status
))
679 while (!(status
& TIOCM_DSR
));
681 fputs("DEBUG: DSR is high; writing to device...\n", stderr
);
685 if ((bytes
= write(device_fd
, print_ptr
, print_bytes
)) < 0)
688 * Write error - bail if we don't see an error we can retry...
691 if (errno
!= EAGAIN
&& errno
!= EINTR
&& errno
!= ENOTTY
)
693 _cupsLangPrintError(_("ERROR: Unable to write print data"));
695 tcsetattr(device_fd
, TCSADRAIN
, &origopts
);
702 return (CUPS_BACKEND_FAILED
);
707 fprintf(stderr
, "DEBUG: Wrote %d bytes...\n", (int)bytes
);
709 print_bytes
-= bytes
;
711 total_bytes
+= bytes
;
718 * Close the serial port and input file and return...
721 tcsetattr(device_fd
, TCSADRAIN
, &origopts
);
728 return (total_bytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
733 * 'list_devices()' - List all serial devices.
739 #if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
740 static char *funky_hex
= "0123456789abcdefghijklmnopqrstuvwxyz";
741 /* Funky hex numbering used for some *
743 #endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ || __FreeBSD_kernel__ */
747 int i
, j
; /* Looping vars */
748 int fd
; /* File descriptor */
749 char device
[255]; /* Device filename */
750 char info
[255]; /* Device info/description */
752 struct serial_struct serinfo
; /* serial port info */
753 # endif /* TIOCGSERIAL */
756 for (i
= 0; i
< 100; i
++)
758 sprintf(device
, "/dev/ttyS%d", i
);
760 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
764 * See if this port exists...
767 serinfo
.reserved_char
[0] = 0;
769 if (!ioctl(fd
, TIOCGSERIAL
, &serinfo
))
771 if (serinfo
.type
== PORT_UNKNOWN
)
781 # endif /* TIOCGSERIAL */
785 snprintf(info
, sizeof(info
),
786 _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i
+ 1);
788 # if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
789 printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device
, info
);
791 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device
, info
);
792 # endif /* _ARCH_PPC || powerpc || __powerpc */
796 for (i
= 0; i
< 16; i
++)
798 snprintf(info
, sizeof(info
),
799 _cupsLangString(cupsLangDefault(), _("USB Serial Port #%d")),
802 sprintf(device
, "/dev/usb/ttyUSB%d", i
);
803 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
806 printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device
, info
);
809 sprintf(device
, "/dev/ttyUSB%d", i
);
810 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
813 printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device
, info
);
817 for (i
= 0; i
< 64; i
++)
819 for (j
= 0; j
< 8; j
++)
821 sprintf(device
, "/dev/ttyQ%02de%d", i
, j
);
822 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
826 printf("serial serial:%s?baud=115200 \"Unknown\" "
827 "\"Equinox ESP %d Port #%d\"\n", device
, i
, j
+ 1);
832 int i
, j
, n
; /* Looping vars */
833 char device
[255]; /* Device filename */
834 inventory_t
*inv
; /* Hardware inventory info */
838 * IRIX maintains a hardware inventory of most devices...
843 while ((inv
= getinvent()) != NULL
)
845 if (inv
->inv_class
== INV_SERIAL
)
848 * Some sort of serial port...
851 if (inv
->inv_type
== INV_CDSIO
|| inv
->inv_type
== INV_CDSIO_E
)
857 for (n
= 0; n
< 6; n
++)
858 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n",
859 n
+ 5 + 8 * inv
->inv_controller
, inv
->inv_controller
, n
+ 1);
861 else if (inv
->inv_type
== INV_EPC_SERIAL
)
864 * Everest serial port...
867 if (inv
->inv_unit
== 0)
870 i
= 41 + 4 * (int)inv
->inv_controller
;
872 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
873 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n",
874 n
+ i
, n
+ 1, (int)inv
->inv_controller
);
876 else if (inv
->inv_state
> 1)
879 * Standard serial port under IRIX 6.4 and earlier...
882 for (n
= 0; n
< (int)inv
->inv_state
; n
++)
883 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n",
884 n
+ (int)inv
->inv_unit
+ 1, n
+ (int)inv
->inv_unit
+ 1);
889 * Standard serial port under IRIX 6.5 and beyond...
892 printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n",
893 (int)inv
->inv_controller
, (int)inv
->inv_controller
);
901 * Central Data makes serial and parallel "servers" that can be
902 * connected in a number of ways. Look for ports...
905 for (i
= 0; i
< 10; i
++)
906 for (j
= 0; j
< 8; j
++)
907 for (n
= 0; n
< 32; n
++)
909 if (i
== 8) /* EtherLite */
910 sprintf(device
, "/dev/ttydn%d%c", j
, funky_hex
[n
]);
911 else if (i
== 9) /* PCI */
912 sprintf(device
, "/dev/ttydp%d%c", j
, funky_hex
[n
]);
914 sprintf(device
, "/dev/ttyd%d%d%c", i
, j
, funky_hex
[n
]);
916 if (access(device
, 0) == 0)
919 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
922 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n",
925 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
930 int i
, j
, n
; /* Looping vars */
931 char device
[255]; /* Device filename */
932 char info
[255]; /* Device info/description */
936 * Standard serial ports...
939 for (i
= 0; i
< 26; i
++)
941 sprintf(device
, "/dev/cua/%c", 'a' + i
);
942 if (!access(device
, 0))
944 snprintf(info
, sizeof(info
),
945 _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i
+ 1);
948 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device
, info
);
950 printf("serial serial:%s?baud=38400 \"Unknown\" \"%s\"\n", device
, info
);
951 # endif /* B115200 */
956 * MAGMA serial ports...
959 for (i
= 0; i
< 40; i
++)
961 sprintf(device
, "/dev/term/%02d", i
);
962 if (access(device
, 0) == 0)
963 printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n",
964 device
, (i
/ 10) + 1, (i
% 10) + 1);
968 * Central Data serial ports...
971 for (i
= 0; i
< 9; i
++)
972 for (j
= 0; j
< 8; j
++)
973 for (n
= 0; n
< 32; n
++)
975 if (i
== 8) /* EtherLite */
976 sprintf(device
, "/dev/sts/ttyN%d%c", j
, funky_hex
[n
]);
978 sprintf(device
, "/dev/sts/tty%c%d%c", i
+ 'C', j
,
981 if (access(device
, 0) == 0)
984 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
987 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
991 #elif defined(__hpux)
992 int i
, j
, n
; /* Looping vars */
993 char device
[255]; /* Device filename */
997 * Standard serial ports...
1000 for (i
= 0; i
< 10; i
++)
1002 sprintf(device
, "/dev/tty%dp0", i
);
1003 if (access(device
, 0) == 0)
1004 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
1009 * Central Data serial ports...
1012 for (i
= 0; i
< 9; i
++)
1013 for (j
= 0; j
< 8; j
++)
1014 for (n
= 0; n
< 32; n
++)
1016 if (i
== 8) /* EtherLite */
1017 sprintf(device
, "/dev/ttyN%d%c", j
, funky_hex
[n
]);
1019 sprintf(device
, "/dev/tty%c%d%c", i
+ 'C', j
,
1022 if (access(device
, 0) == 0)
1025 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
1028 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
1032 #elif defined(__osf__)
1033 int i
; /* Looping var */
1034 char device
[255]; /* Device filename */
1038 * Standard serial ports...
1041 for (i
= 0; i
< 100; i
++)
1043 sprintf(device
, "/dev/tty%02d", i
);
1044 if (access(device
, 0) == 0)
1045 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
1048 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
1049 int i
, j
; /* Looping vars */
1050 int fd
; /* File descriptor */
1051 char device
[255]; /* Device filename */
1052 char info
[255]; /* Device info/description */
1059 for (i
= 0; i
< 32; i
++)
1061 sprintf(device
, "/dev/ttyd%c", funky_hex
[i
]);
1062 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1066 snprintf(info
, sizeof(info
),
1067 _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i
+ 1);
1069 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device
, info
);
1077 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1078 for (j
= 0; j
< 32; j
++)
1080 sprintf(device
, "/dev/ttyc%d%c", i
, funky_hex
[j
]);
1081 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1084 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
1088 sprintf(device
, "/dev/ttyC%d%c", i
, funky_hex
[j
]);
1089 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1092 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
1098 * Digiboard ports...
1101 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1102 for (j
= 0; j
< 32; j
++)
1104 sprintf(device
, "/dev/ttyD%d%c", i
, funky_hex
[j
]);
1105 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1108 printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n",
1117 for (i
= 0; i
< 32; i
++)
1119 sprintf(device
, "/dev/ttyE%c", funky_hex
[i
]);
1120 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1123 printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n",
1132 for (i
= 0; i
< 128; i
++)
1134 sprintf(device
, "/dev/ttyA%d", i
+ 1);
1135 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1138 printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n",
1142 #elif defined(__NetBSD__)
1143 int i
, j
; /* Looping vars */
1144 int fd
; /* File descriptor */
1145 char device
[255]; /* Device filename */
1146 char info
[255]; /* Device info/description */
1150 * Standard serial ports...
1153 for (i
= 0; i
< 4; i
++)
1155 sprintf(device
, "/dev/tty%02d", i
);
1156 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1160 snprintf(info
, sizeof(info
),
1161 _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i
+ 1);
1163 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device
, info
);
1168 * Cyclades-Z ports...
1171 for (i
= 0; i
< 16; i
++) /* Should be up to 65536 boards... */
1172 for (j
= 0; j
< 64; j
++)
1174 sprintf(device
, "/dev/ttyCZ%02d%02d", i
, j
);
1175 if ((fd
= open(device
, O_WRONLY
| O_NOCTTY
| O_NDELAY
)) >= 0)
1178 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n",
1182 #elif defined(__APPLE__)
1184 * Standard serial ports on MacOS X...
1187 kern_return_t kernResult
;
1188 mach_port_t masterPort
;
1189 io_iterator_t serialPortIterator
;
1190 CFMutableDictionaryRef classesToMatch
;
1191 io_object_t serialService
;
1194 kernResult
= IOMasterPort(MACH_PORT_NULL
, &masterPort
);
1195 if (KERN_SUCCESS
!= kernResult
)
1199 * Serial devices are instances of class IOSerialBSDClient.
1202 classesToMatch
= IOServiceMatching(kIOSerialBSDServiceValue
);
1203 if (classesToMatch
!= NULL
)
1205 CFDictionarySetValue(classesToMatch
, CFSTR(kIOSerialBSDTypeKey
),
1206 CFSTR(kIOSerialBSDRS232Type
));
1208 kernResult
= IOServiceGetMatchingServices(masterPort
, classesToMatch
,
1209 &serialPortIterator
);
1210 if (kernResult
== KERN_SUCCESS
)
1212 while ((serialService
= IOIteratorNext(serialPortIterator
)))
1214 CFTypeRef serialNameAsCFString
;
1215 CFTypeRef bsdPathAsCFString
;
1216 CFTypeRef hiddenVal
;
1217 char serialName
[128];
1222 /* Check if hidden... */
1223 hiddenVal
= IORegistryEntrySearchCFProperty(serialService
,
1225 CFSTR("HiddenPort"),
1226 kCFAllocatorDefault
,
1227 kIORegistryIterateRecursively
|
1228 kIORegistryIterateParents
);
1230 CFRelease(hiddenVal
); /* This interface should not be used */
1233 serialNameAsCFString
=
1234 IORegistryEntryCreateCFProperty(serialService
,
1235 CFSTR(kIOTTYDeviceKey
),
1236 kCFAllocatorDefault
, 0);
1237 if (serialNameAsCFString
)
1239 result
= CFStringGetCString(serialNameAsCFString
, serialName
,
1241 kCFStringEncodingASCII
);
1242 CFRelease(serialNameAsCFString
);
1247 IORegistryEntryCreateCFProperty(serialService
,
1248 CFSTR(kIOCalloutDeviceKey
),
1249 kCFAllocatorDefault
, 0);
1250 if (bsdPathAsCFString
)
1252 result
= CFStringGetCString(bsdPathAsCFString
, bsdPath
,
1254 kCFStringEncodingASCII
);
1255 CFRelease(bsdPathAsCFString
);
1258 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
1259 bsdPath
, serialName
);
1265 IOObjectRelease(serialService
);
1269 * Release the iterator.
1272 IOObjectRelease(serialPortIterator
);
1280 * 'side_cb()' - Handle side-channel requests...
1283 static int /* O - 0 on success, -1 on error */
1284 side_cb(int print_fd
, /* I - Print file */
1285 int device_fd
, /* I - Device file */
1286 int use_bc
) /* I - Using back-channel? */
1288 cups_sc_command_t command
; /* Request command */
1289 cups_sc_status_t status
; /* Request/response status */
1290 char data
[2048]; /* Request/response data */
1291 int datalen
; /* Request/response data size */
1294 datalen
= sizeof(data
);
1296 if (cupsSideChannelRead(&command
, &status
, data
, &datalen
, 1.0))
1301 case CUPS_SC_CMD_DRAIN_OUTPUT
:
1302 if (backendDrainOutput(print_fd
, device_fd
))
1303 status
= CUPS_SC_STATUS_IO_ERROR
;
1304 else if (tcdrain(device_fd
))
1305 status
= CUPS_SC_STATUS_IO_ERROR
;
1307 status
= CUPS_SC_STATUS_OK
;
1312 case CUPS_SC_CMD_GET_BIDI
:
1313 status
= CUPS_SC_STATUS_OK
;
1319 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
1324 return (cupsSideChannelWrite(command
, status
, data
, datalen
, 1.0));
1329 * End of "$Id: serial.c 7647 2008-06-16 17:39:40Z mike $".