]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/usb-unix.c
Load cups into easysw/current.
[thirdparty/cups.git] / backend / usb-unix.c
CommitLineData
ef416fc2 1/*
8ca02f3c 2 * "$Id: usb-unix.c 5726 2006-07-12 20:00:11Z mike $"
ef416fc2 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 *
bd7854cb 8 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 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
20 * Hollywood, Maryland 20636 USA
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 *
ed486911 30 * print_device() - Print a file to a USB device.
ef416fc2 31 * list_devices() - List all USB devices.
ed486911 32 * open_device() - Open a USB device...
ef416fc2 33 */
34
35/*
36 * Include necessary headers.
37 */
38
39#include "ieee1284.c"
40#include <sys/select.h>
41
42
43/*
44 * Local functions...
45 */
46
8ca02f3c 47int open_device(const char *uri, int *use_bc);
ef416fc2 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 */
ed486911 59 int print_fd, /* I - File descriptor to print */
e53920b9 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 */
ef416fc2 63{
ed486911 64 int use_bc; /* Use backchannel path? */
65 int device_fd; /* USB device */
66 size_t tbytes; /* Total number of bytes written */
ef416fc2 67 struct termios opts; /* Parallel port options */
ed486911 68
ef416fc2 69
e53920b9 70 (void)argc;
71 (void)argv;
ef416fc2 72
73 /*
74 * Open the USB port device...
75 */
76
757d2cad 77 fputs("STATE: +connecting-to-device\n", stderr);
78
ef416fc2 79 do
80 {
8ca02f3c 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)
ef416fc2 90 {
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
109 return (CUPS_BACKEND_FAILED);
110 }
111
112 if (errno == EBUSY)
113 {
114 fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr);
115 sleep(30);
116 }
ed486911 117 else if (errno == ENXIO || errno == EIO || errno == ENOENT ||
118 errno == ENODEV)
ef416fc2 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));
127 return (CUPS_BACKEND_FAILED);
128 }
129 }
130 }
ed486911 131 while (device_fd < 0);
ef416fc2 132
757d2cad 133 fputs("STATE: -connecting-to-device\n", stderr);
134
ef416fc2 135 /*
136 * Set any options provided...
137 */
138
ed486911 139 tcgetattr(device_fd, &opts);
ef416fc2 140
141 opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
142
143 /**** No options supported yet ****/
144
ed486911 145 tcsetattr(device_fd, TCSANOW, &opts);
ef416fc2 146
ef416fc2 147 /*
148 * Finally, send the print file...
149 */
150
ed486911 151 tbytes = 0;
ef416fc2 152
ed486911 153 while (copies > 0 && tbytes >= 0)
ef416fc2 154 {
155 copies --;
156
ed486911 157 if (print_fd != 0)
ef416fc2 158 {
159 fputs("PAGE: 1 1\n", stderr);
ed486911 160 lseek(print_fd, 0, SEEK_SET);
ef416fc2 161 }
162
8ca02f3c 163 tbytes = backendRunLoop(print_fd, device_fd, use_bc);
ef416fc2 164
ed486911 165 if (print_fd != 0 && tbytes >= 0)
166 fprintf(stderr, "INFO: Sent print file, " CUPS_LLFMT " bytes...\n",
167 CUPS_LLCAST tbytes);
ef416fc2 168 }
169
170 /*
171 * Close the USB port and return...
172 */
173
ed486911 174 close(device_fd);
ef416fc2 175
ed486911 176 return (tbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
ef416fc2 177}
178
179
180/*
181 * 'list_devices()' - List all USB devices.
182 */
183
184void
185list_devices(void)
186{
187#ifdef __linux
188 int i; /* Looping var */
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
201 if (!access("/dev/usblp0", 0))
202 strcpy(format, "/dev/usblp%d");
203 else if (!access("/dev/usb/usblp0", 0))
204 strcpy(format, "/dev/usb/usblp%d");
205 else
206 strcpy(format, "/dev/usb/lp%d");
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 {
ed486911 218 if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
219 make_model, sizeof(make_model),
220 "usb", device_uri, sizeof(device_uri)))
ef416fc2 221 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri,
222 make_model, make_model, i + 1, device_id);
223
224 close(fd);
225 }
226 }
227#elif defined(__sgi)
228#elif defined(__sun) && defined(ECPPIOC_GETDEVID)
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 */
ef416fc2 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
8ca02f3c 245 if ((fd = open(device, O_WRONLY | O_EXCL)) >= 0)
ef416fc2 246 {
ed486911 247 if (!backendGetDeviceID(fd, device_id, sizeof(device_id),
248 make_model, sizeof(make_model),
249 "usb", device_uri, sizeof(device_uri)))
ef416fc2 250 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri,
251 make_model, make_model, i + 1, device_id);
252
253 close(fd);
254 }
255 }
256#elif defined(__hpux)
257#elif defined(__osf)
b423cd4c 258#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
ef416fc2 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 */
8ca02f3c 282open_device(const char *uri, /* I - Device URI */
283 int *use_bc) /* O - Set to 0 for unidirectional */
ef416fc2 284{
8ca02f3c 285 int fd; /* File descriptor */
286
287
ef416fc2 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
294 if (!strncmp(uri, "usb:/dev/", 9))
295#ifdef __linux
ed486911 296 {
297 /*
298 * Do not allow direct devices anymore...
299 */
300
301 errno = ENODEV;
302 return (-1);
303 }
ef416fc2 304 else if (!strncmp(uri, "usb://", 6))
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? */
ef416fc2 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
323 if (!access("/dev/usblp0", 0))
324 strcpy(format, "/dev/usblp%d");
325 else if (!access("/dev/usb/usblp0", 0))
326 strcpy(format, "/dev/usb/usblp%d");
327 else
328 strcpy(format, "/dev/usb/lp%d");
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 {
ed486911 342 backendGetDeviceID(fd, device_id, sizeof(device_id),
343 make_model, sizeof(make_model),
344 "usb", device_uri, sizeof(device_uri));
ef416fc2 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
356 device_uri[0] = '\0';
357 }
358
359 if (!strcmp(uri, device_uri))
360 {
361 /*
362 * Yes, return this file descriptor...
363 */
364
365 fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device);
366
367 return (fd);
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)
ed486911 401 {
402 /*
403 * Do not allow direct devices anymore...
404 */
405
406 errno = ENODEV;
407 return (-1);
408 }
ef416fc2 409 else if (!strncmp(uri, "usb://", 6))
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? */
ef416fc2 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 */
ef416fc2 421
422
423 /*
424 * Find the correct USB device...
425 */
426
427 do
428 {
429 for (i = 0, busy = 0; i < 8; i ++)
430 {
431 sprintf(device, "/dev/usb/printer%d", i);
432
8ca02f3c 433 if ((fd = open(device, O_WRONLY | O_EXCL)) >= 0)
ed486911 434 backendGetDeviceID(fd, device_id, sizeof(device_id),
435 make_model, sizeof(make_model),
436 "usb", device_uri, sizeof(device_uri));
ef416fc2 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
447 device_uri[0] = '\0';
448 }
449
450 if (!strcmp(uri, device_uri))
8ca02f3c 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 }
ef416fc2 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 }
493#else
8ca02f3c 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 }
ef416fc2 503#endif /* __linux */
504 else
505 {
506 errno = ENODEV;
507 return (-1);
508 }
509}
510
511
512/*
8ca02f3c 513 * End of "$Id: usb-unix.c 5726 2006-07-12 20:00:11Z mike $".
ef416fc2 514 */