1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * USB port backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * This file is included from "usb.c" when compiled on UNIX/Linux.
5*5e7646d2SAndroid Build Coastguard Worker *
6*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2013 by Apple Inc.
7*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
8*5e7646d2SAndroid Build Coastguard Worker *
9*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
10*5e7646d2SAndroid Build Coastguard Worker * information.
11*5e7646d2SAndroid Build Coastguard Worker */
12*5e7646d2SAndroid Build Coastguard Worker
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
15*5e7646d2SAndroid Build Coastguard Worker */
16*5e7646d2SAndroid Build Coastguard Worker
17*5e7646d2SAndroid Build Coastguard Worker #include <sys/select.h>
18*5e7646d2SAndroid Build Coastguard Worker
19*5e7646d2SAndroid Build Coastguard Worker
20*5e7646d2SAndroid Build Coastguard Worker /*
21*5e7646d2SAndroid Build Coastguard Worker * Local functions...
22*5e7646d2SAndroid Build Coastguard Worker */
23*5e7646d2SAndroid Build Coastguard Worker
24*5e7646d2SAndroid Build Coastguard Worker static int open_device(const char *uri, int *use_bc);
25*5e7646d2SAndroid Build Coastguard Worker static int side_cb(int print_fd, int device_fd, int snmp_fd,
26*5e7646d2SAndroid Build Coastguard Worker http_addr_t *addr, int use_bc);
27*5e7646d2SAndroid Build Coastguard Worker
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker /*
30*5e7646d2SAndroid Build Coastguard Worker * 'print_device()' - Print a file to a USB device.
31*5e7646d2SAndroid Build Coastguard Worker */
32*5e7646d2SAndroid Build Coastguard Worker
33*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[])34*5e7646d2SAndroid Build Coastguard Worker print_device(const char *uri, /* I - Device URI */
35*5e7646d2SAndroid Build Coastguard Worker const char *hostname, /* I - Hostname/manufacturer */
36*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource/modelname */
37*5e7646d2SAndroid Build Coastguard Worker char *options, /* I - Device options/serial number */
38*5e7646d2SAndroid Build Coastguard Worker int print_fd, /* I - File descriptor to print */
39*5e7646d2SAndroid Build Coastguard Worker int copies, /* I - Copies to print */
40*5e7646d2SAndroid Build Coastguard Worker int argc, /* I - Number of command-line arguments (6 or 7) */
41*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
42*5e7646d2SAndroid Build Coastguard Worker {
43*5e7646d2SAndroid Build Coastguard Worker int use_bc; /* Use backchannel path? */
44*5e7646d2SAndroid Build Coastguard Worker int device_fd; /* USB device */
45*5e7646d2SAndroid Build Coastguard Worker ssize_t tbytes; /* Total number of bytes written */
46*5e7646d2SAndroid Build Coastguard Worker struct termios opts; /* Parallel port options */
47*5e7646d2SAndroid Build Coastguard Worker
48*5e7646d2SAndroid Build Coastguard Worker
49*5e7646d2SAndroid Build Coastguard Worker (void)argc;
50*5e7646d2SAndroid Build Coastguard Worker (void)argv;
51*5e7646d2SAndroid Build Coastguard Worker
52*5e7646d2SAndroid Build Coastguard Worker /*
53*5e7646d2SAndroid Build Coastguard Worker * Open the USB port device...
54*5e7646d2SAndroid Build Coastguard Worker */
55*5e7646d2SAndroid Build Coastguard Worker
56*5e7646d2SAndroid Build Coastguard Worker fputs("STATE: +connecting-to-device\n", stderr);
57*5e7646d2SAndroid Build Coastguard Worker
58*5e7646d2SAndroid Build Coastguard Worker do
59*5e7646d2SAndroid Build Coastguard Worker {
60*5e7646d2SAndroid Build Coastguard Worker #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
61*5e7646d2SAndroid Build Coastguard Worker /*
62*5e7646d2SAndroid Build Coastguard Worker * *BSD's ulpt driver currently does not support the
63*5e7646d2SAndroid Build Coastguard Worker * back-channel, incorrectly returns data ready on a select(),
64*5e7646d2SAndroid Build Coastguard Worker * and locks up on read()...
65*5e7646d2SAndroid Build Coastguard Worker */
66*5e7646d2SAndroid Build Coastguard Worker
67*5e7646d2SAndroid Build Coastguard Worker use_bc = 0;
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker #elif defined(__sun)
70*5e7646d2SAndroid Build Coastguard Worker /*
71*5e7646d2SAndroid Build Coastguard Worker * CUPS STR #3028: Solaris' usbprn driver apparently does not support
72*5e7646d2SAndroid Build Coastguard Worker * select() or poll(), so we can't support backchannel...
73*5e7646d2SAndroid Build Coastguard Worker */
74*5e7646d2SAndroid Build Coastguard Worker
75*5e7646d2SAndroid Build Coastguard Worker use_bc = 0;
76*5e7646d2SAndroid Build Coastguard Worker
77*5e7646d2SAndroid Build Coastguard Worker #else
78*5e7646d2SAndroid Build Coastguard Worker /*
79*5e7646d2SAndroid Build Coastguard Worker * Disable backchannel data when printing to Brother, Canon, or
80*5e7646d2SAndroid Build Coastguard Worker * Minolta USB printers - apparently these printers will return
81*5e7646d2SAndroid Build Coastguard Worker * the IEEE-1284 device ID over and over and over when they get
82*5e7646d2SAndroid Build Coastguard Worker * a read request...
83*5e7646d2SAndroid Build Coastguard Worker */
84*5e7646d2SAndroid Build Coastguard Worker
85*5e7646d2SAndroid Build Coastguard Worker use_bc = _cups_strcasecmp(hostname, "Brother") &&
86*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp(hostname, "Canon") &&
87*5e7646d2SAndroid Build Coastguard Worker _cups_strncasecmp(hostname, "Konica", 6) &&
88*5e7646d2SAndroid Build Coastguard Worker _cups_strncasecmp(hostname, "Minolta", 7);
89*5e7646d2SAndroid Build Coastguard Worker #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */
90*5e7646d2SAndroid Build Coastguard Worker
91*5e7646d2SAndroid Build Coastguard Worker if ((device_fd = open_device(uri, &use_bc)) == -1)
92*5e7646d2SAndroid Build Coastguard Worker {
93*5e7646d2SAndroid Build Coastguard Worker if (getenv("CLASS") != NULL)
94*5e7646d2SAndroid Build Coastguard Worker {
95*5e7646d2SAndroid Build Coastguard Worker /*
96*5e7646d2SAndroid Build Coastguard Worker * If the CLASS environment variable is set, the job was submitted
97*5e7646d2SAndroid Build Coastguard Worker * to a class and not to a specific queue. In this case, we want
98*5e7646d2SAndroid Build Coastguard Worker * to abort immediately so that the job can be requeued on the next
99*5e7646d2SAndroid Build Coastguard Worker * available printer in the class.
100*5e7646d2SAndroid Build Coastguard Worker */
101*5e7646d2SAndroid Build Coastguard Worker
102*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO",
103*5e7646d2SAndroid Build Coastguard Worker _("Unable to contact printer, queuing on next "
104*5e7646d2SAndroid Build Coastguard Worker "printer in class."));
105*5e7646d2SAndroid Build Coastguard Worker
106*5e7646d2SAndroid Build Coastguard Worker /*
107*5e7646d2SAndroid Build Coastguard Worker * Sleep 5 seconds to keep the job from requeuing too rapidly...
108*5e7646d2SAndroid Build Coastguard Worker */
109*5e7646d2SAndroid Build Coastguard Worker
110*5e7646d2SAndroid Build Coastguard Worker sleep(5);
111*5e7646d2SAndroid Build Coastguard Worker
112*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
113*5e7646d2SAndroid Build Coastguard Worker }
114*5e7646d2SAndroid Build Coastguard Worker
115*5e7646d2SAndroid Build Coastguard Worker if (errno == EBUSY)
116*5e7646d2SAndroid Build Coastguard Worker {
117*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
118*5e7646d2SAndroid Build Coastguard Worker sleep(10);
119*5e7646d2SAndroid Build Coastguard Worker }
120*5e7646d2SAndroid Build Coastguard Worker else if (errno == ENXIO || errno == EIO || errno == ENOENT ||
121*5e7646d2SAndroid Build Coastguard Worker errno == ENODEV)
122*5e7646d2SAndroid Build Coastguard Worker {
123*5e7646d2SAndroid Build Coastguard Worker sleep(30);
124*5e7646d2SAndroid Build Coastguard Worker }
125*5e7646d2SAndroid Build Coastguard Worker else
126*5e7646d2SAndroid Build Coastguard Worker {
127*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintError("ERROR", _("Unable to open device file"));
128*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
129*5e7646d2SAndroid Build Coastguard Worker }
130*5e7646d2SAndroid Build Coastguard Worker }
131*5e7646d2SAndroid Build Coastguard Worker }
132*5e7646d2SAndroid Build Coastguard Worker while (device_fd < 0);
133*5e7646d2SAndroid Build Coastguard Worker
134*5e7646d2SAndroid Build Coastguard Worker fputs("STATE: -connecting-to-device\n", stderr);
135*5e7646d2SAndroid Build Coastguard Worker
136*5e7646d2SAndroid Build Coastguard Worker /*
137*5e7646d2SAndroid Build Coastguard Worker * Set any options provided...
138*5e7646d2SAndroid Build Coastguard Worker */
139*5e7646d2SAndroid Build Coastguard Worker
140*5e7646d2SAndroid Build Coastguard Worker tcgetattr(device_fd, &opts);
141*5e7646d2SAndroid Build Coastguard Worker
142*5e7646d2SAndroid Build Coastguard Worker opts.c_lflag &= ~(unsigned)(ICANON | ECHO | ISIG); /* Raw mode */
143*5e7646d2SAndroid Build Coastguard Worker
144*5e7646d2SAndroid Build Coastguard Worker /**** No options supported yet ****/
145*5e7646d2SAndroid Build Coastguard Worker
146*5e7646d2SAndroid Build Coastguard Worker tcsetattr(device_fd, TCSANOW, &opts);
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker /*
149*5e7646d2SAndroid Build Coastguard Worker * Finally, send the print file...
150*5e7646d2SAndroid Build Coastguard Worker */
151*5e7646d2SAndroid Build Coastguard Worker
152*5e7646d2SAndroid Build Coastguard Worker tbytes = 0;
153*5e7646d2SAndroid Build Coastguard Worker
154*5e7646d2SAndroid Build Coastguard Worker while (copies > 0 && tbytes >= 0)
155*5e7646d2SAndroid Build Coastguard Worker {
156*5e7646d2SAndroid Build Coastguard Worker copies --;
157*5e7646d2SAndroid Build Coastguard Worker
158*5e7646d2SAndroid Build Coastguard Worker if (print_fd != 0)
159*5e7646d2SAndroid Build Coastguard Worker {
160*5e7646d2SAndroid Build Coastguard Worker fputs("PAGE: 1 1\n", stderr);
161*5e7646d2SAndroid Build Coastguard Worker lseek(print_fd, 0, SEEK_SET);
162*5e7646d2SAndroid Build Coastguard Worker }
163*5e7646d2SAndroid Build Coastguard Worker
164*5e7646d2SAndroid Build Coastguard Worker #ifdef __sun
165*5e7646d2SAndroid Build Coastguard Worker /*
166*5e7646d2SAndroid Build Coastguard Worker * CUPS STR #3028: Solaris' usbprn driver apparently does not support
167*5e7646d2SAndroid Build Coastguard Worker * select() or poll(), so we can't support the sidechannel either...
168*5e7646d2SAndroid Build Coastguard Worker */
169*5e7646d2SAndroid Build Coastguard Worker
170*5e7646d2SAndroid Build Coastguard Worker tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, NULL);
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker #else
173*5e7646d2SAndroid Build Coastguard Worker tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, side_cb);
174*5e7646d2SAndroid Build Coastguard Worker #endif /* __sun */
175*5e7646d2SAndroid Build Coastguard Worker
176*5e7646d2SAndroid Build Coastguard Worker if (print_fd != 0 && tbytes >= 0)
177*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Print file sent."));
178*5e7646d2SAndroid Build Coastguard Worker }
179*5e7646d2SAndroid Build Coastguard Worker
180*5e7646d2SAndroid Build Coastguard Worker /*
181*5e7646d2SAndroid Build Coastguard Worker * Close the USB port and return...
182*5e7646d2SAndroid Build Coastguard Worker */
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker close(device_fd);
185*5e7646d2SAndroid Build Coastguard Worker
186*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
187*5e7646d2SAndroid Build Coastguard Worker }
188*5e7646d2SAndroid Build Coastguard Worker
189*5e7646d2SAndroid Build Coastguard Worker
190*5e7646d2SAndroid Build Coastguard Worker /*
191*5e7646d2SAndroid Build Coastguard Worker * 'list_devices()' - List all USB devices.
192*5e7646d2SAndroid Build Coastguard Worker */
193*5e7646d2SAndroid Build Coastguard Worker
194*5e7646d2SAndroid Build Coastguard Worker void
list_devices(void)195*5e7646d2SAndroid Build Coastguard Worker list_devices(void)
196*5e7646d2SAndroid Build Coastguard Worker {
197*5e7646d2SAndroid Build Coastguard Worker #ifdef __linux
198*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
199*5e7646d2SAndroid Build Coastguard Worker int fd; /* File descriptor */
200*5e7646d2SAndroid Build Coastguard Worker char device[255], /* Device filename */
201*5e7646d2SAndroid Build Coastguard Worker device_id[1024], /* Device ID string */
202*5e7646d2SAndroid Build Coastguard Worker device_uri[1024], /* Device URI string */
203*5e7646d2SAndroid Build Coastguard Worker make_model[1024]; /* Make and model */
204*5e7646d2SAndroid Build Coastguard Worker
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker /*
207*5e7646d2SAndroid Build Coastguard Worker * Try to open each USB device...
208*5e7646d2SAndroid Build Coastguard Worker */
209*5e7646d2SAndroid Build Coastguard Worker
210*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < 16; i ++)
211*5e7646d2SAndroid Build Coastguard Worker {
212*5e7646d2SAndroid Build Coastguard Worker /*
213*5e7646d2SAndroid Build Coastguard Worker * Linux has a long history of changing the standard filenames used
214*5e7646d2SAndroid Build Coastguard Worker * for USB printer devices. We get the honor of trying them all...
215*5e7646d2SAndroid Build Coastguard Worker */
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usblp%d", i);
218*5e7646d2SAndroid Build Coastguard Worker
219*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_RDWR | O_EXCL)) < 0)
220*5e7646d2SAndroid Build Coastguard Worker {
221*5e7646d2SAndroid Build Coastguard Worker if (errno != ENOENT)
222*5e7646d2SAndroid Build Coastguard Worker continue;
223*5e7646d2SAndroid Build Coastguard Worker
224*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usb/lp%d", i);
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_RDWR | O_EXCL)) < 0)
227*5e7646d2SAndroid Build Coastguard Worker {
228*5e7646d2SAndroid Build Coastguard Worker if (errno != ENOENT)
229*5e7646d2SAndroid Build Coastguard Worker continue;
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usb/usblp%d", i);
232*5e7646d2SAndroid Build Coastguard Worker
233*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_RDWR | O_EXCL)) < 0)
234*5e7646d2SAndroid Build Coastguard Worker continue;
235*5e7646d2SAndroid Build Coastguard Worker }
236*5e7646d2SAndroid Build Coastguard Worker }
237*5e7646d2SAndroid Build Coastguard Worker
238*5e7646d2SAndroid Build Coastguard Worker if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
239*5e7646d2SAndroid Build Coastguard Worker make_model, sizeof(make_model),
240*5e7646d2SAndroid Build Coastguard Worker "usb", device_uri, sizeof(device_uri)))
241*5e7646d2SAndroid Build Coastguard Worker cupsBackendReport("direct", device_uri, make_model, make_model,
242*5e7646d2SAndroid Build Coastguard Worker device_id, NULL);
243*5e7646d2SAndroid Build Coastguard Worker
244*5e7646d2SAndroid Build Coastguard Worker close(fd);
245*5e7646d2SAndroid Build Coastguard Worker }
246*5e7646d2SAndroid Build Coastguard Worker #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
247*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
248*5e7646d2SAndroid Build Coastguard Worker int fd; /* File descriptor */
249*5e7646d2SAndroid Build Coastguard Worker char device[255], /* Device filename */
250*5e7646d2SAndroid Build Coastguard Worker device_id[1024], /* Device ID string */
251*5e7646d2SAndroid Build Coastguard Worker device_uri[1024], /* Device URI string */
252*5e7646d2SAndroid Build Coastguard Worker make_model[1024]; /* Make and model */
253*5e7646d2SAndroid Build Coastguard Worker
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker /*
256*5e7646d2SAndroid Build Coastguard Worker * Open each USB device...
257*5e7646d2SAndroid Build Coastguard Worker */
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < 8; i ++)
260*5e7646d2SAndroid Build Coastguard Worker {
261*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usb/printer%d", i);
262*5e7646d2SAndroid Build Coastguard Worker
263*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_WRONLY | O_EXCL)) >= 0)
264*5e7646d2SAndroid Build Coastguard Worker {
265*5e7646d2SAndroid Build Coastguard Worker if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
266*5e7646d2SAndroid Build Coastguard Worker make_model, sizeof(make_model),
267*5e7646d2SAndroid Build Coastguard Worker "usb", device_uri, sizeof(device_uri)))
268*5e7646d2SAndroid Build Coastguard Worker cupsBackendReport("direct", device_uri, make_model, make_model,
269*5e7646d2SAndroid Build Coastguard Worker device_id, NULL);
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker close(fd);
272*5e7646d2SAndroid Build Coastguard Worker }
273*5e7646d2SAndroid Build Coastguard Worker }
274*5e7646d2SAndroid Build Coastguard Worker #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
275*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
276*5e7646d2SAndroid Build Coastguard Worker char device[255]; /* Device filename */
277*5e7646d2SAndroid Build Coastguard Worker
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < 8; i ++)
280*5e7646d2SAndroid Build Coastguard Worker {
281*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/ulpt%d", i);
282*5e7646d2SAndroid Build Coastguard Worker if (!access(device, 0))
283*5e7646d2SAndroid Build Coastguard Worker printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
284*5e7646d2SAndroid Build Coastguard Worker
285*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/unlpt%d", i);
286*5e7646d2SAndroid Build Coastguard Worker if (!access(device, 0))
287*5e7646d2SAndroid Build Coastguard Worker printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1);
288*5e7646d2SAndroid Build Coastguard Worker }
289*5e7646d2SAndroid Build Coastguard Worker #endif
290*5e7646d2SAndroid Build Coastguard Worker }
291*5e7646d2SAndroid Build Coastguard Worker
292*5e7646d2SAndroid Build Coastguard Worker
293*5e7646d2SAndroid Build Coastguard Worker /*
294*5e7646d2SAndroid Build Coastguard Worker * 'open_device()' - Open a USB device...
295*5e7646d2SAndroid Build Coastguard Worker */
296*5e7646d2SAndroid Build Coastguard Worker
297*5e7646d2SAndroid Build Coastguard Worker static int /* O - File descriptor or -1 on error */
open_device(const char * uri,int * use_bc)298*5e7646d2SAndroid Build Coastguard Worker open_device(const char *uri, /* I - Device URI */
299*5e7646d2SAndroid Build Coastguard Worker int *use_bc) /* O - Set to 0 for unidirectional */
300*5e7646d2SAndroid Build Coastguard Worker {
301*5e7646d2SAndroid Build Coastguard Worker int fd; /* File descriptor */
302*5e7646d2SAndroid Build Coastguard Worker
303*5e7646d2SAndroid Build Coastguard Worker
304*5e7646d2SAndroid Build Coastguard Worker /*
305*5e7646d2SAndroid Build Coastguard Worker * The generic implementation just treats the URI as a device filename...
306*5e7646d2SAndroid Build Coastguard Worker * Specific operating systems may also support using the device serial
307*5e7646d2SAndroid Build Coastguard Worker * number and/or make/model.
308*5e7646d2SAndroid Build Coastguard Worker */
309*5e7646d2SAndroid Build Coastguard Worker
310*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(uri, "usb:/dev/", 9))
311*5e7646d2SAndroid Build Coastguard Worker #ifdef __linux
312*5e7646d2SAndroid Build Coastguard Worker {
313*5e7646d2SAndroid Build Coastguard Worker /*
314*5e7646d2SAndroid Build Coastguard Worker * Do not allow direct devices anymore...
315*5e7646d2SAndroid Build Coastguard Worker */
316*5e7646d2SAndroid Build Coastguard Worker
317*5e7646d2SAndroid Build Coastguard Worker errno = ENODEV;
318*5e7646d2SAndroid Build Coastguard Worker return (-1);
319*5e7646d2SAndroid Build Coastguard Worker }
320*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(uri, "usb://", 6))
321*5e7646d2SAndroid Build Coastguard Worker {
322*5e7646d2SAndroid Build Coastguard Worker /*
323*5e7646d2SAndroid Build Coastguard Worker * For Linux, try looking up the device serial number or model...
324*5e7646d2SAndroid Build Coastguard Worker */
325*5e7646d2SAndroid Build Coastguard Worker
326*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
327*5e7646d2SAndroid Build Coastguard Worker int busy; /* Are any ports busy? */
328*5e7646d2SAndroid Build Coastguard Worker char device[255], /* Device filename */
329*5e7646d2SAndroid Build Coastguard Worker device_id[1024], /* Device ID string */
330*5e7646d2SAndroid Build Coastguard Worker make_model[1024], /* Make and model */
331*5e7646d2SAndroid Build Coastguard Worker device_uri[1024]; /* Device URI string */
332*5e7646d2SAndroid Build Coastguard Worker
333*5e7646d2SAndroid Build Coastguard Worker
334*5e7646d2SAndroid Build Coastguard Worker /*
335*5e7646d2SAndroid Build Coastguard Worker * Find the correct USB device...
336*5e7646d2SAndroid Build Coastguard Worker */
337*5e7646d2SAndroid Build Coastguard Worker
338*5e7646d2SAndroid Build Coastguard Worker for (;;)
339*5e7646d2SAndroid Build Coastguard Worker {
340*5e7646d2SAndroid Build Coastguard Worker for (busy = 0, i = 0; i < 16; i ++)
341*5e7646d2SAndroid Build Coastguard Worker {
342*5e7646d2SAndroid Build Coastguard Worker /*
343*5e7646d2SAndroid Build Coastguard Worker * Linux has a long history of changing the standard filenames used
344*5e7646d2SAndroid Build Coastguard Worker * for USB printer devices. We get the honor of trying them all...
345*5e7646d2SAndroid Build Coastguard Worker */
346*5e7646d2SAndroid Build Coastguard Worker
347*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usblp%d", i);
348*5e7646d2SAndroid Build Coastguard Worker
349*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_RDWR | O_EXCL)) < 0 && errno == ENOENT)
350*5e7646d2SAndroid Build Coastguard Worker {
351*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usb/lp%d", i);
352*5e7646d2SAndroid Build Coastguard Worker
353*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_RDWR | O_EXCL)) < 0 && errno == ENOENT)
354*5e7646d2SAndroid Build Coastguard Worker {
355*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usb/usblp%d", i);
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_RDWR | O_EXCL)) < 0 && errno == ENOENT)
358*5e7646d2SAndroid Build Coastguard Worker continue;
359*5e7646d2SAndroid Build Coastguard Worker }
360*5e7646d2SAndroid Build Coastguard Worker }
361*5e7646d2SAndroid Build Coastguard Worker
362*5e7646d2SAndroid Build Coastguard Worker if (fd >= 0)
363*5e7646d2SAndroid Build Coastguard Worker {
364*5e7646d2SAndroid Build Coastguard Worker backendGetDeviceID(fd, device_id, sizeof(device_id),
365*5e7646d2SAndroid Build Coastguard Worker make_model, sizeof(make_model),
366*5e7646d2SAndroid Build Coastguard Worker "usb", device_uri, sizeof(device_uri));
367*5e7646d2SAndroid Build Coastguard Worker }
368*5e7646d2SAndroid Build Coastguard Worker else
369*5e7646d2SAndroid Build Coastguard Worker {
370*5e7646d2SAndroid Build Coastguard Worker /*
371*5e7646d2SAndroid Build Coastguard Worker * If the open failed because it was busy, flag it so we retry
372*5e7646d2SAndroid Build Coastguard Worker * as needed...
373*5e7646d2SAndroid Build Coastguard Worker */
374*5e7646d2SAndroid Build Coastguard Worker
375*5e7646d2SAndroid Build Coastguard Worker if (errno == EBUSY)
376*5e7646d2SAndroid Build Coastguard Worker busy = 1;
377*5e7646d2SAndroid Build Coastguard Worker
378*5e7646d2SAndroid Build Coastguard Worker device_uri[0] = '\0';
379*5e7646d2SAndroid Build Coastguard Worker }
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri, device_uri))
382*5e7646d2SAndroid Build Coastguard Worker {
383*5e7646d2SAndroid Build Coastguard Worker /*
384*5e7646d2SAndroid Build Coastguard Worker * Yes, return this file descriptor...
385*5e7646d2SAndroid Build Coastguard Worker */
386*5e7646d2SAndroid Build Coastguard Worker
387*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n",
388*5e7646d2SAndroid Build Coastguard Worker device);
389*5e7646d2SAndroid Build Coastguard Worker
390*5e7646d2SAndroid Build Coastguard Worker return (fd);
391*5e7646d2SAndroid Build Coastguard Worker }
392*5e7646d2SAndroid Build Coastguard Worker
393*5e7646d2SAndroid Build Coastguard Worker /*
394*5e7646d2SAndroid Build Coastguard Worker * This wasn't the one...
395*5e7646d2SAndroid Build Coastguard Worker */
396*5e7646d2SAndroid Build Coastguard Worker
397*5e7646d2SAndroid Build Coastguard Worker if (fd >= 0)
398*5e7646d2SAndroid Build Coastguard Worker close(fd);
399*5e7646d2SAndroid Build Coastguard Worker }
400*5e7646d2SAndroid Build Coastguard Worker
401*5e7646d2SAndroid Build Coastguard Worker /*
402*5e7646d2SAndroid Build Coastguard Worker * If we get here and at least one of the printer ports showed up
403*5e7646d2SAndroid Build Coastguard Worker * as "busy", then sleep for a bit and retry...
404*5e7646d2SAndroid Build Coastguard Worker */
405*5e7646d2SAndroid Build Coastguard Worker
406*5e7646d2SAndroid Build Coastguard Worker if (busy)
407*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker sleep(5);
410*5e7646d2SAndroid Build Coastguard Worker }
411*5e7646d2SAndroid Build Coastguard Worker }
412*5e7646d2SAndroid Build Coastguard Worker #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
413*5e7646d2SAndroid Build Coastguard Worker {
414*5e7646d2SAndroid Build Coastguard Worker /*
415*5e7646d2SAndroid Build Coastguard Worker * Do not allow direct devices anymore...
416*5e7646d2SAndroid Build Coastguard Worker */
417*5e7646d2SAndroid Build Coastguard Worker
418*5e7646d2SAndroid Build Coastguard Worker errno = ENODEV;
419*5e7646d2SAndroid Build Coastguard Worker return (-1);
420*5e7646d2SAndroid Build Coastguard Worker }
421*5e7646d2SAndroid Build Coastguard Worker else if (!strncmp(uri, "usb://", 6))
422*5e7646d2SAndroid Build Coastguard Worker {
423*5e7646d2SAndroid Build Coastguard Worker /*
424*5e7646d2SAndroid Build Coastguard Worker * For Solaris, try looking up the device serial number or model...
425*5e7646d2SAndroid Build Coastguard Worker */
426*5e7646d2SAndroid Build Coastguard Worker
427*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
428*5e7646d2SAndroid Build Coastguard Worker int busy; /* Are any ports busy? */
429*5e7646d2SAndroid Build Coastguard Worker char device[255], /* Device filename */
430*5e7646d2SAndroid Build Coastguard Worker device_id[1024], /* Device ID string */
431*5e7646d2SAndroid Build Coastguard Worker make_model[1024], /* Make and model */
432*5e7646d2SAndroid Build Coastguard Worker device_uri[1024]; /* Device URI string */
433*5e7646d2SAndroid Build Coastguard Worker
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker /*
436*5e7646d2SAndroid Build Coastguard Worker * Find the correct USB device...
437*5e7646d2SAndroid Build Coastguard Worker */
438*5e7646d2SAndroid Build Coastguard Worker
439*5e7646d2SAndroid Build Coastguard Worker do
440*5e7646d2SAndroid Build Coastguard Worker {
441*5e7646d2SAndroid Build Coastguard Worker for (i = 0, busy = 0; i < 8; i ++)
442*5e7646d2SAndroid Build Coastguard Worker {
443*5e7646d2SAndroid Build Coastguard Worker snprintf(device, sizeof(device), "/dev/usb/printer%d", i);
444*5e7646d2SAndroid Build Coastguard Worker
445*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(device, O_WRONLY | O_EXCL)) >= 0)
446*5e7646d2SAndroid Build Coastguard Worker backendGetDeviceID(fd, device_id, sizeof(device_id),
447*5e7646d2SAndroid Build Coastguard Worker make_model, sizeof(make_model),
448*5e7646d2SAndroid Build Coastguard Worker "usb", device_uri, sizeof(device_uri));
449*5e7646d2SAndroid Build Coastguard Worker else
450*5e7646d2SAndroid Build Coastguard Worker {
451*5e7646d2SAndroid Build Coastguard Worker /*
452*5e7646d2SAndroid Build Coastguard Worker * If the open failed because it was busy, flag it so we retry
453*5e7646d2SAndroid Build Coastguard Worker * as needed...
454*5e7646d2SAndroid Build Coastguard Worker */
455*5e7646d2SAndroid Build Coastguard Worker
456*5e7646d2SAndroid Build Coastguard Worker if (errno == EBUSY)
457*5e7646d2SAndroid Build Coastguard Worker busy = 1;
458*5e7646d2SAndroid Build Coastguard Worker
459*5e7646d2SAndroid Build Coastguard Worker device_uri[0] = '\0';
460*5e7646d2SAndroid Build Coastguard Worker }
461*5e7646d2SAndroid Build Coastguard Worker
462*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(uri, device_uri))
463*5e7646d2SAndroid Build Coastguard Worker {
464*5e7646d2SAndroid Build Coastguard Worker /*
465*5e7646d2SAndroid Build Coastguard Worker * Yes, return this file descriptor...
466*5e7646d2SAndroid Build Coastguard Worker */
467*5e7646d2SAndroid Build Coastguard Worker
468*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Setting use_bc to 0!\n", stderr);
469*5e7646d2SAndroid Build Coastguard Worker
470*5e7646d2SAndroid Build Coastguard Worker *use_bc = 0;
471*5e7646d2SAndroid Build Coastguard Worker
472*5e7646d2SAndroid Build Coastguard Worker return (fd);
473*5e7646d2SAndroid Build Coastguard Worker }
474*5e7646d2SAndroid Build Coastguard Worker
475*5e7646d2SAndroid Build Coastguard Worker /*
476*5e7646d2SAndroid Build Coastguard Worker * This wasn't the one...
477*5e7646d2SAndroid Build Coastguard Worker */
478*5e7646d2SAndroid Build Coastguard Worker
479*5e7646d2SAndroid Build Coastguard Worker if (fd >= 0)
480*5e7646d2SAndroid Build Coastguard Worker close(fd);
481*5e7646d2SAndroid Build Coastguard Worker }
482*5e7646d2SAndroid Build Coastguard Worker
483*5e7646d2SAndroid Build Coastguard Worker /*
484*5e7646d2SAndroid Build Coastguard Worker * If we get here and at least one of the printer ports showed up
485*5e7646d2SAndroid Build Coastguard Worker * as "busy", then sleep for a bit and retry...
486*5e7646d2SAndroid Build Coastguard Worker */
487*5e7646d2SAndroid Build Coastguard Worker
488*5e7646d2SAndroid Build Coastguard Worker if (busy)
489*5e7646d2SAndroid Build Coastguard Worker {
490*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
491*5e7646d2SAndroid Build Coastguard Worker sleep(5);
492*5e7646d2SAndroid Build Coastguard Worker }
493*5e7646d2SAndroid Build Coastguard Worker }
494*5e7646d2SAndroid Build Coastguard Worker while (busy);
495*5e7646d2SAndroid Build Coastguard Worker
496*5e7646d2SAndroid Build Coastguard Worker /*
497*5e7646d2SAndroid Build Coastguard Worker * Couldn't find the printer, return "no such device or address"...
498*5e7646d2SAndroid Build Coastguard Worker */
499*5e7646d2SAndroid Build Coastguard Worker
500*5e7646d2SAndroid Build Coastguard Worker errno = ENODEV;
501*5e7646d2SAndroid Build Coastguard Worker
502*5e7646d2SAndroid Build Coastguard Worker return (-1);
503*5e7646d2SAndroid Build Coastguard Worker }
504*5e7646d2SAndroid Build Coastguard Worker #else
505*5e7646d2SAndroid Build Coastguard Worker {
506*5e7646d2SAndroid Build Coastguard Worker if (*use_bc)
507*5e7646d2SAndroid Build Coastguard Worker fd = open(uri + 4, O_RDWR | O_EXCL);
508*5e7646d2SAndroid Build Coastguard Worker else
509*5e7646d2SAndroid Build Coastguard Worker fd = -1;
510*5e7646d2SAndroid Build Coastguard Worker
511*5e7646d2SAndroid Build Coastguard Worker if (fd < 0)
512*5e7646d2SAndroid Build Coastguard Worker {
513*5e7646d2SAndroid Build Coastguard Worker fd = open(uri + 4, O_WRONLY | O_EXCL);
514*5e7646d2SAndroid Build Coastguard Worker *use_bc = 0;
515*5e7646d2SAndroid Build Coastguard Worker }
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker return (fd);
518*5e7646d2SAndroid Build Coastguard Worker }
519*5e7646d2SAndroid Build Coastguard Worker #endif /* __linux */
520*5e7646d2SAndroid Build Coastguard Worker else
521*5e7646d2SAndroid Build Coastguard Worker {
522*5e7646d2SAndroid Build Coastguard Worker errno = ENODEV;
523*5e7646d2SAndroid Build Coastguard Worker return (-1);
524*5e7646d2SAndroid Build Coastguard Worker }
525*5e7646d2SAndroid Build Coastguard Worker }
526*5e7646d2SAndroid Build Coastguard Worker
527*5e7646d2SAndroid Build Coastguard Worker
528*5e7646d2SAndroid Build Coastguard Worker /*
529*5e7646d2SAndroid Build Coastguard Worker * 'side_cb()' - Handle side-channel requests...
530*5e7646d2SAndroid Build Coastguard Worker */
531*5e7646d2SAndroid Build Coastguard Worker
532*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on error */
side_cb(int print_fd,int device_fd,int snmp_fd,http_addr_t * addr,int use_bc)533*5e7646d2SAndroid Build Coastguard Worker side_cb(int print_fd, /* I - Print file */
534*5e7646d2SAndroid Build Coastguard Worker int device_fd, /* I - Device file */
535*5e7646d2SAndroid Build Coastguard Worker int snmp_fd, /* I - SNMP socket (unused) */
536*5e7646d2SAndroid Build Coastguard Worker http_addr_t *addr, /* I - Device address (unused) */
537*5e7646d2SAndroid Build Coastguard Worker int use_bc) /* I - Using back-channel? */
538*5e7646d2SAndroid Build Coastguard Worker {
539*5e7646d2SAndroid Build Coastguard Worker cups_sc_command_t command; /* Request command */
540*5e7646d2SAndroid Build Coastguard Worker cups_sc_status_t status; /* Request/response status */
541*5e7646d2SAndroid Build Coastguard Worker char data[2048]; /* Request/response data */
542*5e7646d2SAndroid Build Coastguard Worker int datalen; /* Request/response data size */
543*5e7646d2SAndroid Build Coastguard Worker
544*5e7646d2SAndroid Build Coastguard Worker
545*5e7646d2SAndroid Build Coastguard Worker (void)snmp_fd;
546*5e7646d2SAndroid Build Coastguard Worker (void)addr;
547*5e7646d2SAndroid Build Coastguard Worker
548*5e7646d2SAndroid Build Coastguard Worker datalen = sizeof(data);
549*5e7646d2SAndroid Build Coastguard Worker
550*5e7646d2SAndroid Build Coastguard Worker if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
551*5e7646d2SAndroid Build Coastguard Worker return (-1);
552*5e7646d2SAndroid Build Coastguard Worker
553*5e7646d2SAndroid Build Coastguard Worker switch (command)
554*5e7646d2SAndroid Build Coastguard Worker {
555*5e7646d2SAndroid Build Coastguard Worker case CUPS_SC_CMD_DRAIN_OUTPUT :
556*5e7646d2SAndroid Build Coastguard Worker if (backendDrainOutput(print_fd, device_fd))
557*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_IO_ERROR;
558*5e7646d2SAndroid Build Coastguard Worker else if (tcdrain(device_fd))
559*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_IO_ERROR;
560*5e7646d2SAndroid Build Coastguard Worker else
561*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_OK;
562*5e7646d2SAndroid Build Coastguard Worker
563*5e7646d2SAndroid Build Coastguard Worker datalen = 0;
564*5e7646d2SAndroid Build Coastguard Worker break;
565*5e7646d2SAndroid Build Coastguard Worker
566*5e7646d2SAndroid Build Coastguard Worker case CUPS_SC_CMD_GET_BIDI :
567*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_OK;
568*5e7646d2SAndroid Build Coastguard Worker data[0] = use_bc;
569*5e7646d2SAndroid Build Coastguard Worker datalen = 1;
570*5e7646d2SAndroid Build Coastguard Worker break;
571*5e7646d2SAndroid Build Coastguard Worker
572*5e7646d2SAndroid Build Coastguard Worker case CUPS_SC_CMD_GET_DEVICE_ID :
573*5e7646d2SAndroid Build Coastguard Worker memset(data, 0, sizeof(data));
574*5e7646d2SAndroid Build Coastguard Worker
575*5e7646d2SAndroid Build Coastguard Worker if (backendGetDeviceID(device_fd, data, sizeof(data) - 1,
576*5e7646d2SAndroid Build Coastguard Worker NULL, 0, NULL, NULL, 0))
577*5e7646d2SAndroid Build Coastguard Worker {
578*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
579*5e7646d2SAndroid Build Coastguard Worker datalen = 0;
580*5e7646d2SAndroid Build Coastguard Worker }
581*5e7646d2SAndroid Build Coastguard Worker else
582*5e7646d2SAndroid Build Coastguard Worker {
583*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_OK;
584*5e7646d2SAndroid Build Coastguard Worker datalen = strlen(data);
585*5e7646d2SAndroid Build Coastguard Worker }
586*5e7646d2SAndroid Build Coastguard Worker break;
587*5e7646d2SAndroid Build Coastguard Worker
588*5e7646d2SAndroid Build Coastguard Worker default :
589*5e7646d2SAndroid Build Coastguard Worker status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
590*5e7646d2SAndroid Build Coastguard Worker datalen = 0;
591*5e7646d2SAndroid Build Coastguard Worker break;
592*5e7646d2SAndroid Build Coastguard Worker }
593*5e7646d2SAndroid Build Coastguard Worker
594*5e7646d2SAndroid Build Coastguard Worker return (cupsSideChannelWrite(command, status, data, datalen, 1.0));
595*5e7646d2SAndroid Build Coastguard Worker }
596