/*1* USB printer backend for CUPS.2*3* Copyright © 2007-2012 by Apple Inc.4* Copyright © 1997-2007 by Easy Software Products, all rights reserved.5*6* Licensed under Apache License v2.0. See the file "LICENSE" for more7* information.8*/910/*11* Include necessary headers.12*/1314#ifdef __APPLE__15/* A header order dependency requires this be first */16# include <ApplicationServices/ApplicationServices.h>17#endif /* __APPLE__ */1819#include "backend-private.h"2021#ifdef _WIN3222# include <io.h>23#else24# include <unistd.h>25# include <fcntl.h>26# include <termios.h>27#endif /* _WIN32 */282930/*31* Local functions...32*/3334void list_devices(void);35int print_device(const char *uri, const char *hostname,36const char *resource, char *options,37int print_fd, int copies, int argc, char *argv[]);383940/*41* Include the vendor-specific USB implementation...42*/4344#ifdef HAVE_LIBUSB45# include "usb-libusb.c"46#elif defined(__APPLE__)47# include "usb-darwin.c"48#elif defined(__linux) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)49# include "usb-unix.c"50#else51/*52* Use dummy functions that do nothing on unsupported platforms...53* These can be used as templates for implementing USB printing on new54* platforms...55*/5657/*58* 'list_devices()' - List all available USB devices to stdout.59*/6061void62list_devices(void)63{64/*65* Don't have any devices to list... Use output of the form:66*67* direct usb:/make/model?serial=foo "Make Model" "USB Printer"68*69* Note that "Hewlett Packard" or any other variation MUST be mapped to70* "HP" for compatibility with the PPD and ICC specs.71*/72}737475/*76* 'print_device()' - Print a file to a USB device.77*/7879int /* O - Exit status */80print_device(const char *uri, /* I - Device URI */81const char *hostname, /* I - Hostname/manufacturer */82const char *resource, /* I - Resource/modelname */83char *options, /* I - Device options/serial number */84int print_fd, /* I - File descriptor to print */85int copies, /* I - Copies to print */86int argc, /* I - Number of command-line arguments (6 or 7) */87char *argv[]) /* I - Command-line arguments */88{89/*90* Can't print, so just reference the arguments to eliminate compiler91* warnings and return and exit status of 1. Normally you would use the92* arguments to send a file to the printer and return 0 if everything93* worked OK and non-zero if there was an error.94*/9596(void)uri;97(void)hostname;98(void)resource;99(void)options;100(void)print_fd;101(void)copies;102(void)argc;103(void)argv;104105return (CUPS_BACKEND_FAILED);106}107#endif /* HAVE_LIBUSB */108109110/*111* 'main()' - Send a file to the specified USB port.112*113* Usage:114*115* printer-uri job-id user title copies options [file]116*/117118int /* O - Exit status */119main(int argc, /* I - Number of command-line arguments (6 or 7) */120char *argv[]) /* I - Command-line arguments */121{122int print_fd; /* Print file */123int copies; /* Number of copies to print */124int status; /* Exit status */125int port; /* Port number (not used) */126const char *uri; /* Device URI */127char method[255], /* Method in URI */128hostname[1024], /* Hostname */129username[255], /* Username info (not used) */130resource[1024], /* Resource info (device and options) */131*options; /* Pointer to options */132#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)133struct sigaction action; /* Actions for POSIX signals */134#endif /* HAVE_SIGACTION && !HAVE_SIGSET */135136137/*138* Make sure status messages are not buffered...139*/140141setbuf(stderr, NULL);142143/*144* Ignore SIGPIPE signals...145*/146147#ifdef HAVE_SIGSET148sigset(SIGPIPE, SIG_IGN);149#elif defined(HAVE_SIGACTION)150memset(&action, 0, sizeof(action));151action.sa_handler = SIG_IGN;152sigaction(SIGPIPE, &action, NULL);153#else154signal(SIGPIPE, SIG_IGN);155#endif /* HAVE_SIGSET */156157/*158* Check command-line...159*/160161if (argc == 1)162{163list_devices();164return (CUPS_BACKEND_OK);165}166else if (argc < 6 || argc > 7)167{168_cupsLangPrintf(stderr,169_("Usage: %s job-id user title copies options [file]"),170argv[0]);171return (CUPS_BACKEND_FAILED);172}173174/*175* Extract the device name and options from the URI...176*/177178uri = cupsBackendDeviceURI(argv);179180if (httpSeparateURI(HTTP_URI_CODING_ALL, uri,181method, sizeof(method), username, sizeof(username),182hostname, sizeof(hostname), &port,183resource, sizeof(resource)) < HTTP_URI_OK)184{185_cupsLangPrintFilter(stderr, "ERROR",186_("No device URI found in argv[0] or in DEVICE_URI "187"environment variable."));188return (1);189}190191/*192* See if there are any options...193*/194195if ((options = strchr(resource, '?')) != NULL)196{197/*198* Yup, terminate the device name string and move to the first199* character of the options...200*/201202*options++ = '\0';203}204205/*206* If we have 7 arguments, print the file named on the command-line.207* Otherwise, send stdin instead...208*/209210if (argc == 6)211{212print_fd = 0;213copies = 1;214}215else216{217/*218* Try to open the print file...219*/220221if ((print_fd = open(argv[6], O_RDONLY)) < 0)222{223_cupsLangPrintError("ERROR", _("Unable to open print file"));224return (CUPS_BACKEND_FAILED);225}226227copies = atoi(argv[4]);228}229230/*231* Finally, send the print file...232*/233234status = print_device(uri, hostname, resource, options, print_fd, copies,235argc, argv);236237/*238* Close the input file and return...239*/240241if (print_fd != 0)242close(print_fd);243244return (status);245}246247248