patch-2.4.0-test12 linux/drivers/usb/printer.c
Next file: linux/drivers/usb/scanner.c
Previous file: linux/drivers/usb/plusb.c
Back to the patch index
Back to the overall index
- Lines: 121
- Date:
Fri Dec 1 12:17:24 2000
- Orig file:
v2.4.0-test11/linux/drivers/usb/printer.c
- Orig date:
Sun Nov 19 18:44:16 2000
diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
@@ -82,6 +82,7 @@
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
int minor; /* minor number of device */
+ unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
unsigned char bidir; /* interface is bidirectional */
unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
@@ -90,6 +91,26 @@
static struct usblp *usblp_table[USBLP_MINORS];
+/* Quirks: various printer quirks are handled by this table & its flags. */
+
+struct quirk_printer_struct {
+ __u16 vendorId;
+ __u16 productId;
+ unsigned int quirks;
+};
+
+#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
+#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
+
+static struct quirk_printer_struct quirk_printers[] = {
+ { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
+ { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
+ { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
+ { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
+ { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
+ { 0, 0 }
+};
+
/*
* Functions for usblp control messages.
*/
@@ -325,8 +346,17 @@
return -ENODEV;
if (usblp->writeurb.status) {
- err = usblp_check_status(usblp, err);
- continue;
+ if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+ if (usblp->writeurb.status != -EINPROGRESS)
+ err("usblp%d: error %d writing to printer",
+ usblp->minor, usblp->writeurb.status);
+ err = usblp->writeurb.status;
+ continue;
+ }
+ else {
+ err = usblp_check_status(usblp, err);
+ continue;
+ }
}
writecount += usblp->writeurb.transfer_buffer_length;
@@ -393,13 +423,42 @@
return count;
}
+/*
+ * Checks for printers that have quirks, such as requiring unidirectional
+ * communication but reporting bidirectional; currently some HP printers
+ * have this flaw (HP 810, 880, 895, etc.), or needing an init string
+ * sent at each open (like some Epsons).
+ * Returns 1 if found, 0 if not found.
+ *
+ * HP recommended that we use the bidirectional interface but
+ * don't attempt any bulk IN transfers from the IN endpoint.
+ * Here's some more detail on the problem:
+ * The problem is not that it isn't bidirectional though. The problem
+ * is that if you request a device ID, or status information, while
+ * the buffers are full, the return data will end up in the print data
+ * buffer. For example if you make sure you never request the device ID
+ * while you are sending print data, and you don't try to query the
+ * printer status every couple of milliseconds, you will probably be OK.
+ */
+static unsigned int usblp_quirks (__u16 vendor, __u16 product)
+{
+ int i;
+
+ for (i = 0; quirk_printers[i].vendorId; i++) {
+ if (vendor == quirk_printers[i].vendorId &&
+ product == quirk_printers[i].productId)
+ return quirk_printers[i].quirks;
+ }
+ return 0;
+}
+
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *epread, *epwrite;
struct usblp *usblp;
- int minor, i, bidir = 0;
+ int minor, i, bidir = 0, quirks;
int alts = dev->actconfig->interface[ifnum].act_altsetting;
int length, err;
char *buf;
@@ -453,10 +512,21 @@
}
memset(usblp, 0, sizeof(struct usblp));
+ /* lookup quirks for this printer */
+ quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+ if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
+ bidir = 0;
+ epread = NULL;
+ info ("Disabling reads from problem bidirectional printer on usblp%d",
+ minor);
+ }
+
usblp->dev = dev;
usblp->ifnum = ifnum;
usblp->minor = minor;
usblp->bidir = bidir;
+ usblp->quirks = quirks;
init_waitqueue_head(&usblp->wait);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)