4 * Libusb interface code for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
16 * list_devices() - List the available printers.
17 * print_device() - Print a file to a USB device.
18 * close_device() - Close the connection to the USB printer.
19 * find_device() - Find or enumerate USB printers.
20 * get_device_id() - Get the IEEE-1284 device ID for the printer.
21 * list_cb() - List USB printers for discovery.
22 * make_device_uri() - Create a device URI for a USB printer.
23 * open_device() - Open a connection to the USB printer.
24 * print_cb() - Find a USB printer for printing.
25 * side_cb() - Handle side-channel requests.
29 * Include necessary headers...
40 typedef struct usb_printer_s
/**** USB Printer Data ****/
42 struct usb_device
*device
; /* Device info */
43 int conf
, /* Configuration */
44 iface
, /* Interface */
45 altset
, /* Alternate setting */
46 write_endp
, /* Write endpoint */
47 read_endp
; /* Read endpoint */
48 struct usb_dev_handle
*handle
; /* Open handle to device */
51 typedef int (*usb_cb_t
)(usb_printer_t
*, const char *, const char *,
59 static int close_device(usb_printer_t
*printer
);
60 static usb_printer_t
*find_device(usb_cb_t cb
, const void *data
);
61 static int get_device_id(usb_printer_t
*printer
, char *buffer
,
63 static int list_cb(usb_printer_t
*printer
, const char *device_uri
,
64 const char *device_id
, const void *data
);
65 static char *make_device_uri(usb_printer_t
*printer
,
66 const char *device_id
,
67 char *uri
, size_t uri_size
);
68 static int open_device(usb_printer_t
*printer
, int verbose
);
69 static int print_cb(usb_printer_t
*printer
, const char *device_uri
,
70 const char *device_id
, const void *data
);
71 static ssize_t
side_cb(usb_printer_t
*printer
, int print_fd
);
75 * 'list_devices()' - List the available printers.
81 fputs("DEBUG: list_devices\n", stderr
);
82 find_device(list_cb
, NULL
);
87 * 'print_device()' - Print a file to a USB device.
90 int /* O - Exit status */
91 print_device(const char *uri
, /* I - Device URI */
92 const char *hostname
, /* I - Hostname/manufacturer */
93 const char *resource
, /* I - Resource/modelname */
94 char *options
, /* I - Device options/serial number */
95 int print_fd
, /* I - File descriptor to print */
96 int copies
, /* I - Copies to print */
97 int argc
, /* I - Number of command-line arguments (6 or 7) */
98 char *argv
[]) /* I - Command-line arguments */
100 usb_printer_t
*printer
; /* Printer */
101 ssize_t bytes
, /* Bytes read/written */
102 tbytes
; /* Total bytes written */
103 char buffer
[8192]; /* Print data buffer */
104 struct sigaction action
; /* Actions for POSIX signals */
105 struct pollfd pfds
[2]; /* Poll descriptors */
108 fputs("DEBUG: print_device\n", stderr
);
111 * Connect to the printer...
114 while ((printer
= find_device(print_cb
, uri
)) == NULL
)
116 _cupsLangPuts(stderr
,
117 _("INFO: Waiting for printer to become available...\n"));
123 * If we are printing data from a print driver on stdin, ignore SIGTERM
124 * so that the driver can finish out any page data, e.g. to eject the
125 * current page. We only do this for stdin printing as otherwise there
126 * is no way to cancel a raw print job...
131 memset(&action
, 0, sizeof(action
));
133 sigemptyset(&action
.sa_mask
);
134 action
.sa_handler
= SIG_IGN
;
135 sigaction(SIGTERM
, &action
, NULL
);
140 pfds
[0].fd
= print_fd
;
141 pfds
[0].events
= POLLIN
;
142 pfds
[1].fd
= CUPS_SC_FD
;
143 pfds
[1].events
= POLLIN
;
145 while (copies
> 0 && tbytes
>= 0)
151 fputs("PAGE: 1 1\n", stderr
);
152 lseek(print_fd
, 0, SEEK_SET
);
156 * TODO: Add back-channel support, along with better write error handling.
159 while (poll(pfds
, 2, -1) > 0)
161 if (pfds
[0].revents
& POLLIN
)
163 if ((bytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
165 if (usb_bulk_write(printer
->handle
, printer
->write_endp
, buffer
,
168 _cupsLangPrintf(stderr
,
169 _("ERROR: Unable to write %d bytes to printer!\n"),
177 else if (bytes
== 0 || (bytes
< 0 && errno
!= EAGAIN
&& errno
!= EINTR
))
181 if (pfds
[1].revents
& POLLIN
)
182 tbytes
+= side_cb(printer
, print_fd
);
187 * Close our connection and return...
190 close_device(printer
);
192 return (CUPS_BACKEND_OK
);
197 * 'close_device()' - Close the connection to the USB printer.
200 static int /* I - 0 on success, -1 on failure */
201 close_device(usb_printer_t
*printer
) /* I - Printer */
206 * Release interfaces before closing so that we know all data is written
210 int number
= printer
->device
->config
[printer
->conf
].
211 interface
[printer
->iface
].
212 altsetting
[printer
->altset
].bInterfaceNumber
;
213 usb_release_interface(printer
->handle
, number
);
216 usb_release_interface(printer
->handle
, 0);
219 * Close the interface and return...
222 usb_close(printer
->handle
);
223 printer
->handle
= NULL
;
231 * 'find_device()' - Find or enumerate USB printers.
234 static usb_printer_t
* /* O - Found printer */
235 find_device(usb_cb_t cb
, /* I - Callback function */
236 const void *data
) /* I - User data for callback */
238 struct usb_bus
*bus
; /* Current bus */
239 struct usb_device
*device
; /* Current device */
240 struct usb_config_descriptor
*confptr
;/* Pointer to current configuration */
241 struct usb_interface
*ifaceptr
; /* Pointer to current interface */
242 struct usb_interface_descriptor
*altptr
;
243 /* Pointer to current alternate setting */
244 struct usb_endpoint_descriptor
*endpptr
;
245 /* Pointer to current endpoint */
246 int conf
, /* Current configuration */
247 iface
, /* Current interface */
248 altset
, /* Current alternate setting */
249 protocol
, /* Current protocol */
250 endp
, /* Current endpoint */
251 read_endp
, /* Current read endpoint */
252 write_endp
; /* Current write endpoint */
253 char device_id
[1024],/* IEEE-1284 device ID */
256 static usb_printer_t printer
; /* Current printer */
260 * Initialize libusb...
264 fprintf(stderr
, "DEBUG: usb_find_busses=%d\n", usb_find_busses());
265 fprintf(stderr
, "DEBUG: usb_find_devices=%d\n", usb_find_devices());
268 * Then loop through the devices it found...
271 for (bus
= usb_get_busses(); bus
; bus
= bus
->next
)
272 for (device
= bus
->devices
; device
; device
= device
->next
)
275 * Ignore devices with no configuration data and anything that is not
279 if (!device
->config
|| !device
->descriptor
.idVendor
||
280 !device
->descriptor
.idProduct
)
283 for (conf
= 0, confptr
= device
->config
;
284 conf
< device
->descriptor
.bNumConfigurations
;
286 for (iface
= 0, ifaceptr
= confptr
->interface
;
287 iface
< confptr
->bNumInterfaces
;
288 iface
++, ifaceptr
++)
291 * Some printers offer multiple interfaces...
296 for (altset
= 0, altptr
= ifaceptr
->altsetting
;
297 altset
< ifaceptr
->num_altsetting
;
298 altset
++, altptr
++)
301 * Currently we only support unidirectional and bidirectional
302 * printers. Future versions of this code will support the
303 * 1284.4 (packet mode) protocol as well.
306 if (altptr
->bInterfaceClass
!= USB_CLASS_PRINTER
||
307 altptr
->bInterfaceSubClass
!= 1 ||
308 (altptr
->bInterfaceProtocol
!= 1 && /* Unidirectional */
309 altptr
->bInterfaceProtocol
!= 2) || /* Bidirectional */
310 altptr
->bInterfaceProtocol
< protocol
)
316 for (endp
= 0, endpptr
= altptr
->endpoint
;
317 endp
< altptr
->bNumEndpoints
;
319 if ((endpptr
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) ==
320 USB_ENDPOINT_TYPE_BULK
)
322 if (endpptr
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
)
331 * Save the best match so far...
334 protocol
= altptr
->bInterfaceProtocol
;
335 printer
.altset
= altset
;
336 printer
.write_endp
= write_endp
;
337 printer
.read_endp
= read_endp
;
343 printer
.device
= device
;
345 printer
.iface
= iface
;
346 printer
.handle
= NULL
;
348 if (!open_device(&printer
, data
!= NULL
))
350 if (!get_device_id(&printer
, device_id
, sizeof(device_id
)))
352 make_device_uri(&printer
, device_id
, device_uri
,
355 if ((*cb
)(&printer
, device_uri
, device_id
, data
))
357 printer
.read_endp
= printer
.device
->config
[printer
.conf
].
358 interface
[printer
.iface
].
359 altsetting
[printer
.altset
].
360 endpoint
[printer
.read_endp
].
362 printer
.write_endp
= printer
.device
->config
[printer
.conf
].
363 interface
[printer
.iface
].
364 altsetting
[printer
.altset
].
365 endpoint
[printer
.write_endp
].
371 close_device(&printer
);
378 * If we get this far without returning, then we haven't found a printer
387 * 'get_device_id()' - Get the IEEE-1284 device ID for the printer.
390 static int /* O - 0 on success, -1 on error */
391 get_device_id(usb_printer_t
*printer
, /* I - Printer */
392 char *buffer
, /* I - String buffer */
393 size_t bufsize
) /* I - Number of bytes in buffer */
395 int length
; /* Length of device ID */
398 if (usb_control_msg(printer
->handle
,
399 USB_TYPE_CLASS
| USB_ENDPOINT_IN
| USB_RECIP_INTERFACE
,
400 0, printer
->conf
, printer
->iface
,
401 buffer
, bufsize
, 5000) < 0)
408 * Extract the length of the device ID string from the first two
409 * bytes. The 1284 spec says the length is stored MSB first...
412 length
= (((unsigned)buffer
[0] & 255) << 8) +
413 ((unsigned)buffer
[1] & 255);
416 * Check to see if the length is larger than our buffer; first
417 * assume that the vendor incorrectly implemented the 1284 spec,
418 * and then limit the length to the size of our buffer...
421 if (length
> (bufsize
- 2))
422 length
= (((unsigned)buffer
[1] & 255) << 8) +
423 ((unsigned)buffer
[0] & 255);
425 if (length
> (bufsize
- 2))
426 length
= bufsize
- 2;
429 * Copy the device ID text to the beginning of the buffer and
433 memmove(buffer
, buffer
+ 2, length
);
434 buffer
[length
] = '\0';
441 * 'list_cb()' - List USB printers for discovery.
444 static int /* O - 0 to continue, 1 to stop */
445 list_cb(usb_printer_t
*printer
, /* I - Printer */
446 const char *device_uri
, /* I - Device URI */
447 const char *device_id
, /* I - IEEE-1284 device ID */
448 const void *data
) /* I - User data (not used) */
450 char make_model
[1024]; /* Make and model */
454 * Get the device URI and make/model strings...
457 backendGetMakeModel(device_id
, make_model
, sizeof(make_model
));
460 * Report the printer...
463 cupsBackendReport("direct", device_uri
, make_model
, make_model
, device_id
,
475 * 'make_device_uri()' - Create a device URI for a USB printer.
478 static char * /* O - Device URI */
480 usb_printer_t
*printer
, /* I - Printer */
481 const char *device_id
, /* I - IEEE-1284 device ID */
482 char *uri
, /* I - Device URI buffer */
483 size_t uri_size
) /* I - Size of device URI buffer */
485 char options
[1024]; /* Device URI options */
486 int num_values
; /* Number of 1284 parameters */
487 cups_option_t
*values
; /* 1284 parameters */
488 const char *mfg
, /* Manufacturer */
490 *des
, /* Description */
491 *sern
; /* Serial number */
492 char tempmfg
[256], /* Temporary manufacturer string */
493 tempsern
[256], /* Temporary serial number string */
494 *tempptr
; /* Pointer into temp string */
498 * Get the make, model, and serial numbers...
501 num_values
= _ppdGet1284Values(device_id
, &values
);
503 if ((sern
= cupsGetOption("SERIALNUMBER", num_values
, values
)) == NULL
)
504 if ((sern
= cupsGetOption("SERN", num_values
, values
)) == NULL
)
505 if ((sern
= cupsGetOption("SN", num_values
, values
)) == NULL
)
508 * Try getting the serial number from the device itself...
511 int length
= usb_get_string_simple(printer
->handle
,
512 printer
->device
->descriptor
.
514 tempsern
, sizeof(tempsern
) - 1);
517 tempsern
[length
] = '\0';
522 if ((mfg
= cupsGetOption("MANUFACTURER", num_values
, values
)) == NULL
)
523 mfg
= cupsGetOption("MFG", num_values
, values
);
525 if ((mdl
= cupsGetOption("MODEL", num_values
, values
)) == NULL
)
526 mdl
= cupsGetOption("MDL", num_values
, values
);
530 * To maintain compatibility with the original IOKit-based backend on Mac OS X,
531 * don't map manufacturer names...
538 * To maintain compatibility with the original character device backend on
539 * Linux and *BSD, map manufacturer names...
544 if (!strcasecmp(mfg
, "Hewlett-Packard"))
546 else if (!strcasecmp(mfg
, "Lexmark International"))
550 #endif /* __APPLE__ */
553 * No manufacturer? Use the model string or description...
557 _ppdNormalizeMakeAndModel(mdl
, tempmfg
, sizeof(tempmfg
));
558 else if ((des
= cupsGetOption("DESCRIPTION", num_values
, values
)) != NULL
||
559 (des
= cupsGetOption("DES", num_values
, values
)) != NULL
)
560 _ppdNormalizeMakeAndModel(des
, tempmfg
, sizeof(tempmfg
));
562 strlcpy(tempmfg
, "Unknown", sizeof(tempmfg
));
564 if ((tempptr
= strchr(tempmfg
, ' ')) != NULL
)
571 * Generate the device URI from the manufacturer, model, serial number,
572 * and interface number...
577 if (printer
->iface
> 0)
578 snprintf(options
, sizeof(options
), "?serial=%s&interface=%d", sern
,
581 snprintf(options
, sizeof(options
), "?serial=%s", sern
);
583 else if (printer
->iface
> 0)
584 snprintf(options
, sizeof(options
), "?interface=%d", printer
->iface
);
588 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, uri_size
, "usb", NULL
, mfg
, 0,
589 "/%s%s", mdl
, options
);
591 cupsFreeOptions(num_values
, values
);
598 * 'open_device()' - Open a connection to the USB printer.
601 static int /* O - 0 on success, -1 on error */
602 open_device(usb_printer_t
*printer
, /* I - Printer */
603 int verbose
) /* I - Update connecting-to-device state? */
605 int number
; /* Configuration/interface/altset numbers */
609 * Return immediately if we are already connected...
616 * Try opening the printer...
619 if ((printer
->handle
= usb_open(printer
->device
)) == NULL
)
623 * Then set the desired configuration...
627 fputs("STATE: +connecting-to-device\n", stderr
);
629 number
= printer
->device
->config
[printer
->conf
].bConfigurationValue
;
631 if (usb_set_configuration(printer
->handle
, number
) < 0)
634 * If the set fails, chances are that the printer only supports a
635 * single configuration. Technically these printers don't conform to
636 * the USB printer specification, but otherwise they'll work...
640 fprintf(stderr
, "DEBUG: Failed to set configuration %d for %04x:%04x\n",
641 number
, printer
->device
->descriptor
.idVendor
,
642 printer
->device
->descriptor
.idProduct
);
646 * Claim interfaces as needed...
649 number
= printer
->device
->config
[printer
->conf
].interface
[printer
->iface
].
650 altsetting
[printer
->altset
].bInterfaceNumber
;
651 while (usb_claim_interface(printer
->handle
, number
) < 0)
654 fprintf(stderr
, "DEBUG: Failed to claim interface %d for %04x:%04x: %s\n",
655 number
, printer
->device
->descriptor
.idVendor
,
656 printer
->device
->descriptor
.idProduct
, strerror(errno
));
662 while (usb_claim_interface(printer
->handle
, 0) < 0)
665 fprintf(stderr
, "DEBUG: Failed to claim interface 0 for %04x:%04x: %s\n",
666 printer
->device
->descriptor
.idVendor
,
667 printer
->device
->descriptor
.idProduct
, strerror(errno
));
673 * Set alternate setting...
676 number
= printer
->device
->config
[printer
->conf
].interface
[printer
->iface
].
677 altsetting
[printer
->altset
].bAlternateSetting
;
678 while (usb_set_altinterface(printer
->handle
, number
) < 0)
682 "DEBUG: Failed to set alternate interface %d for %04x:%04x: %s\n",
683 number
, printer
->device
->descriptor
.idVendor
,
684 printer
->device
->descriptor
.idProduct
, strerror(errno
));
690 fputs("STATE: -connecting-to-device\n", stderr
);
695 * If we get here, there was a hard error...
701 fputs("STATE: -connecting-to-device\n", stderr
);
703 usb_close(printer
->handle
);
704 printer
->handle
= NULL
;
711 * 'print_cb()' - Find a USB printer for printing.
714 static int /* O - 0 to continue, 1 to stop (found) */
715 print_cb(usb_printer_t
*printer
, /* I - Printer */
716 const char *device_uri
, /* I - Device URI */
717 const char *device_id
, /* I - IEEE-1284 device ID */
718 const void *data
) /* I - User data (make, model, S/N) */
720 return (!strcmp((char *)data
, device_uri
));
725 * 'side_cb()' - Handle side-channel requests.
728 static ssize_t
/* O - Number of bytes written */
729 side_cb(usb_printer_t
*printer
, /* I - Printer */
730 int print_fd
) /* I - File to print */
732 ssize_t bytes
, /* Bytes read/written */
733 tbytes
; /* Total bytes written */
734 char buffer
[8192]; /* Print data buffer */
735 struct pollfd pfd
; /* Poll descriptor */
736 cups_sc_command_t command
; /* Request command */
737 cups_sc_status_t status
; /* Request/response status */
738 char data
[2048]; /* Request/response data */
739 int datalen
; /* Request/response data size */
743 datalen
= sizeof(data
);
745 if (cupsSideChannelRead(&command
, &status
, data
, &datalen
, 1.0))
747 _cupsLangPuts(stderr
, _("WARNING: Failed to read side-channel request!\n"));
753 case CUPS_SC_CMD_DRAIN_OUTPUT
:
757 while (poll(&pfd
, 1, 1000) > 0)
759 if ((bytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
761 while (usb_bulk_write(printer
->handle
, printer
->write_endp
, buffer
,
764 _cupsLangPrintf(stderr
,
765 _("ERROR: Unable to write %d bytes to printer!\n"),
773 else if (bytes
< 0 && errno
!= EAGAIN
&& errno
!= EINTR
)
778 status
= CUPS_SC_STATUS_IO_ERROR
;
780 status
= CUPS_SC_STATUS_OK
;
785 case CUPS_SC_CMD_GET_BIDI
:
786 status
= CUPS_SC_STATUS_OK
;
787 data
[0] = 0; /* TODO: Change to 1 when read supported */
791 case CUPS_SC_CMD_GET_DEVICE_ID
:
792 if (get_device_id(printer
, data
, sizeof(data
)))
794 status
= CUPS_SC_STATUS_IO_ERROR
;
799 status
= CUPS_SC_STATUS_OK
;
800 datalen
= strlen(data
);
805 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
810 cupsSideChannelWrite(command
, status
, data
, datalen
, 1.0);