]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/usb-libusb.c
Check for overlapping filenames.
[thirdparty/cups.git] / backend / usb-libusb.c
CommitLineData
bdb5a5c3 1/*
2 * "$Id$"
3 *
4 * Libusb interface code for the Common UNIX Printing System (CUPS).
5 *
9f36749a 6 * Copyright 2007-2009 by Apple Inc.
bdb5a5c3 7 *
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/".
13 *
14 * Contents:
15 *
4828c388 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.
bdb5a5c3 26 */
27
28/*
29 * Include necessary headers...
30 */
31
32#include <usb.h>
4828c388 33#include <poll.h>
bdb5a5c3 34
35
36/*
37 * Local types...
38 */
39
40typedef struct usb_printer_s /**** USB Printer Data ****/
41{
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 */
49} usb_printer_t;
50
a9800876 51typedef int (*usb_cb_t)(usb_printer_t *, const char *, const char *,
52 const void *);
bdb5a5c3 53
54
55/*
56 * Local functions...
57 */
58
59static int close_device(usb_printer_t *printer);
60static usb_printer_t *find_device(usb_cb_t cb, const void *data);
61static int get_device_id(usb_printer_t *printer, char *buffer,
62 size_t bufsize);
a9800876 63static int list_cb(usb_printer_t *printer, const char *device_uri,
64 const char *device_id, const void *data);
bdb5a5c3 65static char *make_device_uri(usb_printer_t *printer,
66 const char *device_id,
67 char *uri, size_t uri_size);
a9800876 68static int open_device(usb_printer_t *printer, int verbose);
69static int print_cb(usb_printer_t *printer, const char *device_uri,
70 const char *device_id, const void *data);
4828c388 71static ssize_t side_cb(usb_printer_t *printer, int print_fd);
bdb5a5c3 72
73
74/*
75 * 'list_devices()' - List the available printers.
76 */
77
78void
79list_devices(void)
80{
81 fputs("DEBUG: list_devices\n", stderr);
82 find_device(list_cb, NULL);
83}
84
85
86/*
87 * 'print_device()' - Print a file to a USB device.
88 */
89
90int /* O - Exit status */
91print_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 */
99{
a9800876 100 usb_printer_t *printer; /* Printer */
d11f579d 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 */
4828c388 105 struct pollfd pfds[2]; /* Poll descriptors */
a9800876 106
107
108 fputs("DEBUG: print_device\n", stderr);
109
d11f579d 110 /*
111 * Connect to the printer...
112 */
113
a9800876 114 while ((printer = find_device(print_cb, uri)) == NULL)
115 {
116 _cupsLangPuts(stderr,
117 _("INFO: Waiting for printer to become available...\n"));
118 sleep(5);
119 }
120
d11f579d 121
122 /*
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...
127 */
128
129 if (!print_fd)
130 {
131 memset(&action, 0, sizeof(action));
132
133 sigemptyset(&action.sa_mask);
134 action.sa_handler = SIG_IGN;
135 sigaction(SIGTERM, &action, NULL);
136 }
137
138 tbytes = 0;
139
4828c388 140 pfds[0].fd = print_fd;
141 pfds[0].events = POLLIN;
142 pfds[1].fd = CUPS_SC_FD;
143 pfds[1].events = POLLIN;
144
d11f579d 145 while (copies > 0 && tbytes >= 0)
146 {
147 copies --;
148
149 if (print_fd != 0)
150 {
151 fputs("PAGE: 1 1\n", stderr);
152 lseek(print_fd, 0, SEEK_SET);
153 }
154
155 /*
4828c388 156 * TODO: Add back-channel support, along with better write error handling.
d11f579d 157 */
158
42961c58 159 while (poll(pfds, 2, -1) > 0)
d11f579d 160 {
4828c388 161 if (pfds[0].revents & POLLIN)
d11f579d 162 {
4828c388 163 if ((bytes = read(print_fd, buffer, sizeof(buffer))) > 0)
164 {
42961c58 165 if (usb_bulk_write(printer->handle, printer->write_endp, buffer,
b5565217 166 bytes, 45000) < 0)
4828c388 167 {
168 _cupsLangPrintf(stderr,
169 _("ERROR: Unable to write %d bytes to printer!\n"),
170 (int)bytes);
171 tbytes = -1;
172 break;
173 }
174
175 tbytes += bytes;
176 }
42961c58 177 else if (bytes == 0 || (bytes < 0 && errno != EAGAIN && errno != EINTR))
4828c388 178 break;
d11f579d 179 }
180
4828c388 181 if (pfds[1].revents & POLLIN)
a806b4ec 182 {
183 if ((bytes = side_cb(printer, print_fd)) < 0)
184 pfds[1].events = 0; /* Filter has gone away... */
185 else
186 tbytes += bytes;
187 }
d11f579d 188 }
189 }
190
191 /*
192 * Close our connection and return...
193 */
194
a9800876 195 close_device(printer);
196
197 return (CUPS_BACKEND_OK);
bdb5a5c3 198}
199
200
201/*
202 * 'close_device()' - Close the connection to the USB printer.
203 */
204
205static int /* I - 0 on success, -1 on failure */
206close_device(usb_printer_t *printer) /* I - Printer */
207{
208 if (printer->handle)
209 {
b5565217 210 /*
211 * Release interfaces before closing so that we know all data is written
212 * to the device...
213 */
214
f8fd972e 215 int number = printer->device->config[printer->conf].
216 interface[printer->iface].
217 altsetting[printer->altset].bInterfaceNumber;
b5565217 218 usb_release_interface(printer->handle, number);
219
220 if (number != 0)
221 usb_release_interface(printer->handle, 0);
222
223 /*
224 * Close the interface and return...
225 */
226
bdb5a5c3 227 usb_close(printer->handle);
228 printer->handle = NULL;
229 }
230
231 return (0);
232}
233
234
235/*
236 * 'find_device()' - Find or enumerate USB printers.
237 */
238
239static usb_printer_t * /* O - Found printer */
240find_device(usb_cb_t cb, /* I - Callback function */
241 const void *data) /* I - User data for callback */
242{
243 struct usb_bus *bus; /* Current bus */
244 struct usb_device *device; /* Current device */
245 struct usb_config_descriptor *confptr;/* Pointer to current configuration */
246 struct usb_interface *ifaceptr; /* Pointer to current interface */
247 struct usb_interface_descriptor *altptr;
248 /* Pointer to current alternate setting */
249 struct usb_endpoint_descriptor *endpptr;
250 /* Pointer to current endpoint */
251 int conf, /* Current configuration */
252 iface, /* Current interface */
253 altset, /* Current alternate setting */
254 protocol, /* Current protocol */
255 endp, /* Current endpoint */
256 read_endp, /* Current read endpoint */
257 write_endp; /* Current write endpoint */
a9800876 258 char device_id[1024],/* IEEE-1284 device ID */
259 device_uri[1024];
260 /* Device URI */
bdb5a5c3 261 static usb_printer_t printer; /* Current printer */
262
263
264 /*
265 * Initialize libusb...
266 */
267
268 usb_init();
269 fprintf(stderr, "DEBUG: usb_find_busses=%d\n", usb_find_busses());
270 fprintf(stderr, "DEBUG: usb_find_devices=%d\n", usb_find_devices());
271
272 /*
273 * Then loop through the devices it found...
274 */
275
276 for (bus = usb_get_busses(); bus; bus = bus->next)
277 for (device = bus->devices; device; device = device->next)
278 {
279 /*
280 * Ignore devices with no configuration data and anything that is not
281 * a printer...
282 */
283
bdb5a5c3 284 if (!device->config || !device->descriptor.idVendor ||
285 !device->descriptor.idProduct)
286 continue;
287
288 for (conf = 0, confptr = device->config;
289 conf < device->descriptor.bNumConfigurations;
290 conf ++, confptr ++)
291 for (iface = 0, ifaceptr = confptr->interface;
292 iface < confptr->bNumInterfaces;
293 iface ++, ifaceptr ++)
294 {
295 /*
296 * Some printers offer multiple interfaces...
297 */
298
299 protocol = 0;
300
301 for (altset = 0, altptr = ifaceptr->altsetting;
302 altset < ifaceptr->num_altsetting;
303 altset ++, altptr ++)
304 {
305 /*
306 * Currently we only support unidirectional and bidirectional
307 * printers. Future versions of this code will support the
308 * 1284.4 (packet mode) protocol as well.
309 */
310
311 if (altptr->bInterfaceClass != USB_CLASS_PRINTER ||
312 altptr->bInterfaceSubClass != 1 ||
313 (altptr->bInterfaceProtocol != 1 && /* Unidirectional */
314 altptr->bInterfaceProtocol != 2) || /* Bidirectional */
315 altptr->bInterfaceProtocol < protocol)
316 continue;
317
318 read_endp = -1;
319 write_endp = -1;
320
321 for (endp = 0, endpptr = altptr->endpoint;
322 endp < altptr->bNumEndpoints;
323 endp ++, endpptr ++)
324 if ((endpptr->bmAttributes & USB_ENDPOINT_TYPE_MASK) ==
325 USB_ENDPOINT_TYPE_BULK)
326 {
327 if (endpptr->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
328 read_endp = endp;
329 else
330 write_endp = endp;
331 }
332
333 if (write_endp >= 0)
334 {
335 /*
336 * Save the best match so far...
337 */
338
339 protocol = altptr->bInterfaceProtocol;
340 printer.altset = altset;
341 printer.write_endp = write_endp;
342 printer.read_endp = read_endp;
343 }
344 }
345
346 if (protocol > 0)
347 {
348 printer.device = device;
349 printer.conf = conf;
350 printer.iface = iface;
351 printer.handle = NULL;
352
a9800876 353 if (!open_device(&printer, data != NULL))
bdb5a5c3 354 {
355 if (!get_device_id(&printer, device_id, sizeof(device_id)))
a9800876 356 {
357 make_device_uri(&printer, device_id, device_uri,
358 sizeof(device_uri));
359
360 if ((*cb)(&printer, device_uri, device_id, data))
4828c388 361 {
362 printer.read_endp = printer.device->config[printer.conf].
363 interface[printer.iface].
364 altsetting[printer.altset].
365 endpoint[printer.read_endp].
366 bEndpointAddress;
367 printer.write_endp = printer.device->config[printer.conf].
368 interface[printer.iface].
369 altsetting[printer.altset].
370 endpoint[printer.write_endp].
371 bEndpointAddress;
bdb5a5c3 372 return (&printer);
4828c388 373 }
a9800876 374 }
bdb5a5c3 375
376 close_device(&printer);
377 }
378 }
379 }
380 }
381
382 /*
383 * If we get this far without returning, then we haven't found a printer
384 * to print to...
385 */
386
387 return (NULL);
388}
389
390
391/*
392 * 'get_device_id()' - Get the IEEE-1284 device ID for the printer.
393 */
394
395static int /* O - 0 on success, -1 on error */
396get_device_id(usb_printer_t *printer, /* I - Printer */
397 char *buffer, /* I - String buffer */
398 size_t bufsize) /* I - Number of bytes in buffer */
399{
400 int length; /* Length of device ID */
401
402
403 if (usb_control_msg(printer->handle,
404 USB_TYPE_CLASS | USB_ENDPOINT_IN | USB_RECIP_INTERFACE,
7e734dcc 405 0, printer->conf, printer->iface,
bdb5a5c3 406 buffer, bufsize, 5000) < 0)
407 {
408 *buffer = '\0';
409 return (-1);
410 }
411
412 /*
413 * Extract the length of the device ID string from the first two
414 * bytes. The 1284 spec says the length is stored MSB first...
415 */
416
417 length = (((unsigned)buffer[0] & 255) << 8) +
418 ((unsigned)buffer[1] & 255);
419
420 /*
421 * Check to see if the length is larger than our buffer; first
422 * assume that the vendor incorrectly implemented the 1284 spec,
423 * and then limit the length to the size of our buffer...
424 */
425
b379a395 426 if (length > bufsize)
bdb5a5c3 427 length = (((unsigned)buffer[1] & 255) << 8) +
428 ((unsigned)buffer[0] & 255);
429
b379a395 430 if (length > bufsize)
431 length = bufsize;
432
433 length -= 2;
bdb5a5c3 434
435 /*
436 * Copy the device ID text to the beginning of the buffer and
437 * nul-terminate.
438 */
439
440 memmove(buffer, buffer + 2, length);
441 buffer[length] = '\0';
442
443 return (0);
444}
445
446
447/*
448 * 'list_cb()' - List USB printers for discovery.
449 */
450
451static int /* O - 0 to continue, 1 to stop */
452list_cb(usb_printer_t *printer, /* I - Printer */
a9800876 453 const char *device_uri, /* I - Device URI */
bdb5a5c3 454 const char *device_id, /* I - IEEE-1284 device ID */
455 const void *data) /* I - User data (not used) */
456{
a9800876 457 char make_model[1024]; /* Make and model */
bdb5a5c3 458
459
460 /*
461 * Get the device URI and make/model strings...
462 */
463
bdb5a5c3 464 backendGetMakeModel(device_id, make_model, sizeof(make_model));
465
466 /*
467 * Report the printer...
468 */
469
2317ac1e 470 cupsBackendReport("direct", device_uri, make_model, make_model, device_id,
471 NULL);
bdb5a5c3 472
473 /*
474 * Keep going...
475 */
476
477 return (0);
478}
479
480
481/*
482 * 'make_device_uri()' - Create a device URI for a USB printer.
483 */
484
485static char * /* O - Device URI */
486make_device_uri(
487 usb_printer_t *printer, /* I - Printer */
488 const char *device_id, /* I - IEEE-1284 device ID */
489 char *uri, /* I - Device URI buffer */
490 size_t uri_size) /* I - Size of device URI buffer */
491{
492 char options[1024]; /* Device URI options */
493 int num_values; /* Number of 1284 parameters */
494 cups_option_t *values; /* 1284 parameters */
495 const char *mfg, /* Manufacturer */
496 *mdl, /* Model */
497 *des, /* Description */
498 *sern; /* Serial number */
a9800876 499 char tempmfg[256], /* Temporary manufacturer string */
500 tempsern[256], /* Temporary serial number string */
bdb5a5c3 501 *tempptr; /* Pointer into temp string */
502
503
504 /*
505 * Get the make, model, and serial numbers...
506 */
507
508 num_values = _ppdGet1284Values(device_id, &values);
509
510 if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
511 if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
a9800876 512 if ((sern = cupsGetOption("SN", num_values, values)) == NULL)
513 {
514 /*
515 * Try getting the serial number from the device itself...
516 */
517
518 int length = usb_get_string_simple(printer->handle,
519 printer->device->descriptor.
520 iSerialNumber,
521 tempsern, sizeof(tempsern) - 1);
522 if (length > 0)
523 {
524 tempsern[length] = '\0';
525 sern = tempsern;
526 }
527 }
bdb5a5c3 528
529 if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL)
530 mfg = cupsGetOption("MFG", num_values, values);
531
532 if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL)
533 mdl = cupsGetOption("MDL", num_values, values);
534
a9800876 535#ifdef __APPLE__
536 /*
537 * To maintain compatibility with the original IOKit-based backend on Mac OS X,
538 * don't map manufacturer names...
539 */
540
541 if (!mfg)
542
543#else
544 /*
545 * To maintain compatibility with the original character device backend on
546 * Linux and *BSD, map manufacturer names...
547 */
548
bdb5a5c3 549 if (mfg)
550 {
551 if (!strcasecmp(mfg, "Hewlett-Packard"))
552 mfg = "HP";
553 else if (!strcasecmp(mfg, "Lexmark International"))
554 mfg = "Lexmark";
555 }
556 else
a9800876 557#endif /* __APPLE__ */
bdb5a5c3 558 {
559 /*
560 * No manufacturer? Use the model string or description...
561 */
562
563 if (mdl)
a9800876 564 _ppdNormalizeMakeAndModel(mdl, tempmfg, sizeof(tempmfg));
bdb5a5c3 565 else if ((des = cupsGetOption("DESCRIPTION", num_values, values)) != NULL ||
566 (des = cupsGetOption("DES", num_values, values)) != NULL)
a9800876 567 _ppdNormalizeMakeAndModel(des, tempmfg, sizeof(tempmfg));
bdb5a5c3 568 else
a9800876 569 strlcpy(tempmfg, "Unknown", sizeof(tempmfg));
bdb5a5c3 570
a9800876 571 if ((tempptr = strchr(tempmfg, ' ')) != NULL)
bdb5a5c3 572 *tempptr = '\0';
573
a9800876 574 mfg = tempmfg;
bdb5a5c3 575 }
576
577 /*
578 * Generate the device URI from the manufacturer, model, serial number,
579 * and interface number...
580 */
581
582 if (sern)
583 {
584 if (printer->iface > 0)
585 snprintf(options, sizeof(options), "?serial=%s&interface=%d", sern,
586 printer->iface);
587 else
588 snprintf(options, sizeof(options), "?serial=%s", sern);
589 }
590 else if (printer->iface > 0)
591 snprintf(options, sizeof(options), "?interface=%d", printer->iface);
592 else
593 options[0] = '\0';
594
595 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, uri_size, "usb", NULL, mfg, 0,
596 "/%s%s", mdl, options);
597
598 cupsFreeOptions(num_values, values);
599
600 return (uri);
601}
602
603
604/*
605 * 'open_device()' - Open a connection to the USB printer.
606 */
607
608static int /* O - 0 on success, -1 on error */
a9800876 609open_device(usb_printer_t *printer, /* I - Printer */
610 int verbose) /* I - Update connecting-to-device state? */
bdb5a5c3 611{
612 int number; /* Configuration/interface/altset numbers */
613
614
615 /*
616 * Return immediately if we are already connected...
617 */
618
619 if (printer->handle)
620 return (0);
621
622 /*
623 * Try opening the printer...
624 */
625
626 if ((printer->handle = usb_open(printer->device)) == NULL)
627 return (-1);
628
629 /*
630 * Then set the desired configuration...
631 */
632
a9800876 633 if (verbose)
634 fputs("STATE: +connecting-to-device\n", stderr);
bdb5a5c3 635
636 number = printer->device->config[printer->conf].bConfigurationValue;
7e734dcc 637
638 if (usb_set_configuration(printer->handle, number) < 0)
bdb5a5c3 639 {
7e734dcc 640 /*
641 * If the set fails, chances are that the printer only supports a
642 * single configuration. Technically these printers don't conform to
643 * the USB printer specification, but otherwise they'll work...
644 */
645
a9800876 646 if (errno != EBUSY)
bdb5a5c3 647 fprintf(stderr, "DEBUG: Failed to set configuration %d for %04x:%04x\n",
648 number, printer->device->descriptor.idVendor,
649 printer->device->descriptor.idProduct);
bdb5a5c3 650 }
651
652 /*
653 * Claim interfaces as needed...
654 */
655
656 number = printer->device->config[printer->conf].interface[printer->iface].
657 altsetting[printer->altset].bInterfaceNumber;
658 while (usb_claim_interface(printer->handle, number) < 0)
659 {
a9800876 660 if (errno != EBUSY)
7e734dcc 661 fprintf(stderr, "DEBUG: Failed to claim interface %d for %04x:%04x: %s\n",
bdb5a5c3 662 number, printer->device->descriptor.idVendor,
7e734dcc 663 printer->device->descriptor.idProduct, strerror(errno));
bdb5a5c3 664
a9800876 665 goto error;
bdb5a5c3 666 }
667
668 if (number != 0)
669 while (usb_claim_interface(printer->handle, 0) < 0)
670 {
a9800876 671 if (errno != EBUSY)
7e734dcc 672 fprintf(stderr, "DEBUG: Failed to claim interface 0 for %04x:%04x: %s\n",
bdb5a5c3 673 printer->device->descriptor.idVendor,
7e734dcc 674 printer->device->descriptor.idProduct, strerror(errno));
bdb5a5c3 675
a9800876 676 goto error;
bdb5a5c3 677 }
678
679 /*
680 * Set alternate setting...
681 */
682
683 number = printer->device->config[printer->conf].interface[printer->iface].
684 altsetting[printer->altset].bAlternateSetting;
685 while (usb_set_altinterface(printer->handle, number) < 0)
686 {
a9800876 687 if (errno != EBUSY)
bdb5a5c3 688 fprintf(stderr,
7e734dcc 689 "DEBUG: Failed to set alternate interface %d for %04x:%04x: %s\n",
bdb5a5c3 690 number, printer->device->descriptor.idVendor,
7e734dcc 691 printer->device->descriptor.idProduct, strerror(errno));
bdb5a5c3 692
a9800876 693 goto error;
bdb5a5c3 694 }
695
a9800876 696 if (verbose)
697 fputs("STATE: -connecting-to-device\n", stderr);
bdb5a5c3 698
699 return (0);
700
701 /*
702 * If we get here, there was a hard error...
703 */
704
705 error:
706
a9800876 707 if (verbose)
708 fputs("STATE: -connecting-to-device\n", stderr);
bdb5a5c3 709
710 usb_close(printer->handle);
711 printer->handle = NULL;
a9800876 712
bdb5a5c3 713 return (-1);
714}
715
716
717/*
718 * 'print_cb()' - Find a USB printer for printing.
719 */
720
721static int /* O - 0 to continue, 1 to stop (found) */
722print_cb(usb_printer_t *printer, /* I - Printer */
a9800876 723 const char *device_uri, /* I - Device URI */
bdb5a5c3 724 const char *device_id, /* I - IEEE-1284 device ID */
725 const void *data) /* I - User data (make, model, S/N) */
726{
a9800876 727 return (!strcmp((char *)data, device_uri));
bdb5a5c3 728}
729
730
4828c388 731/*
732 * 'side_cb()' - Handle side-channel requests.
733 */
734
735static ssize_t /* O - Number of bytes written */
736side_cb(usb_printer_t *printer, /* I - Printer */
737 int print_fd) /* I - File to print */
738{
739 ssize_t bytes, /* Bytes read/written */
740 tbytes; /* Total bytes written */
741 char buffer[8192]; /* Print data buffer */
742 struct pollfd pfd; /* Poll descriptor */
743 cups_sc_command_t command; /* Request command */
744 cups_sc_status_t status; /* Request/response status */
745 char data[2048]; /* Request/response data */
746 int datalen; /* Request/response data size */
747
748
749 tbytes = 0;
750 datalen = sizeof(data);
751
752 if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
a806b4ec 753 return (-1);
4828c388 754
755 switch (command)
756 {
757 case CUPS_SC_CMD_DRAIN_OUTPUT :
758 pfd.fd = print_fd;
759 pfd.events = POLLIN;
760
761 while (poll(&pfd, 1, 1000) > 0)
762 {
763 if ((bytes = read(print_fd, buffer, sizeof(buffer))) > 0)
764 {
765 while (usb_bulk_write(printer->handle, printer->write_endp, buffer,
766 bytes, 5000) < 0)
767 {
768 _cupsLangPrintf(stderr,
769 _("ERROR: Unable to write %d bytes to printer!\n"),
770 (int)bytes);
771 tbytes = -1;
772 break;
773 }
774
775 tbytes += bytes;
776 }
777 else if (bytes < 0 && errno != EAGAIN && errno != EINTR)
778 break;
779 }
780
781 if (tbytes < 0)
782 status = CUPS_SC_STATUS_IO_ERROR;
783 else
784 status = CUPS_SC_STATUS_OK;
785
786 datalen = 0;
787 break;
788
789 case CUPS_SC_CMD_GET_BIDI :
130780d3 790 status = CUPS_SC_STATUS_OK;
4828c388 791 data[0] = 0; /* TODO: Change to 1 when read supported */
792 datalen = 1;
793 break;
794
795 case CUPS_SC_CMD_GET_DEVICE_ID :
796 if (get_device_id(printer, data, sizeof(data)))
797 {
798 status = CUPS_SC_STATUS_IO_ERROR;
799 datalen = 0;
800 }
801 else
802 {
803 status = CUPS_SC_STATUS_OK;
804 datalen = strlen(data);
805 }
806 break;
807
808 default :
809 status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
810 datalen = 0;
811 break;
812 }
813
814 cupsSideChannelWrite(command, status, data, datalen, 1.0);
815
816 return (tbytes);
817}
818
819
bdb5a5c3 820/*
821 * End of "$Id$".
822 */
823