]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/usb-unix.c
Don't save/restore unless we redefine showpage.
[thirdparty/cups.git] / backend / usb-unix.c
CommitLineData
8e3807e7 1/*
c9d3f842 2 * "$Id$"
8e3807e7 3 *
4 * USB port backend for the Common UNIX Printing System (CUPS).
5 *
6 * This file is included from "usb.c" when compiled on UNIX/Linux.
7 *
766ef83d 8 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
8e3807e7 9 *
10 * These coded instructions, statements, and computer programs are the
11 * property of Easy Software Products and are protected by Federal
12 * copyright law. Distribution and use rights are outlined in the file
13 * "LICENSE" which should have been included with this file. If this
14 * file is missing or damaged please contact Easy Software Products
15 * at:
16 *
17 * Attn: CUPS Licensing Information
18 * Easy Software Products
19 * 44141 Airport View Drive, Suite 204
c9d3f842 20 * Hollywood, Maryland 20636 USA
8e3807e7 21 *
22 * Voice: (301) 373-9600
23 * EMail: cups-info@cups.org
24 * WWW: http://www.cups.org
25 *
26 * This file is subject to the Apple OS-Developed Software exception.
27 *
28 * Contents:
29 *
74584961 30 * print_device() - Print a file to a USB device.
8e3807e7 31 * list_devices() - List all USB devices.
74584961 32 * open_device() - Open a USB device...
8e3807e7 33 */
34
35/*
36 * Include necessary headers.
37 */
38
9ef960f1 39#include "ieee1284.c"
5baa731f 40#include <sys/select.h>
41
8e3807e7 42
43/*
44 * Local functions...
45 */
46
acc0a9db 47int open_device(const char *uri, int *use_bc);
8e3807e7 48
49
50/*
51 * 'print_device()' - Print a file to a USB device.
52 */
53
54int /* O - Exit status */
55print_device(const char *uri, /* I - Device URI */
56 const char *hostname, /* I - Hostname/manufacturer */
57 const char *resource, /* I - Resource/modelname */
58 const char *options, /* I - Device options/serial number */
43b5ad0d 59 int print_fd, /* I - File descriptor to print */
7e826c4a 60 int copies, /* I - Copies to print */
61 int argc, /* I - Number of command-line arguments (6 or 7) */
62 char *argv[]) /* I - Command-line arguments */
8e3807e7 63{
43b5ad0d 64 int use_bc; /* Use backchannel path? */
65 int device_fd; /* USB device */
66 size_t tbytes; /* Total number of bytes written */
8e3807e7 67 struct termios opts; /* Parallel port options */
43b5ad0d 68
8e3807e7 69
7e826c4a 70 (void)argc;
71 (void)argv;
8e3807e7 72
73 /*
74 * Open the USB port device...
75 */
76
22a980cc 77 fputs("STATE: +connecting-to-device\n", stderr);
78
8e3807e7 79 do
80 {
acc0a9db 81 /*
82 * Disable backchannel data when printing to Canon USB printers - apparently
83 * Canon printers will return the IEEE-1284 device ID over and over and over
84 * when they get a read request...
85 */
86
87 use_bc = strcasecmp(hostname, "Canon") != 0;
88
89 if ((device_fd = open_device(uri, &use_bc)) == -1)
8e3807e7 90 {
b7b63780 91 if (getenv("CLASS") != NULL)
92 {
93 /*
94 * If the CLASS environment variable is set, the job was submitted
95 * to a class and not to a specific queue. In this case, we want
96 * to abort immediately so that the job can be requeued on the next
97 * available printer in the class.
98 */
99
100 fputs("INFO: Unable to open USB device, queuing on next printer in class...\n",
101 stderr);
102
103 /*
104 * Sleep 5 seconds to keep the job from requeuing too rapidly...
105 */
106
107 sleep(5);
108
6248387b 109 return (CUPS_BACKEND_FAILED);
b7b63780 110 }
111
8e3807e7 112 if (errno == EBUSY)
113 {
114 fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr);
115 sleep(30);
116 }
43b5ad0d 117 else if (errno == ENXIO || errno == EIO || errno == ENOENT ||
118 errno == ENODEV)
8e3807e7 119 {
120 fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr);
121 sleep(30);
122 }
123 else
124 {
125 fprintf(stderr, "ERROR: Unable to open USB device \"%s\": %s\n",
126 uri, strerror(errno));
6248387b 127 return (CUPS_BACKEND_FAILED);
8e3807e7 128 }
129 }
130 }
43b5ad0d 131 while (device_fd < 0);
8e3807e7 132
22a980cc 133 fputs("STATE: -connecting-to-device\n", stderr);
134
8e3807e7 135 /*
136 * Set any options provided...
137 */
138
43b5ad0d 139 tcgetattr(device_fd, &opts);
8e3807e7 140
141 opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
142
143 /**** No options supported yet ****/
144
43b5ad0d 145 tcsetattr(device_fd, TCSANOW, &opts);
9ef960f1 146
8e3807e7 147 /*
148 * Finally, send the print file...
149 */
150
43b5ad0d 151 tbytes = 0;
897922a9 152
43b5ad0d 153 while (copies > 0 && tbytes >= 0)
8e3807e7 154 {
155 copies --;
156
43b5ad0d 157 if (print_fd != 0)
8e3807e7 158 {
159 fputs("PAGE: 1 1\n", stderr);
43b5ad0d 160 lseek(print_fd, 0, SEEK_SET);
8e3807e7 161 }
162
acc0a9db 163 tbytes = backendRunLoop(print_fd, device_fd, use_bc);
8e3807e7 164
43b5ad0d 165 if (print_fd != 0 && tbytes >= 0)
166 fprintf(stderr, "INFO: Sent print file, " CUPS_LLFMT " bytes...\n",
167 CUPS_LLCAST tbytes);
8e3807e7 168 }
169
170 /*
171 * Close the USB port and return...
172 */
173
43b5ad0d 174 close(device_fd);
8e3807e7 175
43b5ad0d 176 return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
8e3807e7 177}
178
179
8e3807e7 180/*
181 * 'list_devices()' - List all USB devices.
182 */
183
184void
185list_devices(void)
186{
187#ifdef __linux
188 int i; /* Looping var */
8e3807e7 189 int fd; /* File descriptor */
190 char format[255], /* Format for device filename */
191 device[255], /* Device filename */
192 device_id[1024], /* Device ID string */
193 device_uri[1024], /* Device URI string */
194 make_model[1024]; /* Make and model */
195
196
197 /*
198 * First figure out which USB printer filename to use...
199 */
200
9ef960f1 201 if (!access("/dev/usblp0", 0))
6f96d00f 202 strcpy(format, "/dev/usblp%d");
9ef960f1 203 else if (!access("/dev/usb/usblp0", 0))
8e3807e7 204 strcpy(format, "/dev/usb/usblp%d");
205 else
6f96d00f 206 strcpy(format, "/dev/usb/lp%d");
8e3807e7 207
208 /*
209 * Then open each USB device...
210 */
211
212 for (i = 0; i < 16; i ++)
213 {
214 sprintf(device, format, i);
215
216 if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
217 {
43b5ad0d 218 if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
219 make_model, sizeof(make_model),
220 "usb", device_uri, sizeof(device_uri)))
9ef960f1 221 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri,
222 make_model, make_model, i + 1, device_id);
8e3807e7 223
224 close(fd);
225 }
8e3807e7 226 }
227#elif defined(__sgi)
74ef1ffb 228#elif defined(__sun) && defined(ECPPIOC_GETDEVID)
8e3807e7 229 int i; /* Looping var */
230 int fd; /* File descriptor */
231 char device[255], /* Device filename */
232 device_id[1024], /* Device ID string */
233 device_uri[1024], /* Device URI string */
234 make_model[1024]; /* Make and model */
8e3807e7 235
236
237 /*
238 * Open each USB device...
239 */
240
241 for (i = 0; i < 8; i ++)
242 {
243 sprintf(device, "/dev/usb/printer%d", i);
244
acc0a9db 245 if ((fd = open(device, O_WRONLY | O_EXCL)) >= 0)
8e3807e7 246 {
43b5ad0d 247 if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
248 make_model, sizeof(make_model),
249 "usb", device_uri, sizeof(device_uri)))
9ef960f1 250 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri,
251 make_model, make_model, i + 1, device_id);
8e3807e7 252
253 close(fd);
254 }
8e3807e7 255 }
256#elif defined(__hpux)
257#elif defined(__osf)
fe688a06 258#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
8e3807e7 259 int i; /* Looping var */
260 char device[255]; /* Device filename */
261
262
263 for (i = 0; i < 8; i ++)
264 {
265 sprintf(device, "/dev/ulpt%d", i);
266 if (!access(device, 0))
267 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
268
269 sprintf(device, "/dev/unlpt%d", i);
270 if (!access(device, 0))
271 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1);
272 }
273#endif
274}
275
276
277/*
278 * 'open_device()' - Open a USB device...
279 */
280
281int /* O - File descriptor or -1 on error */
acc0a9db 282open_device(const char *uri, /* I - Device URI */
283 int *use_bc) /* O - Set to 0 for unidirectional */
8e3807e7 284{
acc0a9db 285 int fd; /* File descriptor */
286
287
8e3807e7 288 /*
289 * The generic implementation just treats the URI as a device filename...
290 * Specific operating systems may also support using the device serial
291 * number and/or make/model.
292 */
293
9ef960f1 294 if (!strncmp(uri, "usb:/dev/", 9))
8e3807e7 295#ifdef __linux
74584961 296 {
297 /*
298 * Do not allow direct devices anymore...
299 */
300
301 errno = ENODEV;
302 return (-1);
303 }
9ef960f1 304 else if (!strncmp(uri, "usb://", 6))
8e3807e7 305 {
306 /*
307 * For Linux, try looking up the device serial number or model...
308 */
309
310 int i; /* Looping var */
311 int busy; /* Are any ports busy? */
8e3807e7 312 char format[255], /* Format for device filename */
313 device[255], /* Device filename */
314 device_id[1024], /* Device ID string */
315 make_model[1024], /* Make and model */
316 device_uri[1024]; /* Device URI string */
317
318
319 /*
320 * First figure out which USB printer filename to use...
321 */
322
9ef960f1 323 if (!access("/dev/usblp0", 0))
6f96d00f 324 strcpy(format, "/dev/usblp%d");
9ef960f1 325 else if (!access("/dev/usb/usblp0", 0))
8e3807e7 326 strcpy(format, "/dev/usb/usblp%d");
327 else
6f96d00f 328 strcpy(format, "/dev/usb/lp%d");
8e3807e7 329
330 /*
331 * Then find the correct USB device...
332 */
333
334 do
335 {
336 for (busy = 0, i = 0; i < 16; i ++)
337 {
338 sprintf(device, format, i);
339
340 if ((fd = open(device, O_RDWR | O_EXCL)) >= 0)
341 {
43b5ad0d 342 backendGetDeviceID(fd, device_id, sizeof(device_id),
343 make_model, sizeof(make_model),
344 "usb", device_uri, sizeof(device_uri));
8e3807e7 345 }
346 else
347 {
348 /*
349 * If the open failed because it was busy, flag it so we retry
350 * as needed...
351 */
352
353 if (errno == EBUSY)
354 busy = 1;
355
9ef960f1 356 device_uri[0] = '\0';
8e3807e7 357 }
358
9ef960f1 359 if (!strcmp(uri, device_uri))
8e3807e7 360 {
361 /*
9ef960f1 362 * Yes, return this file descriptor...
8e3807e7 363 */
364
9ef960f1 365 fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device);
8e3807e7 366
9ef960f1 367 return (fd);
8e3807e7 368 }
369
370 /*
371 * This wasn't the one...
372 */
373
374 if (fd >= 0)
375 close(fd);
376 }
377
378 /*
379 * If we get here and at least one of the printer ports showed up
380 * as "busy", then sleep for a bit and retry...
381 */
382
383 if (busy)
384 {
385 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
386 stderr);
387 sleep(5);
388 }
389 }
390 while (busy);
391
392 /*
393 * Couldn't find the printer, return "no such device or address"...
394 */
395
396 errno = ENODEV;
397
398 return (-1);
399 }
400#elif defined(__sun) && defined(ECPPIOC_GETDEVID)
74584961 401 {
402 /*
403 * Do not allow direct devices anymore...
404 */
405
406 errno = ENODEV;
407 return (-1);
408 }
9ef960f1 409 else if (!strncmp(uri, "usb://", 6))
8e3807e7 410 {
411 /*
412 * For Solaris, try looking up the device serial number or model...
413 */
414
415 int i; /* Looping var */
416 int busy; /* Are any ports busy? */
8e3807e7 417 char device[255], /* Device filename */
418 device_id[1024], /* Device ID string */
419 make_model[1024], /* Make and model */
420 device_uri[1024]; /* Device URI string */
8e3807e7 421
422
423 /*
424 * Find the correct USB device...
425 */
426
427 do
428 {
63412dfd 429 for (i = 0, busy = 0; i < 8; i ++)
8e3807e7 430 {
431 sprintf(device, "/dev/usb/printer%d", i);
432
acc0a9db 433 if ((fd = open(device, O_WRONLY | O_EXCL)) >= 0)
43b5ad0d 434 backendGetDeviceID(fd, device_id, sizeof(device_id),
435 make_model, sizeof(make_model),
436 "usb", device_uri, sizeof(device_uri));
8e3807e7 437 else
438 {
439 /*
440 * If the open failed because it was busy, flag it so we retry
441 * as needed...
442 */
443
444 if (errno == EBUSY)
445 busy = 1;
446
9ef960f1 447 device_uri[0] = '\0';
8e3807e7 448 }
449
9ef960f1 450 if (!strcmp(uri, device_uri))
acc0a9db 451 {
452 /*
453 * Yes, return this file descriptor...
454 */
455
456 fputs("DEBUG: Setting use_bc to 0!\n", stderr);
457
458 *use_bc = 0;
459
460 return (fd);
461 }
8e3807e7 462
463 /*
464 * This wasn't the one...
465 */
466
467 if (fd >= 0)
468 close(fd);
469 }
470
471 /*
472 * If we get here and at least one of the printer ports showed up
473 * as "busy", then sleep for a bit and retry...
474 */
475
476 if (busy)
477 {
478 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
479 stderr);
480 sleep(5);
481 }
482 }
483 while (busy);
484
485 /*
486 * Couldn't find the printer, return "no such device or address"...
487 */
488
489 errno = ENODEV;
490
491 return (-1);
492 }
d4102150 493#else
acc0a9db 494 {
495 if ((fd = open(uri + 4, O_RDWR | O_EXCL)) < 0)
496 {
497 fd = open(uri + 4, O_WRONLY | O_EXCL);
498 *use_bc = 0;
499 }
500
501 return (fd);
502 }
d4102150 503#endif /* __linux */
8e3807e7 504 else
505 {
506 errno = ENODEV;
507 return (-1);
508 }
509}
510
511
512/*
c9d3f842 513 * End of "$Id$".
8e3807e7 514 */