]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/usb-unix.c
2 * "$Id: usb-unix.c 5553 2006-05-20 12:22:27Z mike $"
4 * USB port backend for the Common UNIX Printing System (CUPS).
6 * This file is included from "usb.c" when compiled on UNIX/Linux.
8 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
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
17 * Attn: CUPS Licensing Information
18 * Easy Software Products
19 * 44141 Airport View Drive, Suite 204
20 * Hollywood, Maryland 20636 USA
22 * Voice: (301) 373-9600
23 * EMail: cups-info@cups.org
24 * WWW: http://www.cups.org
26 * This file is subject to the Apple OS-Developed Software exception.
30 * main() - Send a file to the specified USB port.
31 * list_devices() - List all USB devices.
35 * Include necessary headers.
39 #include <sys/select.h>
46 int open_device(const char *uri
);
50 * 'print_device()' - Print a file to a USB device.
53 int /* O - Exit status */
54 print_device(const char *uri
, /* I - Device URI */
55 const char *hostname
, /* I - Hostname/manufacturer */
56 const char *resource
, /* I - Resource/modelname */
57 const char *options
, /* I - Device options/serial number */
58 int fp
, /* I - File descriptor to print */
59 int copies
, /* I - Copies to print */
60 int argc
, /* I - Number of command-line arguments (6 or 7) */
61 char *argv
[]) /* I - Command-line arguments */
63 int usebc
; /* Use backchannel path? */
64 int fd
; /* USB device */
65 int rbytes
; /* Number of bytes read */
66 int wbytes
; /* Number of bytes written */
67 size_t nbytes
, /* Number of bytes read */
68 tbytes
; /* Total number of bytes written */
69 char buffer
[8192], /* Output buffer */
70 *bufptr
, /* Pointer into buffer */
71 backbuf
[1024]; /* Backchannel buffer */
72 struct termios opts
; /* Parallel port options */
73 fd_set input
, /* Input set for select() */
74 output
; /* Output set for select() */
75 int paperout
; /* Paper out? */
76 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
77 struct sigaction action
; /* Actions for POSIX signals */
78 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
80 unsigned int status
; /* Port status (off-line, out-of-paper, etc.) */
87 * Disable backchannel data when printing to Canon USB printers - apparently
88 * Canon printers will return the IEEE-1284 device ID over and over and over
89 * when they get a read request...
92 usebc
= strcasecmp(hostname
, "Canon") != 0;
95 * Open the USB port device...
98 fputs("STATE: +connecting-to-device\n", stderr
);
102 if ((fd
= open_device(uri
)) == -1)
104 if (getenv("CLASS") != NULL
)
107 * If the CLASS environment variable is set, the job was submitted
108 * to a class and not to a specific queue. In this case, we want
109 * to abort immediately so that the job can be requeued on the next
110 * available printer in the class.
113 fputs("INFO: Unable to open USB device, queuing on next printer in class...\n",
117 * Sleep 5 seconds to keep the job from requeuing too rapidly...
122 return (CUPS_BACKEND_FAILED
);
127 fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr
);
130 else if (errno
== ENXIO
|| errno
== EIO
|| errno
== ENOENT
|| errno
== ENODEV
)
132 fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr
);
137 fprintf(stderr
, "ERROR: Unable to open USB device \"%s\": %s\n",
138 uri
, strerror(errno
));
139 return (CUPS_BACKEND_FAILED
);
145 fputs("STATE: -connecting-to-device\n", stderr
);
148 * Set any options provided...
151 tcgetattr(fd
, &opts
);
153 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
); /* Raw mode */
155 /**** No options supported yet ****/
157 tcsetattr(fd
, TCSANOW
, &opts
);
160 * Check printer status...
165 #if defined(__linux) && defined(LP_POUTPA)
167 * Show the printer status before we send the file...
170 while (!ioctl(fd
, LPGETSTATUS
, &status
))
172 fprintf(stderr
, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status
);
174 if (status
& LP_POUTPA
)
176 fputs("WARNING: Media tray empty!\n", stderr
);
177 fputs("STATUS: +media-tray-empty-error\n", stderr
);
182 if (!(status
& LP_PERRORP
))
183 fputs("WARNING: Printer fault!\n", stderr
);
184 else if (!(status
& LP_PSELECD
))
185 fputs("WARNING: Printer off-line.\n", stderr
);
191 #endif /* __linux && LP_POUTPA */
194 * Now that we are "connected" to the port, ignore SIGTERM so that we
195 * can finish out any page data the driver sends (e.g. to eject the
196 * current page... Only ignore SIGTERM if we are printing data from
197 * stdin (otherwise you can't cancel raw jobs...)
202 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
203 sigset(SIGTERM
, SIG_IGN
);
204 #elif defined(HAVE_SIGACTION)
205 memset(&action
, 0, sizeof(action
));
207 sigemptyset(&action
.sa_mask
);
208 action
.sa_handler
= SIG_IGN
;
209 sigaction(SIGTERM
, &action
, NULL
);
211 signal(SIGTERM
, SIG_IGN
);
212 #endif /* HAVE_SIGSET */
216 * Finally, send the print file...
227 fputs("PAGE: 1 1\n", stderr
);
228 lseek(fp
, 0, SEEK_SET
);
232 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
235 * Write the print data to the printer...
244 * See if we are ready to read or write...
256 while (select(fd
+ 1, &input
, &output
, NULL
, NULL
) < 0);
258 if (FD_ISSET(fd
, &input
))
261 * Read backchannel data...
264 if ((rbytes
= read(fd
, backbuf
, sizeof(backbuf
))) > 0)
266 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
268 cupsBackChannelWrite(backbuf
, rbytes
, 1.0);
272 if (FD_ISSET(fd
, &output
))
275 * Write print data...
278 if ((wbytes
= write(fd
, bufptr
, nbytes
)) < 0)
280 wbytes
= write(fd
, bufptr
, nbytes
);
285 * Check for retryable errors...
291 fputs("ERROR: Out of paper!\n", stderr
);
292 fputs("STATUS: +media-tray-empty-error\n", stderr
);
294 else if (errno
!= EAGAIN
&& errno
!= EINTR
)
296 perror("ERROR: Unable to send print file to printer");
303 * Update count and pointer...
308 fputs("STATUS: -media-tray-empty-error\n", stderr
);
322 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
323 (unsigned long)tbytes
);
328 * Close the USB port and return...
333 return (wbytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
338 * 'list_devices()' - List all USB devices.
345 int i
; /* Looping var */
346 int fd
; /* File descriptor */
347 char format
[255], /* Format for device filename */
348 device
[255], /* Device filename */
349 device_id
[1024], /* Device ID string */
350 device_uri
[1024], /* Device URI string */
351 make_model
[1024]; /* Make and model */
355 * First figure out which USB printer filename to use...
358 if (!access("/dev/usblp0", 0))
359 strcpy(format
, "/dev/usblp%d");
360 else if (!access("/dev/usb/usblp0", 0))
361 strcpy(format
, "/dev/usb/usblp%d");
363 strcpy(format
, "/dev/usb/lp%d");
366 * Then open each USB device...
369 for (i
= 0; i
< 16; i
++)
371 sprintf(device
, format
, i
);
373 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
375 if (!get_device_id(fd
, device_id
, sizeof(device_id
),
376 make_model
, sizeof(make_model
),
377 "usb", device_uri
, sizeof(device_uri
)))
378 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri
,
379 make_model
, make_model
, i
+ 1, device_id
);
385 #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
386 int i
; /* Looping var */
387 int fd
; /* File descriptor */
388 char device
[255], /* Device filename */
389 device_id
[1024], /* Device ID string */
390 device_uri
[1024], /* Device URI string */
391 make_model
[1024]; /* Make and model */
395 * Open each USB device...
398 for (i
= 0; i
< 8; i
++)
400 sprintf(device
, "/dev/usb/printer%d", i
);
402 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
404 if (!get_device_id(fd
, device_id
, sizeof(device_id
),
405 make_model
, sizeof(make_model
),
406 "usb", device_uri
, sizeof(device_uri
)))
407 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri
,
408 make_model
, make_model
, i
+ 1, device_id
);
413 #elif defined(__hpux)
415 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
416 int i
; /* Looping var */
417 char device
[255]; /* Device filename */
420 for (i
= 0; i
< 8; i
++)
422 sprintf(device
, "/dev/ulpt%d", i
);
423 if (!access(device
, 0))
424 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device
, i
+ 1);
426 sprintf(device
, "/dev/unlpt%d", i
);
427 if (!access(device
, 0))
428 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device
, i
+ 1);
435 * 'open_device()' - Open a USB device...
438 int /* O - File descriptor or -1 on error */
439 open_device(const char *uri
) /* I - Device URI */
442 * The generic implementation just treats the URI as a device filename...
443 * Specific operating systems may also support using the device serial
444 * number and/or make/model.
447 if (!strncmp(uri
, "usb:/dev/", 9))
449 return (-1); /* Do not allow direct devices anymore */
450 else if (!strncmp(uri
, "usb://", 6))
453 * For Linux, try looking up the device serial number or model...
456 int i
; /* Looping var */
457 int busy
; /* Are any ports busy? */
458 int fd
; /* File descriptor */
459 char format
[255], /* Format for device filename */
460 device
[255], /* Device filename */
461 device_id
[1024], /* Device ID string */
462 make_model
[1024], /* Make and model */
463 device_uri
[1024]; /* Device URI string */
467 * First figure out which USB printer filename to use...
470 if (!access("/dev/usblp0", 0))
471 strcpy(format
, "/dev/usblp%d");
472 else if (!access("/dev/usb/usblp0", 0))
473 strcpy(format
, "/dev/usb/usblp%d");
475 strcpy(format
, "/dev/usb/lp%d");
478 * Then find the correct USB device...
483 for (busy
= 0, i
= 0; i
< 16; i
++)
485 sprintf(device
, format
, i
);
487 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
489 get_device_id(fd
, device_id
, sizeof(device_id
),
490 make_model
, sizeof(make_model
),
491 "usb", device_uri
, sizeof(device_uri
));
496 * If the open failed because it was busy, flag it so we retry
503 device_uri
[0] = '\0';
506 if (!strcmp(uri
, device_uri
))
509 * Yes, return this file descriptor...
512 fprintf(stderr
, "DEBUG: Printer using device file \"%s\"...\n", device
);
518 * This wasn't the one...
526 * If we get here and at least one of the printer ports showed up
527 * as "busy", then sleep for a bit and retry...
532 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
540 * Couldn't find the printer, return "no such device or address"...
547 #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
548 return (-1); /* Do not allow direct devices anymore */
549 else if (!strncmp(uri
, "usb://", 6))
552 * For Solaris, try looking up the device serial number or model...
555 int i
; /* Looping var */
556 int busy
; /* Are any ports busy? */
557 int fd
; /* File descriptor */
558 char device
[255], /* Device filename */
559 device_id
[1024], /* Device ID string */
560 make_model
[1024], /* Make and model */
561 device_uri
[1024]; /* Device URI string */
565 * Find the correct USB device...
570 for (i
= 0, busy
= 0; i
< 8; i
++)
572 sprintf(device
, "/dev/usb/printer%d", i
);
574 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
575 get_device_id(fd
, device_id
, sizeof(device_id
),
576 make_model
, sizeof(make_model
),
577 "usb", device_uri
, sizeof(device_uri
));
581 * If the open failed because it was busy, flag it so we retry
588 device_uri
[0] = '\0';
591 if (!strcmp(uri
, device_uri
))
592 return (fd
); /* Yes, return this file descriptor... */
595 * This wasn't the one...
603 * If we get here and at least one of the printer ports showed up
604 * as "busy", then sleep for a bit and retry...
609 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
617 * Couldn't find the printer, return "no such device or address"...
625 return (open(uri
+ 4, O_RDWR
| O_EXCL
));
636 * End of "$Id: usb-unix.c 5553 2006-05-20 12:22:27Z mike $".