xref: /aosp_15_r20/external/libcups/backend/usb.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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