1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * USB printer backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2012 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
16*5e7646d2SAndroid Build Coastguard Worker /* A header order dependency requires this be first */
17*5e7646d2SAndroid Build Coastguard Worker # include <ApplicationServices/ApplicationServices.h>
18*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
19*5e7646d2SAndroid Build Coastguard Worker
20*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
21*5e7646d2SAndroid Build Coastguard Worker
22*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
23*5e7646d2SAndroid Build Coastguard Worker # include <io.h>
24*5e7646d2SAndroid Build Coastguard Worker #else
25*5e7646d2SAndroid Build Coastguard Worker # include <unistd.h>
26*5e7646d2SAndroid Build Coastguard Worker # include <fcntl.h>
27*5e7646d2SAndroid Build Coastguard Worker # include <termios.h>
28*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
29*5e7646d2SAndroid Build Coastguard Worker
30*5e7646d2SAndroid Build Coastguard Worker
31*5e7646d2SAndroid Build Coastguard Worker /*
32*5e7646d2SAndroid Build Coastguard Worker * Local functions...
33*5e7646d2SAndroid Build Coastguard Worker */
34*5e7646d2SAndroid Build Coastguard Worker
35*5e7646d2SAndroid Build Coastguard Worker void list_devices(void);
36*5e7646d2SAndroid Build Coastguard Worker int print_device(const char *uri, const char *hostname,
37*5e7646d2SAndroid Build Coastguard Worker const char *resource, char *options,
38*5e7646d2SAndroid Build Coastguard Worker int print_fd, int copies, int argc, char *argv[]);
39*5e7646d2SAndroid Build Coastguard Worker
40*5e7646d2SAndroid Build Coastguard Worker
41*5e7646d2SAndroid Build Coastguard Worker /*
42*5e7646d2SAndroid Build Coastguard Worker * Include the vendor-specific USB implementation...
43*5e7646d2SAndroid Build Coastguard Worker */
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBUSB
46*5e7646d2SAndroid Build Coastguard Worker # include "usb-libusb.c"
47*5e7646d2SAndroid Build Coastguard Worker #elif defined(__APPLE__)
48*5e7646d2SAndroid Build Coastguard Worker # include "usb-darwin.c"
49*5e7646d2SAndroid Build Coastguard Worker #elif defined(__linux) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
50*5e7646d2SAndroid Build Coastguard Worker # include "usb-unix.c"
51*5e7646d2SAndroid Build Coastguard Worker #else
52*5e7646d2SAndroid Build Coastguard Worker /*
53*5e7646d2SAndroid Build Coastguard Worker * Use dummy functions that do nothing on unsupported platforms...
54*5e7646d2SAndroid Build Coastguard Worker * These can be used as templates for implementing USB printing on new
55*5e7646d2SAndroid Build Coastguard Worker * platforms...
56*5e7646d2SAndroid Build Coastguard Worker */
57*5e7646d2SAndroid Build Coastguard Worker
58*5e7646d2SAndroid Build Coastguard Worker /*
59*5e7646d2SAndroid Build Coastguard Worker * 'list_devices()' - List all available USB devices to stdout.
60*5e7646d2SAndroid Build Coastguard Worker */
61*5e7646d2SAndroid Build Coastguard Worker
62*5e7646d2SAndroid Build Coastguard Worker void
list_devices(void)63*5e7646d2SAndroid Build Coastguard Worker list_devices(void)
64*5e7646d2SAndroid Build Coastguard Worker {
65*5e7646d2SAndroid Build Coastguard Worker /*
66*5e7646d2SAndroid Build Coastguard Worker * Don't have any devices to list... Use output of the form:
67*5e7646d2SAndroid Build Coastguard Worker *
68*5e7646d2SAndroid Build Coastguard Worker * direct usb:/make/model?serial=foo "Make Model" "USB Printer"
69*5e7646d2SAndroid Build Coastguard Worker *
70*5e7646d2SAndroid Build Coastguard Worker * Note that "Hewlett Packard" or any other variation MUST be mapped to
71*5e7646d2SAndroid Build Coastguard Worker * "HP" for compatibility with the PPD and ICC specs.
72*5e7646d2SAndroid Build Coastguard Worker */
73*5e7646d2SAndroid Build Coastguard Worker }
74*5e7646d2SAndroid Build Coastguard Worker
75*5e7646d2SAndroid Build Coastguard Worker
76*5e7646d2SAndroid Build Coastguard Worker /*
77*5e7646d2SAndroid Build Coastguard Worker * 'print_device()' - Print a file to a USB device.
78*5e7646d2SAndroid Build Coastguard Worker */
79*5e7646d2SAndroid Build Coastguard Worker
80*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit status */
print_device(const char * uri,const char * hostname,const char * resource,char * options,int print_fd,int copies,int argc,char * argv[])81*5e7646d2SAndroid Build Coastguard Worker print_device(const char *uri, /* I - Device URI */
82*5e7646d2SAndroid Build Coastguard Worker const char *hostname, /* I - Hostname/manufacturer */
83*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource/modelname */
84*5e7646d2SAndroid Build Coastguard Worker char *options, /* I - Device options/serial number */
85*5e7646d2SAndroid Build Coastguard Worker int print_fd, /* I - File descriptor to print */
86*5e7646d2SAndroid Build Coastguard Worker int copies, /* I - Copies to print */
87*5e7646d2SAndroid Build Coastguard Worker int argc, /* I - Number of command-line arguments (6 or 7) */
88*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
89*5e7646d2SAndroid Build Coastguard Worker {
90*5e7646d2SAndroid Build Coastguard Worker /*
91*5e7646d2SAndroid Build Coastguard Worker * Can't print, so just reference the arguments to eliminate compiler
92*5e7646d2SAndroid Build Coastguard Worker * warnings and return and exit status of 1. Normally you would use the
93*5e7646d2SAndroid Build Coastguard Worker * arguments to send a file to the printer and return 0 if everything
94*5e7646d2SAndroid Build Coastguard Worker * worked OK and non-zero if there was an error.
95*5e7646d2SAndroid Build Coastguard Worker */
96*5e7646d2SAndroid Build Coastguard Worker
97*5e7646d2SAndroid Build Coastguard Worker (void)uri;
98*5e7646d2SAndroid Build Coastguard Worker (void)hostname;
99*5e7646d2SAndroid Build Coastguard Worker (void)resource;
100*5e7646d2SAndroid Build Coastguard Worker (void)options;
101*5e7646d2SAndroid Build Coastguard Worker (void)print_fd;
102*5e7646d2SAndroid Build Coastguard Worker (void)copies;
103*5e7646d2SAndroid Build Coastguard Worker (void)argc;
104*5e7646d2SAndroid Build Coastguard Worker (void)argv;
105*5e7646d2SAndroid Build Coastguard Worker
106*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
107*5e7646d2SAndroid Build Coastguard Worker }
108*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBUSB */
109*5e7646d2SAndroid Build Coastguard Worker
110*5e7646d2SAndroid Build Coastguard Worker
111*5e7646d2SAndroid Build Coastguard Worker /*
112*5e7646d2SAndroid Build Coastguard Worker * 'main()' - Send a file to the specified USB port.
113*5e7646d2SAndroid Build Coastguard Worker *
114*5e7646d2SAndroid Build Coastguard Worker * Usage:
115*5e7646d2SAndroid Build Coastguard Worker *
116*5e7646d2SAndroid Build Coastguard Worker * printer-uri job-id user title copies options [file]
117*5e7646d2SAndroid Build Coastguard Worker */
118*5e7646d2SAndroid Build Coastguard Worker
119*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit status */
main(int argc,char * argv[])120*5e7646d2SAndroid Build Coastguard Worker main(int argc, /* I - Number of command-line arguments (6 or 7) */
121*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
122*5e7646d2SAndroid Build Coastguard Worker {
123*5e7646d2SAndroid Build Coastguard Worker int print_fd; /* Print file */
124*5e7646d2SAndroid Build Coastguard Worker int copies; /* Number of copies to print */
125*5e7646d2SAndroid Build Coastguard Worker int status; /* Exit status */
126*5e7646d2SAndroid Build Coastguard Worker int port; /* Port number (not used) */
127*5e7646d2SAndroid Build Coastguard Worker const char *uri; /* Device URI */
128*5e7646d2SAndroid Build Coastguard Worker char method[255], /* Method in URI */
129*5e7646d2SAndroid Build Coastguard Worker hostname[1024], /* Hostname */
130*5e7646d2SAndroid Build Coastguard Worker username[255], /* Username info (not used) */
131*5e7646d2SAndroid Build Coastguard Worker resource[1024], /* Resource info (device and options) */
132*5e7646d2SAndroid Build Coastguard Worker *options; /* Pointer to options */
133*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
134*5e7646d2SAndroid Build Coastguard Worker struct sigaction action; /* Actions for POSIX signals */
135*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
136*5e7646d2SAndroid Build Coastguard Worker
137*5e7646d2SAndroid Build Coastguard Worker
138*5e7646d2SAndroid Build Coastguard Worker /*
139*5e7646d2SAndroid Build Coastguard Worker * Make sure status messages are not buffered...
140*5e7646d2SAndroid Build Coastguard Worker */
141*5e7646d2SAndroid Build Coastguard Worker
142*5e7646d2SAndroid Build Coastguard Worker setbuf(stderr, NULL);
143*5e7646d2SAndroid Build Coastguard Worker
144*5e7646d2SAndroid Build Coastguard Worker /*
145*5e7646d2SAndroid Build Coastguard Worker * Ignore SIGPIPE signals...
146*5e7646d2SAndroid Build Coastguard Worker */
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET
149*5e7646d2SAndroid Build Coastguard Worker sigset(SIGPIPE, SIG_IGN);
150*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
151*5e7646d2SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
152*5e7646d2SAndroid Build Coastguard Worker action.sa_handler = SIG_IGN;
153*5e7646d2SAndroid Build Coastguard Worker sigaction(SIGPIPE, &action, NULL);
154*5e7646d2SAndroid Build Coastguard Worker #else
155*5e7646d2SAndroid Build Coastguard Worker signal(SIGPIPE, SIG_IGN);
156*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
157*5e7646d2SAndroid Build Coastguard Worker
158*5e7646d2SAndroid Build Coastguard Worker /*
159*5e7646d2SAndroid Build Coastguard Worker * Check command-line...
160*5e7646d2SAndroid Build Coastguard Worker */
161*5e7646d2SAndroid Build Coastguard Worker
162*5e7646d2SAndroid Build Coastguard Worker if (argc == 1)
163*5e7646d2SAndroid Build Coastguard Worker {
164*5e7646d2SAndroid Build Coastguard Worker list_devices();
165*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
166*5e7646d2SAndroid Build Coastguard Worker }
167*5e7646d2SAndroid Build Coastguard Worker else if (argc < 6 || argc > 7)
168*5e7646d2SAndroid Build Coastguard Worker {
169*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
170*5e7646d2SAndroid Build Coastguard Worker _("Usage: %s job-id user title copies options [file]"),
171*5e7646d2SAndroid Build Coastguard Worker argv[0]);
172*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
173*5e7646d2SAndroid Build Coastguard Worker }
174*5e7646d2SAndroid Build Coastguard Worker
175*5e7646d2SAndroid Build Coastguard Worker /*
176*5e7646d2SAndroid Build Coastguard Worker * Extract the device name and options from the URI...
177*5e7646d2SAndroid Build Coastguard Worker */
178*5e7646d2SAndroid Build Coastguard Worker
179*5e7646d2SAndroid Build Coastguard Worker uri = cupsBackendDeviceURI(argv);
180*5e7646d2SAndroid Build Coastguard Worker
181*5e7646d2SAndroid Build Coastguard Worker if (httpSeparateURI(HTTP_URI_CODING_ALL, uri,
182*5e7646d2SAndroid Build Coastguard Worker method, sizeof(method), username, sizeof(username),
183*5e7646d2SAndroid Build Coastguard Worker hostname, sizeof(hostname), &port,
184*5e7646d2SAndroid Build Coastguard Worker resource, sizeof(resource)) < HTTP_URI_OK)
185*5e7646d2SAndroid Build Coastguard Worker {
186*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
187*5e7646d2SAndroid Build Coastguard Worker _("No device URI found in argv[0] or in DEVICE_URI "
188*5e7646d2SAndroid Build Coastguard Worker "environment variable."));
189*5e7646d2SAndroid Build Coastguard Worker return (1);
190*5e7646d2SAndroid Build Coastguard Worker }
191*5e7646d2SAndroid Build Coastguard Worker
192*5e7646d2SAndroid Build Coastguard Worker /*
193*5e7646d2SAndroid Build Coastguard Worker * See if there are any options...
194*5e7646d2SAndroid Build Coastguard Worker */
195*5e7646d2SAndroid Build Coastguard Worker
196*5e7646d2SAndroid Build Coastguard Worker if ((options = strchr(resource, '?')) != NULL)
197*5e7646d2SAndroid Build Coastguard Worker {
198*5e7646d2SAndroid Build Coastguard Worker /*
199*5e7646d2SAndroid Build Coastguard Worker * Yup, terminate the device name string and move to the first
200*5e7646d2SAndroid Build Coastguard Worker * character of the options...
201*5e7646d2SAndroid Build Coastguard Worker */
202*5e7646d2SAndroid Build Coastguard Worker
203*5e7646d2SAndroid Build Coastguard Worker *options++ = '\0';
204*5e7646d2SAndroid Build Coastguard Worker }
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker /*
207*5e7646d2SAndroid Build Coastguard Worker * If we have 7 arguments, print the file named on the command-line.
208*5e7646d2SAndroid Build Coastguard Worker * Otherwise, send stdin instead...
209*5e7646d2SAndroid Build Coastguard Worker */
210*5e7646d2SAndroid Build Coastguard Worker
211*5e7646d2SAndroid Build Coastguard Worker if (argc == 6)
212*5e7646d2SAndroid Build Coastguard Worker {
213*5e7646d2SAndroid Build Coastguard Worker print_fd = 0;
214*5e7646d2SAndroid Build Coastguard Worker copies = 1;
215*5e7646d2SAndroid Build Coastguard Worker }
216*5e7646d2SAndroid Build Coastguard Worker else
217*5e7646d2SAndroid Build Coastguard Worker {
218*5e7646d2SAndroid Build Coastguard Worker /*
219*5e7646d2SAndroid Build Coastguard Worker * Try to open the print file...
220*5e7646d2SAndroid Build Coastguard Worker */
221*5e7646d2SAndroid Build Coastguard Worker
222*5e7646d2SAndroid Build Coastguard Worker if ((print_fd = open(argv[6], O_RDONLY)) < 0)
223*5e7646d2SAndroid Build Coastguard Worker {
224*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintError("ERROR", _("Unable to open print file"));
225*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
226*5e7646d2SAndroid Build Coastguard Worker }
227*5e7646d2SAndroid Build Coastguard Worker
228*5e7646d2SAndroid Build Coastguard Worker copies = atoi(argv[4]);
229*5e7646d2SAndroid Build Coastguard Worker }
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker /*
232*5e7646d2SAndroid Build Coastguard Worker * Finally, send the print file...
233*5e7646d2SAndroid Build Coastguard Worker */
234*5e7646d2SAndroid Build Coastguard Worker
235*5e7646d2SAndroid Build Coastguard Worker status = print_device(uri, hostname, resource, options, print_fd, copies,
236*5e7646d2SAndroid Build Coastguard Worker argc, argv);
237*5e7646d2SAndroid Build Coastguard Worker
238*5e7646d2SAndroid Build Coastguard Worker /*
239*5e7646d2SAndroid Build Coastguard Worker * Close the input file and return...
240*5e7646d2SAndroid Build Coastguard Worker */
241*5e7646d2SAndroid Build Coastguard Worker
242*5e7646d2SAndroid Build Coastguard Worker if (print_fd != 0)
243*5e7646d2SAndroid Build Coastguard Worker close(print_fd);
244*5e7646d2SAndroid Build Coastguard Worker
245*5e7646d2SAndroid Build Coastguard Worker return (status);
246*5e7646d2SAndroid Build Coastguard Worker }
247