--- cups-1.2.10/backend/runloop.c.usb-paperout 2006-12-06 20:10:16.000000000 +0000 +++ cups-1.2.10/backend/runloop.c 2007-07-04 12:12:00.000000000 +0100 @@ -40,6 +40,14 @@ #endif /* __hpux */ +#ifdef __linux +#include +#include +#include +int linux_usb_paperout_hack = 0; +#endif /* __linux */ + + /* * 'backendRunLoop()' - Read and write print and back-channel data. */ @@ -64,6 +72,9 @@ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +#ifdef __linux + time_t last_write = 0; /* Last time write() succeeded */ +#endif /* __linux */ fprintf(stderr, "DEBUG: backendRunLoop(print_fd=%d, device_fd=%d, use_bc=%d)\n", @@ -110,8 +121,6 @@ FD_ZERO(&input); if (!print_bytes) FD_SET(print_fd, &input); - if (use_bc) - FD_SET(device_fd, &input); FD_ZERO(&output); if (print_bytes || !use_bc) @@ -119,7 +128,10 @@ if (use_bc) { - if (select(nfds, &input, &output, NULL, NULL) < 0) + struct timeval fives; + fives.tv_sec = 5; + fives.tv_usec = 0; + if (select(nfds, &input, &output, NULL, &fives) < 0) { /* * Pause printing to clear any pending errors... @@ -141,14 +153,24 @@ * Check if we have back-channel data ready... */ - if (FD_ISSET(device_fd, &input)) + if (use_bc && FD_ISSET(device_fd, &output)) /* finished writing */ { - if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0) + struct timeval nowait; + fd_set readback; + FD_ZERO (&readback); + nowait.tv_sec = 0; + nowait.tv_usec = 0; + FD_SET(device_fd, &readback); + if (select (device_fd + 1, &readback, NULL, NULL, &nowait) && + FD_ISSET(device_fd, &readback)) { - fprintf(stderr, - "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n", - CUPS_LLCAST bc_bytes); - cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0); + if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0) + { + fprintf(stderr, + "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n", + CUPS_LLCAST bc_bytes); + cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0); + } } } @@ -219,6 +241,10 @@ offline = 1; } } + else if (linux_usb_paperout_hack && errno == EAGAIN) + { + sleep (1); + } else if (errno != EAGAIN && errno != EINTR && errno != ENOTTY) { perror("ERROR: Unable to write print data"); @@ -227,6 +253,9 @@ } else { +#ifdef __linux + last_write = time (NULL); +#endif /* __linux */ if (paperout) { fputs("STATE: -media-empty-error\n", stderr); @@ -247,7 +276,42 @@ total_bytes += bytes; } } + +#ifdef __linux + if (linux_usb_paperout_hack) + { + time_t now; + if (!paperout && + ((now = time(NULL)) - last_write) >= 5) + { + unsigned int status; + if (ioctl (device_fd, LPGETSTATUS, &status) == 0 && + (status & LP_POUTPA)) + { + fputs("ERROR: Out of paper!\n", stderr); + fputs("STATE: +media-empty-error\n", stderr); + paperout = 1; + } + + /* Don't check status for another 5s. */ + last_write = now; + } + } +#endif /* __linux */ + } + +#ifdef __linux + if (linux_usb_paperout_hack) + { + /* Wait for the last write() to finish. */ + do + { + FD_ZERO(&output); + FD_SET(device_fd, &output); + } while (select(device_fd + 1, NULL, &output, NULL, NULL) < 0 && + errno == EINTR); } +#endif /* __linux */ /* * Return with success... --- cups-1.2.10/backend/usb-unix.c.usb-paperout 2007-07-04 12:11:46.000000000 +0100 +++ cups-1.2.10/backend/usb-unix.c 2007-07-04 12:11:46.000000000 +0100 @@ -39,6 +39,11 @@ #include "ieee1284.c" #include +#ifdef __linux +#include +#include +extern int linux_usb_paperout_hack; +#endif /* __linux */ /* * Local functions... @@ -70,6 +75,11 @@ (void)argc; (void)argv; +#ifdef __linux + /* Get the runloop to check for USB paper-out condition. */ + linux_usb_paperout_hack = 1; +#endif /* __linux */ + /* * Open the USB port device... */ @@ -150,6 +160,12 @@ tcsetattr(device_fd, TCSANOW, &opts); +#ifdef __linux + /* Put the file descriptor into non-blocking mode so that we + * get a chance to detect paper-out. */ + fcntl (device_fd, F_SETFL, fcntl (device_fd, F_GETFL) | O_NONBLOCK); +#endif /* __linux */ + /* * Finally, send the print file... */