]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/usb-unix.c
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-2005 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/ioctl.h>
40 # include <linux/lp.h>
41 # define IOCNR_GET_DEVICE_ID 1
44 * Get device_id string
46 # define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
51 # include <sys/ecppio.h>
53 # include <sys/ioccom.h>
54 # include <sys/ecppsys.h>
63 void decode_device_id(int port
, const char *device_id
,
64 char *make_model
, int mmsize
,
65 char *uri
, int urisize
);
66 int open_device(const char *uri
);
70 * 'print_device()' - Print a file to a USB device.
73 int /* O - Exit status */
74 print_device(const char *uri
, /* I - Device URI */
75 const char *hostname
, /* I - Hostname/manufacturer */
76 const char *resource
, /* I - Resource/modelname */
77 const char *options
, /* I - Device options/serial number */
78 int fp
, /* I - File descriptor to print */
79 int copies
) /* I - Copies to print */
81 int fd
; /* USB device */
82 int wbytes
; /* Number of bytes written */
83 size_t nbytes
, /* Number of bytes read */
84 tbytes
; /* Total number of bytes written */
85 char buffer
[8192], /* Output buffer */
86 *bufptr
; /* Pointer into buffer */
87 struct termios opts
; /* Parallel port options */
88 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
89 struct sigaction action
; /* Actions for POSIX signals */
90 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
92 unsigned int status
; /* Port status (off-line, out-of-paper, etc.) */
97 * Open the USB port device...
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...
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
));
146 * Set any options provided...
149 tcgetattr(fd
, &opts
);
151 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
); /* Raw mode */
153 /**** No options supported yet ****/
155 tcsetattr(fd
, TCSANOW
, &opts
);
158 * Now that we are "connected" to the port, ignore SIGTERM so that we
159 * can finish out any page data the driver sends (e.g. to eject the
160 * current page... Only ignore SIGTERM if we are printing data from
161 * stdin (otherwise you can't cancel raw jobs...)
166 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
167 sigset(SIGTERM
, SIG_IGN
);
168 #elif defined(HAVE_SIGACTION)
169 memset(&action
, 0, sizeof(action
));
171 sigemptyset(&action
.sa_mask
);
172 action
.sa_handler
= SIG_IGN
;
173 sigaction(SIGTERM
, &action
, NULL
);
175 signal(SIGTERM
, SIG_IGN
);
176 #endif /* HAVE_SIGSET */
179 #if defined(__linux) && defined(LP_POUTPA)
181 * Show the printer status before we send the file; normally, we'd
182 * do this while we write data to the printer, however at least some
183 * Linux kernels have buggy USB drivers which don't like to be
184 * queried while sending data to the printer...
186 * Also, we're using the 8255 constants instead of the ones that are
187 * supposed to be used, as it appears that the USB driver also doesn't
188 * follow standards...
191 if (ioctl(fd
, LPGETSTATUS
, &status
) == 0)
193 fprintf(stderr
, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status
);
195 if (status
& LP_POUTPA
)
196 fputs("WARNING: Media tray empty!\n", stderr
);
197 else if (!(status
& LP_PERRORP
))
198 fputs("WARNING: Printer fault!\n", stderr
);
199 else if (!(status
& LP_PSELECD
))
200 fputs("WARNING: Printer off-line.\n", stderr
);
202 #endif /* __linux && LP_POUTPA */
205 * Finally, send the print file...
216 fputs("PAGE: 1 1\n", stderr
);
217 lseek(fp
, 0, SEEK_SET
);
221 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
224 * Write the print data to the printer...
233 if ((wbytes
= write(fd
, bufptr
, nbytes
)) < 0)
235 wbytes
= write(fd
, bufptr
, nbytes
);
239 perror("ERROR: Unable to send print file to printer");
251 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
252 (unsigned long)tbytes
);
257 * Close the USB port and return...
267 * 'decode_device_id()' - Decode the IEEE-1284 device ID string.
271 decode_device_id(int port
, /* I - Port number */
272 const char *device_id
, /* I - 1284 device ID string */
273 char *make_model
, /* O - Make/model */
274 int mmsize
, /* I - Size of buffer */
275 char *uri
, /* O - Device URI */
276 int urisize
) /* I - Size of buffer */
278 char *attr
, /* 1284 attribute */
279 *delim
, /* 1284 delimiter */
280 *uriptr
, /* Pointer into URI */
281 *mfg
, /* Manufacturer string */
282 *mdl
, /* Model string */
283 serial_number
[1024]; /* Serial number string */
287 * Look for the description field...
290 if ((attr
= strstr(device_id
, "DES:")) != NULL
)
292 else if ((attr
= strstr(device_id
, "DESCRIPTION:")) != NULL
)
295 if ((mfg
= strstr(device_id
, "MANUFACTURER:")) != NULL
)
297 else if ((mfg
= strstr(device_id
, "MFG:")) != NULL
)
300 if ((mdl
= strstr(device_id
, "MODEL:")) != NULL
)
302 else if ((mdl
= strstr(device_id
, "MDL:")) != NULL
)
311 if (!strncasecmp(attr
, "Hewlett-Packard hp ", 19))
314 * Check for a common HP bug...
317 strlcpy(make_model
, "HP ", mmsize
);
318 strlcpy(make_model
+ 3, attr
+ 19, mmsize
- 3);
320 else if (!strncasecmp(attr
, "Hewlett-Packard ", 16))
322 strlcpy(make_model
, "HP ", mmsize
);
323 strlcpy(make_model
+ 3, attr
+ 16, mmsize
- 3);
327 strlcpy(make_model
, attr
, mmsize
);
333 * Build a make-model string from the manufacturer and model attributes...
336 if (!strncasecmp(mfg
, "Hewlett-Packard", 15))
337 strlcpy(make_model
, "HP", mmsize
);
339 strlcpy(make_model
, mfg
, mmsize
);
341 if ((delim
= strchr(make_model
, ';')) != NULL
)
344 if (!strncasecmp(make_model
, mdl
, strlen(make_model
)))
347 * Just copy model string, since it has the manufacturer...
350 strlcpy(make_model
, mdl
, mmsize
);
355 * Concatenate the make and model...
358 strlcat(make_model
, " ", mmsize
);
359 strlcat(make_model
, mdl
, mmsize
);
365 * Use "Unknown" as the printer make and model...
368 strlcpy(make_model
, "Unknown", mmsize
);
371 if ((delim
= strchr(make_model
, ';')) != NULL
)
375 * Look for the serial number field...
378 if ((attr
= strstr(device_id
, "SERN:")) != NULL
)
380 else if ((attr
= strstr(device_id
, "SERIALNUMBER:")) != NULL
)
382 else if ((attr
= strstr(device_id
, ";SN:")) != NULL
)
387 strlcpy(serial_number
, attr
, sizeof(serial_number
));
389 if ((delim
= strchr(serial_number
, ';')) != NULL
)
393 serial_number
[0] = '\0';
396 * Generate the device URI from the make_model and serial number strings.
399 strlcpy(uri
, "usb://", urisize
);
400 for (uriptr
= uri
+ 6, delim
= make_model
;
401 *delim
&& uriptr
< (uri
+ urisize
- 1);
412 for (; *delim
&& uriptr
< (uri
+ urisize
- 3); delim
++)
424 if (serial_number
[0])
427 * Add the serial number to the URI...
430 strlcat(uri
, "?serial=", urisize
);
431 strlcat(uri
, serial_number
, urisize
);
437 * 'list_devices()' - List all USB devices.
444 int i
; /* Looping var */
445 int length
; /* Length of device ID info */
446 int fd
; /* File descriptor */
447 char format
[255], /* Format for device filename */
448 device
[255], /* Device filename */
449 device_id
[1024], /* Device ID string */
450 device_uri
[1024], /* Device URI string */
451 make_model
[1024]; /* Make and model */
455 * First figure out which USB printer filename to use...
458 if (access("/dev/usblp0", 0) == 0)
459 strcpy(format
, "/dev/usblp%d");
460 else if (access("/dev/usb/usblp0", 0) == 0)
461 strcpy(format
, "/dev/usb/usblp%d");
463 strcpy(format
, "/dev/usb/lp%d");
466 * Then open each USB device...
469 for (i
= 0; i
< 16; i
++)
471 sprintf(device
, format
, i
);
473 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
475 if (ioctl(fd
, LPIOC_GET_DEVICE_ID(sizeof(device_id
)), device_id
) == 0)
477 length
= (((unsigned)device_id
[0] & 255) << 8) +
478 ((unsigned)device_id
[1] & 255);
481 * Check to see if the length is larger than our buffer; first
482 * assume that the vendor incorrectly implemented the 1284 spec,
483 * and then limit the length to the size of our buffer...
486 if (length
> (sizeof(device_id
) - 2))
487 length
= (((unsigned)device_id
[1] & 255) << 8) +
488 ((unsigned)device_id
[0] & 255);
490 if (length
> (sizeof(device_id
) - 2))
491 length
= sizeof(device_id
) - 2;
493 memmove(device_id
, device_id
+ 2, length
);
494 device_id
[length
] = '\0';
506 decode_device_id(i
, device_id
, make_model
, sizeof(make_model
),
507 device_uri
, sizeof(device_uri
));
509 printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri
,
514 #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
515 int i
; /* Looping var */
516 int fd
; /* File descriptor */
517 char device
[255], /* Device filename */
518 device_id
[1024], /* Device ID string */
519 device_uri
[1024], /* Device URI string */
520 make_model
[1024]; /* Make and model */
521 struct ecpp_device_id did
; /* Device ID buffer */
525 * Open each USB device...
528 for (i
= 0; i
< 8; i
++)
530 sprintf(device
, "/dev/usb/printer%d", i
);
532 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
534 did
.mode
= ECPP_CENTRONICS
;
535 did
.len
= sizeof(device_id
);
537 did
.addr
= device_id
;
539 if (ioctl(fd
, ECPPIOC_GETDEVID
, &did
) == 0)
541 if (did
.rlen
< (sizeof(device_id
) - 1))
542 device_id
[did
.rlen
] = '\0';
544 device_id
[sizeof(device_id
) - 1] = '\0';
556 decode_device_id(i
, device_id
, make_model
, sizeof(make_model
),
557 device_uri
, sizeof(device_uri
));
559 printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri
,
563 #elif defined(__hpux)
565 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
566 int i
; /* Looping var */
567 char device
[255]; /* Device filename */
570 for (i
= 0; i
< 8; i
++)
572 sprintf(device
, "/dev/ulpt%d", i
);
573 if (!access(device
, 0))
574 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device
, i
+ 1);
576 sprintf(device
, "/dev/unlpt%d", i
);
577 if (!access(device
, 0))
578 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device
, i
+ 1);
585 * 'open_device()' - Open a USB device...
588 int /* O - File descriptor or -1 on error */
589 open_device(const char *uri
) /* I - Device URI */
592 * The generic implementation just treats the URI as a device filename...
593 * Specific operating systems may also support using the device serial
594 * number and/or make/model.
597 if (strncmp(uri
, "usb:/dev/", 9) == 0)
599 return (-1); /* Do not allow direct devices anymore */
600 else if (strncmp(uri
, "usb://", 6) == 0)
603 * For Linux, try looking up the device serial number or model...
606 int i
; /* Looping var */
607 int busy
; /* Are any ports busy? */
608 int length
; /* Length of device ID info */
609 int fd
; /* File descriptor */
610 char format
[255], /* Format for device filename */
611 device
[255], /* Device filename */
612 device_id
[1024], /* Device ID string */
613 make_model
[1024], /* Make and model */
614 device_uri
[1024]; /* Device URI string */
618 * First figure out which USB printer filename to use...
621 if (access("/dev/usblp0", 0) == 0)
622 strcpy(format
, "/dev/usblp%d");
623 else if (access("/dev/usb/usblp0", 0) == 0)
624 strcpy(format
, "/dev/usb/usblp%d");
626 strcpy(format
, "/dev/usb/lp%d");
629 * Then find the correct USB device...
634 for (busy
= 0, i
= 0; i
< 16; i
++)
636 sprintf(device
, format
, i
);
638 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
640 if (ioctl(fd
, LPIOC_GET_DEVICE_ID(sizeof(device_id
)), device_id
) == 0)
642 length
= (((unsigned)device_id
[0] & 255) << 8) +
643 ((unsigned)device_id
[1] & 255);
644 memmove(device_id
, device_id
+ 2, length
);
645 device_id
[length
] = '\0';
653 * If the open failed because it was busy, flag it so we retry
666 * Got the device ID - is this the one?
669 decode_device_id(i
, device_id
, make_model
, sizeof(make_model
),
670 device_uri
, sizeof(device_uri
));
672 if (strcmp(uri
, device_uri
) == 0)
675 * Yes, return this file descriptor...
678 fprintf(stderr
, "DEBUG: Printer using device file \"%s\"...\n", device
);
685 * This wasn't the one...
693 * If we get here and at least one of the printer ports showed up
694 * as "busy", then sleep for a bit and retry...
699 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
707 * Couldn't find the printer, return "no such device or address"...
714 #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
715 return (-1); /* Do not allow direct devices anymore */
716 else if (strncmp(uri
, "usb://", 6) == 0)
719 * For Solaris, try looking up the device serial number or model...
722 int i
; /* Looping var */
723 int busy
; /* Are any ports busy? */
724 int fd
; /* File descriptor */
725 char device
[255], /* Device filename */
726 device_id
[1024], /* Device ID string */
727 make_model
[1024], /* Make and model */
728 device_uri
[1024]; /* Device URI string */
729 struct ecpp_device_id did
; /* Device ID buffer */
733 * Find the correct USB device...
738 for (i
= 0, busy
= 0; i
< 8; i
++)
740 sprintf(device
, "/dev/usb/printer%d", i
);
742 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
744 did
.mode
= ECPP_CENTRONICS
;
745 did
.len
= sizeof(device_id
);
747 did
.addr
= device_id
;
749 if (ioctl(fd
, ECPPIOC_GETDEVID
, &did
) == 0)
751 if (did
.rlen
< (sizeof(device_id
) - 1))
752 device_id
[did
.rlen
] = '\0';
754 device_id
[sizeof(device_id
) - 1] = '\0';
762 * If the open failed because it was busy, flag it so we retry
775 * Got the device ID - is this the one?
778 decode_device_id(i
, device_id
, make_model
, sizeof(make_model
),
779 device_uri
, sizeof(device_uri
));
781 if (strcmp(uri
, device_uri
) == 0)
782 return (fd
); /* Yes, return this file descriptor... */
786 * This wasn't the one...
794 * If we get here and at least one of the printer ports showed up
795 * as "busy", then sleep for a bit and retry...
800 fputs("INFO: USB printer is busy; will retry in 5 seconds...\n",
808 * Couldn't find the printer, return "no such device or address"...
816 return (open(uri
+ 4, O_RDWR
| O_EXCL
));