4 * Libusb interface code for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 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 if (poll(pfds
, 2, -1) > 0)
161 if (pfds
[0].revents
& POLLIN
)
163 if ((bytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
165 while (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 && 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 */
205 usb_close(printer
->handle
);
206 printer
->handle
= NULL
;
214 * 'find_device()' - Find or enumerate USB printers.
217 static usb_printer_t
* /* O - Found printer */
218 find_device(usb_cb_t cb
, /* I - Callback function */
219 const void *data
) /* I - User data for callback */
221 struct usb_bus
*bus
; /* Current bus */
222 struct usb_device
*device
; /* Current device */
223 struct usb_config_descriptor
*confptr
;/* Pointer to current configuration */
224 struct usb_interface
*ifaceptr
; /* Pointer to current interface */
225 struct usb_interface_descriptor
*altptr
;
226 /* Pointer to current alternate setting */
227 struct usb_endpoint_descriptor
*endpptr
;
228 /* Pointer to current endpoint */
229 int conf
, /* Current configuration */
230 iface
, /* Current interface */
231 altset
, /* Current alternate setting */
232 protocol
, /* Current protocol */
233 endp
, /* Current endpoint */
234 read_endp
, /* Current read endpoint */
235 write_endp
; /* Current write endpoint */
236 char device_id
[1024],/* IEEE-1284 device ID */
239 static usb_printer_t printer
; /* Current printer */
243 * Initialize libusb...
247 fprintf(stderr
, "DEBUG: usb_find_busses=%d\n", usb_find_busses());
248 fprintf(stderr
, "DEBUG: usb_find_devices=%d\n", usb_find_devices());
251 * Then loop through the devices it found...
254 for (bus
= usb_get_busses(); bus
; bus
= bus
->next
)
255 for (device
= bus
->devices
; device
; device
= device
->next
)
258 * Ignore devices with no configuration data and anything that is not
262 if (!device
->config
|| !device
->descriptor
.idVendor
||
263 !device
->descriptor
.idProduct
)
266 for (conf
= 0, confptr
= device
->config
;
267 conf
< device
->descriptor
.bNumConfigurations
;
269 for (iface
= 0, ifaceptr
= confptr
->interface
;
270 iface
< confptr
->bNumInterfaces
;
271 iface
++, ifaceptr
++)
274 * Some printers offer multiple interfaces...
279 for (altset
= 0, altptr
= ifaceptr
->altsetting
;
280 altset
< ifaceptr
->num_altsetting
;
281 altset
++, altptr
++)
284 * Currently we only support unidirectional and bidirectional
285 * printers. Future versions of this code will support the
286 * 1284.4 (packet mode) protocol as well.
289 if (altptr
->bInterfaceClass
!= USB_CLASS_PRINTER
||
290 altptr
->bInterfaceSubClass
!= 1 ||
291 (altptr
->bInterfaceProtocol
!= 1 && /* Unidirectional */
292 altptr
->bInterfaceProtocol
!= 2) || /* Bidirectional */
293 altptr
->bInterfaceProtocol
< protocol
)
299 for (endp
= 0, endpptr
= altptr
->endpoint
;
300 endp
< altptr
->bNumEndpoints
;
302 if ((endpptr
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) ==
303 USB_ENDPOINT_TYPE_BULK
)
305 if (endpptr
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
)
314 * Save the best match so far...
317 protocol
= altptr
->bInterfaceProtocol
;
318 printer
.altset
= altset
;
319 printer
.write_endp
= write_endp
;
320 printer
.read_endp
= read_endp
;
326 printer
.device
= device
;
328 printer
.iface
= iface
;
329 printer
.handle
= NULL
;
331 if (!open_device(&printer
, data
!= NULL
))
333 if (!get_device_id(&printer
, device_id
, sizeof(device_id
)))
335 make_device_uri(&printer
, device_id
, device_uri
,
338 if ((*cb
)(&printer
, device_uri
, device_id
, data
))
340 printer
.read_endp
= printer
.device
->config
[printer
.conf
].
341 interface
[printer
.iface
].
342 altsetting
[printer
.altset
].
343 endpoint
[printer
.read_endp
].
345 printer
.write_endp
= printer
.device
->config
[printer
.conf
].
346 interface
[printer
.iface
].
347 altsetting
[printer
.altset
].
348 endpoint
[printer
.write_endp
].
354 close_device(&printer
);
361 * If we get this far without returning, then we haven't found a printer
370 * 'get_device_id()' - Get the IEEE-1284 device ID for the printer.
373 static int /* O - 0 on success, -1 on error */
374 get_device_id(usb_printer_t
*printer
, /* I - Printer */
375 char *buffer
, /* I - String buffer */
376 size_t bufsize
) /* I - Number of bytes in buffer */
378 int length
; /* Length of device ID */
381 if (usb_control_msg(printer
->handle
,
382 USB_TYPE_CLASS
| USB_ENDPOINT_IN
| USB_RECIP_INTERFACE
,
384 (printer
->iface
<< 8) |
385 printer
->device
->config
[printer
->conf
].
386 interface
[printer
->iface
].
387 altsetting
[printer
->altset
].bAlternateSetting
,
388 buffer
, bufsize
, 5000) < 0)
395 * Extract the length of the device ID string from the first two
396 * bytes. The 1284 spec says the length is stored MSB first...
399 length
= (((unsigned)buffer
[0] & 255) << 8) +
400 ((unsigned)buffer
[1] & 255);
403 * Check to see if the length is larger than our buffer; first
404 * assume that the vendor incorrectly implemented the 1284 spec,
405 * and then limit the length to the size of our buffer...
408 if (length
> (bufsize
- 2))
409 length
= (((unsigned)buffer
[1] & 255) << 8) +
410 ((unsigned)buffer
[0] & 255);
412 if (length
> (bufsize
- 2))
413 length
= bufsize
- 2;
416 * Copy the device ID text to the beginning of the buffer and
420 memmove(buffer
, buffer
+ 2, length
);
421 buffer
[length
] = '\0';
428 * 'list_cb()' - List USB printers for discovery.
431 static int /* O - 0 to continue, 1 to stop */
432 list_cb(usb_printer_t
*printer
, /* I - Printer */
433 const char *device_uri
, /* I - Device URI */
434 const char *device_id
, /* I - IEEE-1284 device ID */
435 const void *data
) /* I - User data (not used) */
437 char make_model
[1024]; /* Make and model */
441 * Get the device URI and make/model strings...
444 backendGetMakeModel(device_id
, make_model
, sizeof(make_model
));
447 * Report the printer...
450 cupsBackendReport("direct", device_uri
, make_model
, make_model
, device_id
,
462 * 'make_device_uri()' - Create a device URI for a USB printer.
465 static char * /* O - Device URI */
467 usb_printer_t
*printer
, /* I - Printer */
468 const char *device_id
, /* I - IEEE-1284 device ID */
469 char *uri
, /* I - Device URI buffer */
470 size_t uri_size
) /* I - Size of device URI buffer */
472 char options
[1024]; /* Device URI options */
473 int num_values
; /* Number of 1284 parameters */
474 cups_option_t
*values
; /* 1284 parameters */
475 const char *mfg
, /* Manufacturer */
477 *des
, /* Description */
478 *sern
; /* Serial number */
479 char tempmfg
[256], /* Temporary manufacturer string */
480 tempsern
[256], /* Temporary serial number string */
481 *tempptr
; /* Pointer into temp string */
485 * Get the make, model, and serial numbers...
488 num_values
= _ppdGet1284Values(device_id
, &values
);
490 if ((sern
= cupsGetOption("SERIALNUMBER", num_values
, values
)) == NULL
)
491 if ((sern
= cupsGetOption("SERN", num_values
, values
)) == NULL
)
492 if ((sern
= cupsGetOption("SN", num_values
, values
)) == NULL
)
495 * Try getting the serial number from the device itself...
498 int length
= usb_get_string_simple(printer
->handle
,
499 printer
->device
->descriptor
.
501 tempsern
, sizeof(tempsern
) - 1);
504 tempsern
[length
] = '\0';
509 if ((mfg
= cupsGetOption("MANUFACTURER", num_values
, values
)) == NULL
)
510 mfg
= cupsGetOption("MFG", num_values
, values
);
512 if ((mdl
= cupsGetOption("MODEL", num_values
, values
)) == NULL
)
513 mdl
= cupsGetOption("MDL", num_values
, values
);
517 * To maintain compatibility with the original IOKit-based backend on Mac OS X,
518 * don't map manufacturer names...
525 * To maintain compatibility with the original character device backend on
526 * Linux and *BSD, map manufacturer names...
531 if (!strcasecmp(mfg
, "Hewlett-Packard"))
533 else if (!strcasecmp(mfg
, "Lexmark International"))
537 #endif /* __APPLE__ */
540 * No manufacturer? Use the model string or description...
544 _ppdNormalizeMakeAndModel(mdl
, tempmfg
, sizeof(tempmfg
));
545 else if ((des
= cupsGetOption("DESCRIPTION", num_values
, values
)) != NULL
||
546 (des
= cupsGetOption("DES", num_values
, values
)) != NULL
)
547 _ppdNormalizeMakeAndModel(des
, tempmfg
, sizeof(tempmfg
));
549 strlcpy(tempmfg
, "Unknown", sizeof(tempmfg
));
551 if ((tempptr
= strchr(tempmfg
, ' ')) != NULL
)
558 * Generate the device URI from the manufacturer, model, serial number,
559 * and interface number...
564 if (printer
->iface
> 0)
565 snprintf(options
, sizeof(options
), "?serial=%s&interface=%d", sern
,
568 snprintf(options
, sizeof(options
), "?serial=%s", sern
);
570 else if (printer
->iface
> 0)
571 snprintf(options
, sizeof(options
), "?interface=%d", printer
->iface
);
575 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, uri_size
, "usb", NULL
, mfg
, 0,
576 "/%s%s", mdl
, options
);
578 cupsFreeOptions(num_values
, values
);
585 * 'open_device()' - Open a connection to the USB printer.
588 static int /* O - 0 on success, -1 on error */
589 open_device(usb_printer_t
*printer
, /* I - Printer */
590 int verbose
) /* I - Update connecting-to-device state? */
592 int number
; /* Configuration/interface/altset numbers */
596 * Return immediately if we are already connected...
603 * Try opening the printer...
606 if ((printer
->handle
= usb_open(printer
->device
)) == NULL
)
610 * Then set the desired configuration...
614 fputs("STATE: +connecting-to-device\n", stderr
);
616 number
= printer
->device
->config
[printer
->conf
].bConfigurationValue
;
617 while (usb_set_configuration(printer
->handle
, number
) < 0)
620 fprintf(stderr
, "DEBUG: Failed to set configuration %d for %04x:%04x\n",
621 number
, printer
->device
->descriptor
.idVendor
,
622 printer
->device
->descriptor
.idProduct
);
628 * Claim interfaces as needed...
631 number
= printer
->device
->config
[printer
->conf
].interface
[printer
->iface
].
632 altsetting
[printer
->altset
].bInterfaceNumber
;
633 while (usb_claim_interface(printer
->handle
, number
) < 0)
636 fprintf(stderr
, "DEBUG: Failed to claim interface %d for %04x:%04x\n",
637 number
, printer
->device
->descriptor
.idVendor
,
638 printer
->device
->descriptor
.idProduct
);
644 while (usb_claim_interface(printer
->handle
, 0) < 0)
647 fprintf(stderr
, "DEBUG: Failed to claim interface 0 for %04x:%04x\n",
648 printer
->device
->descriptor
.idVendor
,
649 printer
->device
->descriptor
.idProduct
);
655 * Set alternate setting...
658 number
= printer
->device
->config
[printer
->conf
].interface
[printer
->iface
].
659 altsetting
[printer
->altset
].bAlternateSetting
;
660 while (usb_set_altinterface(printer
->handle
, number
) < 0)
664 "DEBUG: Failed to set alternate interface %d for %04x:%04x\n",
665 number
, printer
->device
->descriptor
.idVendor
,
666 printer
->device
->descriptor
.idProduct
);
672 fputs("STATE: -connecting-to-device\n", stderr
);
677 * If we get here, there was a hard error...
683 fputs("STATE: -connecting-to-device\n", stderr
);
685 usb_close(printer
->handle
);
686 printer
->handle
= NULL
;
693 * 'print_cb()' - Find a USB printer for printing.
696 static int /* O - 0 to continue, 1 to stop (found) */
697 print_cb(usb_printer_t
*printer
, /* I - Printer */
698 const char *device_uri
, /* I - Device URI */
699 const char *device_id
, /* I - IEEE-1284 device ID */
700 const void *data
) /* I - User data (make, model, S/N) */
702 return (!strcmp((char *)data
, device_uri
));
707 * 'side_cb()' - Handle side-channel requests.
710 static ssize_t
/* O - Number of bytes written */
711 side_cb(usb_printer_t
*printer
, /* I - Printer */
712 int print_fd
) /* I - File to print */
714 ssize_t bytes
, /* Bytes read/written */
715 tbytes
; /* Total bytes written */
716 char buffer
[8192]; /* Print data buffer */
717 struct pollfd pfd
; /* Poll descriptor */
718 cups_sc_command_t command
; /* Request command */
719 cups_sc_status_t status
; /* Request/response status */
720 char data
[2048]; /* Request/response data */
721 int datalen
; /* Request/response data size */
725 datalen
= sizeof(data
);
727 if (cupsSideChannelRead(&command
, &status
, data
, &datalen
, 1.0))
729 _cupsLangPuts(stderr
, _("WARNING: Failed to read side-channel request!\n"));
735 case CUPS_SC_CMD_DRAIN_OUTPUT
:
739 while (poll(&pfd
, 1, 1000) > 0)
741 if ((bytes
= read(print_fd
, buffer
, sizeof(buffer
))) > 0)
743 while (usb_bulk_write(printer
->handle
, printer
->write_endp
, buffer
,
746 _cupsLangPrintf(stderr
,
747 _("ERROR: Unable to write %d bytes to printer!\n"),
755 else if (bytes
< 0 && errno
!= EAGAIN
&& errno
!= EINTR
)
760 status
= CUPS_SC_STATUS_IO_ERROR
;
762 status
= CUPS_SC_STATUS_OK
;
767 case CUPS_SC_CMD_GET_BIDI
:
768 data
[0] = 0; /* TODO: Change to 1 when read supported */
772 case CUPS_SC_CMD_GET_DEVICE_ID
:
773 if (get_device_id(printer
, data
, sizeof(data
)))
775 status
= CUPS_SC_STATUS_IO_ERROR
;
780 status
= CUPS_SC_STATUS_OK
;
781 datalen
= strlen(data
);
786 status
= CUPS_SC_STATUS_NOT_IMPLEMENTED
;
791 cupsSideChannelWrite(command
, status
, data
, datalen
, 1.0);