]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/usb-unix.c
2 * "$Id: usb-unix.c 5099 2006-02-13 02:46:10Z 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 */
61 int fd
; /* USB device */
62 int rbytes
; /* Number of bytes read */
63 int wbytes
; /* Number of bytes written */
64 size_t nbytes
, /* Number of bytes read */
65 tbytes
; /* Total number of bytes written */
66 char buffer
[8192], /* Output buffer */
67 *bufptr
, /* Pointer into buffer */
68 backbuf
[1024]; /* Backchannel buffer */
69 struct termios opts
; /* Parallel port options */
70 fd_set input
, /* Input set for select() */
71 output
; /* Output set for select() */
72 int paperout
; /* Paper out? */
73 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
74 struct sigaction action
; /* Actions for POSIX signals */
75 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
77 unsigned int status
; /* Port status (off-line, out-of-paper, etc.) */
82 * Open the USB port device...
87 if ((fd
= open_device(uri
)) == -1)
89 if (getenv("CLASS") != NULL
)
92 * If the CLASS environment variable is set, the job was submitted
93 * to a class and not to a specific queue. In this case, we want
94 * to abort immediately so that the job can be requeued on the next
95 * available printer in the class.
98 fputs("INFO: Unable to open USB device, queuing on next printer in class...\n",
102 * Sleep 5 seconds to keep the job from requeuing too rapidly...
107 return (CUPS_BACKEND_FAILED
);
112 fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr
);
115 else if (errno
== ENXIO
|| errno
== EIO
|| errno
== ENOENT
|| errno
== ENODEV
)
117 fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr
);
122 fprintf(stderr
, "ERROR: Unable to open USB device \"%s\": %s\n",
123 uri
, strerror(errno
));
124 return (CUPS_BACKEND_FAILED
);
131 * Set any options provided...
134 tcgetattr(fd
, &opts
);
136 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
); /* Raw mode */
138 /**** No options supported yet ****/
140 tcsetattr(fd
, TCSANOW
, &opts
);
143 * Check printer status...
148 #if defined(__linux) && defined(LP_POUTPA)
150 * Show the printer status before we send the file...
153 while (!ioctl(fd
, LPGETSTATUS
, &status
))
155 fprintf(stderr
, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status
);
157 if (status
& LP_POUTPA
)
159 fputs("WARNING: Media tray empty!\n", stderr
);
160 fputs("STATUS: +media-tray-empty-error\n", stderr
);
165 if (!(status
& LP_PERRORP
))
166 fputs("WARNING: Printer fault!\n", stderr
);
167 else if (!(status
& LP_PSELECD
))
168 fputs("WARNING: Printer off-line.\n", stderr
);
174 #endif /* __linux && LP_POUTPA */
177 * Now that we are "connected" to the port, ignore SIGTERM so that we
178 * can finish out any page data the driver sends (e.g. to eject the
179 * current page... Only ignore SIGTERM if we are printing data from
180 * stdin (otherwise you can't cancel raw jobs...)
185 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
186 sigset(SIGTERM
, SIG_IGN
);
187 #elif defined(HAVE_SIGACTION)
188 memset(&action
, 0, sizeof(action
));
190 sigemptyset(&action
.sa_mask
);
191 action
.sa_handler
= SIG_IGN
;
192 sigaction(SIGTERM
, &action
, NULL
);
194 signal(SIGTERM
, SIG_IGN
);
195 #endif /* HAVE_SIGSET */
199 * Finally, send the print file...
210 fputs("PAGE: 1 1\n", stderr
);
211 lseek(fp
, 0, SEEK_SET
);
215 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
218 * Write the print data to the printer...
227 * See if we are ready to read or write...
237 while (select(fd
+ 1, &input
, &output
, NULL
, NULL
) < 0);
239 if (FD_ISSET(fd
, &input
))
242 * Read backchannel data...
245 if ((rbytes
= read(fd
, backbuf
, sizeof(backbuf
))) > 0)
247 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
249 cupsBackChannelWrite(backbuf
, rbytes
, 1.0);
253 if (FD_ISSET(fd
, &output
))
256 * Write print data...
259 if ((wbytes
= write(fd
, bufptr
, nbytes
)) < 0)
261 wbytes
= write(fd
, bufptr
, nbytes
);
266 * Check for retryable errors...
272 fputs("ERROR: Out of paper!\n", stderr
);
273 fputs("STATUS: +media-tray-empty-error\n", stderr
);
275 else if (errno
!= EAGAIN
&& errno
!= EINTR
)
277 perror("ERROR: Unable to send print file to printer");
284 * Update count and pointer...
289 fputs("STATUS: -media-tray-empty-error\n", stderr
);
303 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
304 (unsigned long)tbytes
);
309 * Close the USB port and return...
314 return (wbytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
319 * 'list_devices()' - List all USB devices.
326 int i
; /* Looping var */
327 int fd
; /* File descriptor */
328 char format
[255], /* Format for device filename */
329 device
[255], /* Device filename */
330 device_id
[1024], /* Device ID string */
331 device_uri
[1024], /* Device URI string */
332 make_model
[1024]; /* Make and model */
336 * First figure out which USB printer filename to use...
339 if (!access("/dev/usblp0", 0))
340 strcpy(format
, "/dev/usblp%d");
341 else if (!access("/dev/usb/usblp0", 0))
342 strcpy(format
, "/dev/usb/usblp%d");
344 strcpy(format
, "/dev/usb/lp%d");
347 * Then open each USB device...
350 for (i
= 0; i
< 16; i
++)
352 sprintf(device
, format
, i
);
354 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
356 if (!get_device_id(fd
, device_id
, sizeof(device_id
),
357 make_model
, sizeof(make_model
),
358 "usb", device_uri
, sizeof(device_uri
)))
359 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri
,
360 make_model
, make_model
, i
+ 1, device_id
);
366 #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
367 int i
; /* Looping var */
368 int fd
; /* File descriptor */
369 char device
[255], /* Device filename */
370 device_id
[1024], /* Device ID string */
371 device_uri
[1024], /* Device URI string */
372 make_model
[1024]; /* Make and model */
373 struct ecpp_device_id did
; /* Device ID buffer */
377 * Open each USB device...
380 for (i
= 0; i
< 8; i
++)
382 sprintf(device
, "/dev/usb/printer%d", i
);
384 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
386 if (!get_device_id(fd
, device_id
, sizeof(device_id
),
387 make_model
, sizeof(make_model
),
388 "usb", device_uri
, sizeof(device_uri
)))
389 printf("direct %s \"%s\" \"%s USB #%d\" \"%s\"\n", device_uri
,
390 make_model
, make_model
, i
+ 1, device_id
);
395 #elif defined(__hpux)
397 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
398 int i
; /* Looping var */
399 char device
[255]; /* Device filename */
402 for (i
= 0; i
< 8; i
++)
404 sprintf(device
, "/dev/ulpt%d", i
);
405 if (!access(device
, 0))
406 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device
, i
+ 1);
408 sprintf(device
, "/dev/unlpt%d", i
);
409 if (!access(device
, 0))
410 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device
, i
+ 1);
417 * 'open_device()' - Open a USB device...
420 int /* O - File descriptor or -1 on error */
421 open_device(const char *uri
) /* I - Device URI */
424 * The generic implementation just treats the URI as a device filename...
425 * Specific operating systems may also support using the device serial
426 * number and/or make/model.
429 if (!strncmp(uri
, "usb:/dev/", 9))
431 return (-1); /* Do not allow direct devices anymore */
432 else if (!strncmp(uri
, "usb://", 6))
435 * For Linux, try looking up the device serial number or model...
438 int i
; /* Looping var */
439 int busy
; /* Are any ports busy? */
440 int fd
; /* File descriptor */
441 char format
[255], /* Format for device filename */
442 device
[255], /* Device filename */
443 device_id
[1024], /* Device ID string */
444 make_model
[1024], /* Make and model */
445 device_uri
[1024]; /* Device URI string */
449 * First figure out which USB printer filename to use...
452 if (!access("/dev/usblp0", 0))
453 strcpy(format
, "/dev/usblp%d");
454 else if (!access("/dev/usb/usblp0", 0))
455 strcpy(format
, "/dev/usb/usblp%d");
457 strcpy(format
, "/dev/usb/lp%d");
460 * Then find the correct USB device...
465 for (busy
= 0, i
= 0; i
< 16; i
++)
467 sprintf(device
, format
, i
);
469 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
471 get_device_id(fd
, device_id
, sizeof(device_id
),
472 make_model
, sizeof(make_model
),
473 "usb", device_uri
, sizeof(device_uri
));
478 * If the open failed because it was busy, flag it so we retry
485 device_uri
[0] = '\0';
488 if (!strcmp(uri
, device_uri
))
491 * Yes, return this file descriptor...
494 fprintf(stderr
, "DEBUG: Printer using device file \"%s\"...\n", device
);
500 * This wasn't the one...
508 * If we get here and at least one of the printer ports showed up
509 * as "busy", then sleep for a bit and retry...
514 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
522 * Couldn't find the printer, return "no such device or address"...
529 #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
530 return (-1); /* Do not allow direct devices anymore */
531 else if (!strncmp(uri
, "usb://", 6))
534 * For Solaris, try looking up the device serial number or model...
537 int i
; /* Looping var */
538 int busy
; /* Are any ports busy? */
539 int fd
; /* File descriptor */
540 char device
[255], /* Device filename */
541 device_id
[1024], /* Device ID string */
542 make_model
[1024], /* Make and model */
543 device_uri
[1024]; /* Device URI string */
544 struct ecpp_device_id did
; /* Device ID buffer */
548 * Find the correct USB device...
553 for (i
= 0, busy
= 0; i
< 8; i
++)
555 sprintf(device
, "/dev/usb/printer%d", i
);
557 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
558 get_device_id(fd
, device_id
, sizeof(device_id
),
559 make_model
, sizeof(make_model
),
560 "usb", device_uri
, sizeof(device_uri
));
564 * If the open failed because it was busy, flag it so we retry
571 device_uri
[0] = '\0';
574 if (!strcmp(uri
, device_uri
))
575 return (fd
); /* Yes, return this file descriptor... */
578 * This wasn't the one...
586 * If we get here and at least one of the printer ports showed up
587 * as "busy", then sleep for a bit and retry...
592 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
600 * Couldn't find the printer, return "no such device or address"...
608 return (open(uri
+ 4, O_RDWR
| O_EXCL
));
619 * End of "$Id: usb-unix.c 5099 2006-02-13 02:46:10Z mike $".