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