/*
- * "$Id: serial.c 6591 2007-06-21 20:35:28Z mike $"
+ * "$Id: serial.c 7647 2008-06-16 17:39:40Z mike $"
*
- * Serial port backend for the Common UNIX Printing System (CUPS).
+ * Serial port backend for CUPS.
*
+ * Copyright 2007-2011 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
* "LICENSE" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* This file is subject to the Apple OS-Developed Software exception.
*
*/
#include "backend-private.h"
+#include <stdio.h>
#ifdef __hpux
# include <sys/modem.h>
*/
static void list_devices(void);
-static void side_cb(int print_fd, int device_fd, int use_bc);
+static int side_cb(int print_fd, int device_fd, int use_bc);
/*
username[255], /* Username info (not used) */
resource[1024], /* Resource info (device and options) */
*options, /* Pointer to options */
- name[255], /* Name of option */
- value[255], /* Value of option */
- *ptr; /* Pointer into name or value */
+ *name, /* Name of option */
+ *value, /* Value of option */
+ sep; /* Option separator */
int port; /* Port number (not used) */
int copies; /* Number of copies to print */
- int print_fd, /* Print file */
+ int side_eof = 0, /* Saw EOF on side-channel? */
+ print_fd, /* Print file */
device_fd; /* Serial device */
int nfds; /* Maximum file descriptor value + 1 */
fd_set input, /* Input set for reading */
}
else if (argc < 6 || argc > 7)
{
- fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
- argv[0]);
+ _cupsLangPrintf(stderr,
+ _("Usage: %s job-id user title copies options [file]"),
+ argv[0]);
return (CUPS_BACKEND_FAILED);
}
if ((print_fd = open(argv[6], O_RDONLY)) < 0)
{
- perror("ERROR: unable to open print file");
+ _cupsLangPrintError("ERROR", _("Unable to open print file"));
return (CUPS_BACKEND_FAILED);
}
* available printer in the class.
*/
- fputs(_("INFO: Unable to contact printer, queuing on next "
- "printer in class...\n"), stderr);
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Unable to contact printer, queuing on next "
+ "printer in class."));
/*
* Sleep 5 seconds to keep the job from requeuing too rapidly...
if (errno == EBUSY)
{
- fputs(_("INFO: Printer busy; will retry in 30 seconds...\n"), stderr);
+ _cupsLangPrintFilter(stderr, "INFO",
+ _("Printer busy; will retry in 30 seconds."));
sleep(30);
}
else
{
- fprintf(stderr, _("ERROR: Unable to open device file \"%s\": %s\n"),
- resource, strerror(errno));
+ _cupsLangPrintError("ERROR", _("Unable to open device file"));
return (CUPS_BACKEND_FAILED);
}
}
* Get the name...
*/
- for (ptr = name; *options && *options != '=';)
- if (ptr < (name + sizeof(name) - 1))
- *ptr++ = *options++;
- *ptr = '\0';
+ name = options;
+
+ while (*options && *options != '=' && *options != '+' && *options != '&')
+ options ++;
+
+ if ((sep = *options) != '\0')
+ *options++ = '\0';
- if (*options == '=')
+ if (sep == '=')
{
/*
* Get the value...
*/
- options ++;
-
- for (ptr = value; *options && *options != '+' && *options != '&';)
- if (ptr < (value + sizeof(value) - 1))
- *ptr++ = *options++;
- *ptr = '\0';
+ value = options;
- if (*options == '+' || *options == '&')
+ while (*options && *options != '+' && *options != '&')
options ++;
+
+ if (*options)
+ *options++ = '\0';
}
else
- value[0] = '\0';
+ value = (char *)"";
/*
* Process the option...
*/
- if (!strcasecmp(name, "baud"))
+ if (!_cups_strcasecmp(name, "baud"))
{
/*
* Set the baud rate...
break;
# endif /* B230400 */
default :
- fprintf(stderr, _("WARNING: Unsupported baud rate %s!\n"),
- value);
+ _cupsLangPrintFilter(stderr, "WARNING",
+ _("Unsupported baud rate: %s"), value);
break;
}
#endif /* B19200 == 19200 */
}
- else if (!strcasecmp(name, "bits"))
+ else if (!_cups_strcasecmp(name, "bits"))
{
/*
* Set number of data bits...
break;
}
}
- else if (!strcasecmp(name, "parity"))
+ else if (!_cups_strcasecmp(name, "parity"))
{
/*
* Set parity checking...
*/
- if (!strcasecmp(value, "even"))
+ if (!_cups_strcasecmp(value, "even"))
{
opts.c_cflag |= PARENB;
opts.c_cflag &= ~PARODD;
}
- else if (!strcasecmp(value, "odd"))
+ else if (!_cups_strcasecmp(value, "odd"))
{
opts.c_cflag |= PARENB;
opts.c_cflag |= PARODD;
}
- else if (!strcasecmp(value, "none"))
+ else if (!_cups_strcasecmp(value, "none"))
opts.c_cflag &= ~PARENB;
- else if (!strcasecmp(value, "space"))
+ else if (!_cups_strcasecmp(value, "space"))
{
/*
* Note: we only support space parity with 7 bits per character...
opts.c_cflag |= CS8;
opts.c_cflag &= ~PARENB;
}
- else if (!strcasecmp(value, "mark"))
+ else if (!_cups_strcasecmp(value, "mark"))
{
/*
* Note: we only support mark parity with 7 bits per character
opts.c_cflag |= CSTOPB;
}
}
- else if (!strcasecmp(name, "flow"))
+ else if (!_cups_strcasecmp(name, "flow"))
{
/*
* Set flow control...
*/
- if (!strcasecmp(value, "none"))
+ if (!_cups_strcasecmp(value, "none"))
{
opts.c_iflag &= ~(IXON | IXOFF);
opts.c_cflag &= ~CRTSCTS;
}
- else if (!strcasecmp(value, "soft"))
+ else if (!_cups_strcasecmp(value, "soft"))
{
opts.c_iflag |= IXON | IXOFF;
opts.c_cflag &= ~CRTSCTS;
}
- else if (!strcasecmp(value, "hard") ||
- !strcasecmp(value, "rtscts"))
+ else if (!_cups_strcasecmp(value, "hard") ||
+ !_cups_strcasecmp(value, "rtscts"))
{
opts.c_iflag &= ~(IXON | IXOFF);
opts.c_cflag |= CRTSCTS;
}
- else if (!strcasecmp(value, "dtrdsr"))
+ else if (!_cups_strcasecmp(value, "dtrdsr"))
{
opts.c_iflag &= ~(IXON | IXOFF);
opts.c_cflag &= ~CRTSCTS;
dtrdsr = 1;
}
}
- else if (!strcasecmp(name, "stop"))
+ else if (!_cups_strcasecmp(name, "stop"))
{
switch (atoi(value))
{
* stdin (otherwise you can't cancel raw jobs...)
*/
- if (print_fd != 0)
+ if (!print_fd)
{
#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
sigset(SIGTERM, SIG_IGN);
if (!print_bytes)
FD_SET(print_fd, &input);
FD_SET(device_fd, &input);
- FD_SET(CUPS_SC_FD, &input);
+ if (!print_bytes && !side_eof)
+ FD_SET(CUPS_SC_FD, &input);
FD_ZERO(&output);
if (print_bytes)
*/
if (FD_ISSET(CUPS_SC_FD, &input))
- side_cb(print_fd, device_fd, 1);
+ {
+ /*
+ * Do the side-channel request, then start back over in the select
+ * loop since it may have read from print_fd...
+ */
+
+ if (side_cb(print_fd, device_fd, 1))
+ side_eof = 1;
+ continue;
+ }
/*
* Check if we have back-channel data ready...
if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
{
fprintf(stderr,
- "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n",
+ "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n",
CUPS_LLCAST bc_bytes);
cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0);
}
if (errno != EAGAIN || errno != EINTR)
{
- perror("ERROR: Unable to read print data");
+ perror("DEBUG: Unable to read print data");
tcsetattr(device_fd, TCSADRAIN, &origopts);
if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
{
- perror("ERROR: Unable to write print data");
+ perror("DEBUG: Unable to write print data");
tcsetattr(device_fd, TCSADRAIN, &origopts);
if (print_fd != 0)
close(print_fd);
- return (total_bytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
+ return (CUPS_BACKEND_OK);
}
static void
list_devices(void)
{
-#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
/* Funky hex numbering used for some *
* devices */
-#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
+#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ || __FreeBSD_kernel__ */
+
#ifdef __linux
int i, j; /* Looping vars */
int fd; /* File descriptor */
char device[255]; /* Device filename */
+ char info[255]; /* Device info/description */
# ifdef TIOCGSERIAL
struct serial_struct serinfo; /* serial port info */
# endif /* TIOCGSERIAL */
close(fd);
+ snprintf(info, sizeof(info),
+ _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
# if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
- printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
- device, i + 1);
+ printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device, info);
# else
- printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
- device, i + 1);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
# endif /* _ARCH_PPC || powerpc || __powerpc */
}
}
for (i = 0; i < 16; i ++)
{
+ snprintf(info, sizeof(info),
+ _cupsLangString(cupsLangDefault(), _("USB Serial Port #%d")),
+ i + 1);
+
sprintf(device, "/dev/usb/ttyUSB%d", i);
if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
{
close(fd);
- printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
- device, i + 1);
+ printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device, info);
}
sprintf(device, "/dev/ttyUSB%d", i);
if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
{
close(fd);
- printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
- device, i + 1);
+ printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device, info);
}
}
if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
{
close(fd);
+
printf("serial serial:%s?baud=115200 \"Unknown\" "
- "\"Equinox ESP %d Port #%d\"\n",
- device, i, j + 1);
+ "\"Equinox ESP %d Port #%d\"\n", device, i, j + 1);
}
}
}
}
}
#elif defined(__sun)
- int i, j, n; /* Looping vars */
- char device[255]; /* Device filename */
+ int i, j, n; /* Looping vars */
+ char device[255]; /* Device filename */
+ char info[255]; /* Device info/description */
/*
for (i = 0; i < 26; i ++)
{
sprintf(device, "/dev/cua/%c", 'a' + i);
- if (access(device, 0) == 0)
+ if (!access(device, 0))
+ {
+ snprintf(info, sizeof(info),
+ _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
# ifdef B115200
- printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
- device, i + 1);
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
# else
- printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
- device, i + 1);
+ printf("serial serial:%s?baud=38400 \"Unknown\" \"%s\"\n", device, info);
# endif /* B115200 */
+ }
}
/*
printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
device, i + 1);
}
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
- int i, j; /* Looping vars */
- int fd; /* File descriptor */
- char device[255]; /* Device filename */
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+ int i, j; /* Looping vars */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+ char info[255]; /* Device info/description */
/*
if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
{
close(fd);
- printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
- device, i + 1);
+
+ snprintf(info, sizeof(info),
+ _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
}
}
}
}
#elif defined(__NetBSD__)
- int i, j; /* Looping vars */
- int fd; /* File descriptor */
- char device[255]; /* Device filename */
+ int i, j; /* Looping vars */
+ int fd; /* File descriptor */
+ char device[255]; /* Device filename */
+ char info[255]; /* Device info/description */
/*
if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
{
close(fd);
- printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
- device, i + 1);
+
+ snprintf(info, sizeof(info),
+ _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
}
}
{
CFTypeRef serialNameAsCFString;
CFTypeRef bsdPathAsCFString;
+ CFTypeRef hiddenVal;
char serialName[128];
char bsdPath[1024];
Boolean result;
- serialNameAsCFString =
- IORegistryEntryCreateCFProperty(serialService,
- CFSTR(kIOTTYDeviceKey),
- kCFAllocatorDefault, 0);
- if (serialNameAsCFString)
+ /* Check if hidden... */
+ hiddenVal = IORegistryEntrySearchCFProperty(serialService,
+ kIOServicePlane,
+ CFSTR("HiddenPort"),
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively |
+ kIORegistryIterateParents);
+ if (hiddenVal)
+ CFRelease(hiddenVal); /* This interface should not be used */
+ else
{
- result = CFStringGetCString(serialNameAsCFString, serialName,
- sizeof(serialName),
- kCFStringEncodingASCII);
- CFRelease(serialNameAsCFString);
-
- if (result)
+ serialNameAsCFString =
+ IORegistryEntryCreateCFProperty(serialService,
+ CFSTR(kIOTTYDeviceKey),
+ kCFAllocatorDefault, 0);
+ if (serialNameAsCFString)
{
- bsdPathAsCFString =
- IORegistryEntryCreateCFProperty(serialService,
- CFSTR(kIOCalloutDeviceKey),
- kCFAllocatorDefault, 0);
- if (bsdPathAsCFString)
+ result = CFStringGetCString(serialNameAsCFString, serialName,
+ sizeof(serialName),
+ kCFStringEncodingASCII);
+ CFRelease(serialNameAsCFString);
+
+ if (result)
{
- result = CFStringGetCString(bsdPathAsCFString, bsdPath,
- sizeof(bsdPath),
- kCFStringEncodingASCII);
- CFRelease(bsdPathAsCFString);
-
- if (result)
- printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
- bsdPath, serialName);
+ bsdPathAsCFString =
+ IORegistryEntryCreateCFProperty(serialService,
+ CFSTR(kIOCalloutDeviceKey),
+ kCFAllocatorDefault, 0);
+ if (bsdPathAsCFString)
+ {
+ result = CFStringGetCString(bsdPathAsCFString, bsdPath,
+ sizeof(bsdPath),
+ kCFStringEncodingASCII);
+ CFRelease(bsdPathAsCFString);
+
+ if (result)
+ printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
+ bsdPath, serialName);
+ }
}
}
}
* 'side_cb()' - Handle side-channel requests...
*/
-static void
+static int /* O - 0 on success, -1 on error */
side_cb(int print_fd, /* I - Print file */
int device_fd, /* I - Device file */
int use_bc) /* I - Using back-channel? */
datalen = sizeof(data);
if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
- {
- fputs(_("WARNING: Failed to read side-channel request!\n"), stderr);
- return;
- }
+ return (-1);
switch (command)
{
break;
case CUPS_SC_CMD_GET_BIDI :
+ status = CUPS_SC_STATUS_OK;
data[0] = use_bc;
datalen = 1;
break;
break;
}
- cupsSideChannelWrite(command, status, data, datalen, 1.0);
+ return (cupsSideChannelWrite(command, status, data, datalen, 1.0));
}
/*
- * End of "$Id: serial.c 6591 2007-06-21 20:35:28Z mike $".
+ * End of "$Id: serial.c 7647 2008-06-16 17:39:40Z mike $".
*/