]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
The libusb-based USB backend now loads its list of quirks from files in
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 17 Jul 2013 15:21:18 +0000 (15:21 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 17 Jul 2013 15:21:18 +0000 (15:21 +0000)
/usr/share/cups/usb instead of using a hardcoded table
(<rdar://problem/14442769>)

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11154 a1ca3aef-8c08-0410-bb20-df032aa958be

CHANGES-1.6.txt
Makedefs.in
backend/Makefile
backend/org.cups.usb-quirks [new file with mode: 0644]
backend/usb-libusb.c
config-scripts/cups-common.m4
packaging/cups.spec.in

index dfbd42f39d9b0d162dc897319387b0ba17c0ce19..96da1a537ebd2b8893371c1de3968d30ebf05428 100644 (file)
@@ -3,6 +3,9 @@ CHANGES-1.6.txt
 
 CHANGES IN CUPS V1.6.4
 
+       - The libusb-based USB backend now loads its list of quirks from files
+         in /usr/share/cups/usb instead of using a hardcoded table
+         (<rdar://problem/14442769>)
        - The scheduler did not properly register ICC color profiles with
          colord (<rdar://problem/14455625>)
 
index 676e0dd64df82031c698f575f7611403074fadb9..817f18ab1285ad97db3870d6f9fb3b534b5dde82 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Common makefile definitions for CUPS.
 #
-#   Copyright 2007-2012 by Apple Inc.
+#   Copyright 2007-2013 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -218,6 +218,7 @@ SERVERBIN   =       $(BUILDROOT)@CUPS_SERVERBIN@
 SERVERROOT     =       $(BUILDROOT)@CUPS_SERVERROOT@
 SMFMANIFESTDIR =       @SMFMANIFESTDIR@
 STATEDIR       =       $(BUILDROOT)@CUPS_STATEDIR@
+USBQUIRKS      =       @USBQUIRKS@
 XINETD         =       @XINETD@
 
 MAN1EXT                =       @MAN1EXT@
index adb8f67004534a4f09a6376e943d70d8dccff469..8d1e12e71ea8646bd5f26d67759453001da05275 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Backend makefile for CUPS.
 #
-#   Copyright 2007-2012 by Apple Inc.
+#   Copyright 2007-2013 by Apple Inc.
 #   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -109,6 +109,11 @@ install:   all install-data install-headers install-libs install-exec
 #
 
 install-data:
+       if test "x$(USBQUIRKS)" != x; then \
+               echo Installing USB quirks in $(USBQUIRKS); \
+               $(INSTALL_DIR) -m 755 $(USBQUIRKS); \
+               $(INSTALL_DATA) org.cups.usb-quirks $(USBQUIRKS); \
+       fi
 
 
 #
diff --git a/backend/org.cups.usb-quirks b/backend/org.cups.usb-quirks
new file mode 100644 (file)
index 0000000..6d41cf5
--- /dev/null
@@ -0,0 +1,212 @@
+# USB backend 'quirks' file.
+#
+# This file lists known issues with various vendors or printers.  Each
+# line contains either a comment (starting with #) or the USB vendor ID,
+# product ID (omit for all vendor products), and a list of known issues:
+#
+#   blacklist     The printer is not functional with the USB backend.
+#   no-reattach   Do no re-attach usblp kernel module after printing.
+#   soft-reset    Do a soft reset after printing for cleanup.
+#   unidir        Only supported unidirectional I/O
+#   usb-init      Needs vendor USB initialization string.
+#   vendor-class  Uses vendor-specific class or subclass.
+#   whitelist     The printer is functional with the USB backend.
+
+# HP DeskJet 895C
+0x03f0 0x0004 unidir
+
+# HP DeskJet 880C
+0x03f0 0x0104 unidir
+
+# HP DeskJet 815C
+0x03f0 0x0204 unidir
+
+# HP DeskJet 810C/812C
+0x03f0 0x0304 unidir
+
+# HP DeskJet 830C
+0x03f0 0x0404 unidir
+
+# HP DeskJet 885C
+0x03f0 0x0504 unidir
+
+# HP DeskJet 840C
+0x03f0 0x0604 unidir
+
+# HP DeskJet 816C
+0x03f0 0x0804 unidir
+
+# HP Deskjet 959C
+0x03f0 0x1104 unidir
+
+# NEC Picty900 (HP OEM)
+0x0409 0xefbe unidir
+
+# NEC Picty760 (HP OEM)
+0x0409 0xbef4 unidir
+
+# NEC Picty920 (HP OEM)
+0x0409 0xf0be unidir
+
+# NEC Picty800 (HP OEM)
+0x0409 0xf1be unidir
+
+# Lexmark International, Inc. (e250d), https://bugs.launchpad.net/bugs/1084164
+0x043d 0x00f3 no-reattach
+
+# Kyocera Mita FS 820, by zut <kernel@zut.de>
+0x0482 0x0010 unidir
+
+# Canon, Inc. PIXMA iP6000D Printer, https://bugs.launchpad.net/bugs/1160638
+0x04a9 0x1095 unidir
+
+# Canon, Inc. PIXMA iP4200 Printer, http://www.cups.org/str.php?L4155
+0x04a9 0x10a2 unidir
+
+# Canon, Inc. PIXMA iP4300 Printer, https://bugs.launchpad.net/bugs/1032385
+0x04a9 0x10b6 unidir
+
+# Canon, Inc. MP210 https://bugzilla.redhat.com/show_bug.cgi?id=847923#c53
+0x04a9 0x1721 unidir
+
+# Canon, Inc. MP500 Printer, https://bugs.launchpad.net/bugs/1032456
+0x04a9 0x170c unidir
+
+# Canon, Inc. MP510 Printer, https://bugs.launchpad.net/bugs/1050009
+0x04a9 0x1717 unidir
+
+# Canon, Inc. MP550 Printer, http://www.cups.org/str.php?L4155
+0x04a9 0x173d unidir
+
+# Canon, Inc. MP560 Printer, http://www.cups.org/str.php?L4155
+0x04a9 0x173e unidir
+
+# Canon, Inc. MF4150 Printer, https://bugs.launchpad.net/bugs/1160638
+0x04a9 0x26a3 no-reattach
+
+# Brother Industries, Ltd HL-1430 Laser Printer, https://bugs.launchpad.net/bugs/1038695
+0x04f9 0x001a no-reattach
+
+# Brother Industries, Ltd HL-1440 Laser Printer, https://bugs.launchpad.net/bugs/1000253
+0x04f9 0x000d no-reattach unidir
+
+# Brother Industries, Ltd HL-1450 Laser Printer, https://bugs.launchpad.net/bugs/1000253
+0x04f9 0x000e no-reattach unidir
+
+# Oki Data Corp. Okipage 14ex Printer, https://bugs.launchpad.net/bugs/872483
+0x06bc 0x000b no-reattach
+
+# Oki Data Corp. B410d, https://bugs.launchpad.net/bugs/872483
+0x06bc 0x01c7 no-reattach
+
+# Seiko Epson Corp. Stylus Color 740 / Photo 750, http://bugs.debian.org/697970
+0x04b8 0x0001 no-reattach unidir
+
+# Seiko Epson Corp. Stylus Color 670, https://bugs.launchpad.net/bugs/872483
+0x04b8 0x0005 no-reattach
+
+# Seiko Epson Receipt Printer M129C
+0x04b8 0x0202 vendor-class
+
+# Prolific Technology, Inc. PL2305 Parallel Port (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/987485
+0x067b 0x2305 no-reattach soft-reset unidir
+
+# Xerox Phaser 3124 https://bugzilla.redhat.com/show_bug.cgi?id=867392
+0x0924 0x3ce9 no-reattach
+
+# Xerox WorkCentre 3210 https://bugs.launchpad.net/bugs/1102470
+0x0924 0x4293 no-reattach
+
+# QinHeng Electronics CH340S (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/1000253
+0x1a86 0x7584 no-reattach
+
+# All Samsung devices, https://bugs.launchpad.net/bugs/1032456
+0x04e8 soft-reset
+
+# All Zebra devices, https://bugs.launchpad.net/bugs/1001028
+0x0a5f unidir
+
+# Canon CP-10
+0x04a9 0x304a blacklist
+
+# Canon CP-100
+0x04a9 0x3063 blacklist
+
+# Canon CP-200
+0x04a9 0x307c blacklist
+
+# Canon CP-300
+0x04a9 0x307d blacklist
+
+# Canon CP-220
+0x04a9 0x30bd blacklist
+
+# Canon CP-330
+0x04a9 0x30be blacklist
+
+# Canon SELPHY CP400
+0x04a9 0x30f6 blacklist
+
+# Canon SELPHY CP600
+0x04a9 0x310b blacklist
+
+# Canon SELPHY CP710
+0x04a9 0x3127 blacklist
+
+# Canon SELPHY CP510
+0x04a9 0x3128 blacklist
+
+# Canon SELPHY ES1
+0x04a9 0x3141 blacklist
+
+# Canon SELPHY CP730
+0x04a9 0x3142 blacklist
+
+# Canon SELPHY CP720
+0x04a9 0x3143 blacklist
+
+# Canon SELPHY CP750
+0x04a9 0x3170 blacklist
+
+# Canon SELPHY CP740
+0x04a9 0x3171 blacklist
+
+# Canon SELPHY ES2
+0x04a9 0x3185 blacklist
+
+# Canon SELPHY ES20
+0x04a9 0x3186 blacklist
+
+# Canon SELPHY CP770
+0x04a9 0x31aa blacklist
+
+# Canon SELPHY CP760
+0x04a9 0x31ab blacklist
+
+# Canon SELPHY ES30
+0x04a9 0x31b0 blacklist
+
+# Canon SELPHY CP780
+0x04a9 0x31dd blacklist
+
+# Canon SELPHY ES40
+0x04a9 0x31ee blacklist
+
+# Canon SELPHY CP800
+0x04a9 0x3214 blacklist
+
+# Canon SELPHY CP900
+0x04a9 0x3255 blacklist
+
+# Canon SELPHY CP810
+0x04a9 0x3256 blacklist
+
+# Canon SELPHY CP500
+0x04a9 0x30f5 blacklist
+
+# Canon SELPHY ES3
+0x04a9 0x31af blacklist
+
+# Canon SELPHY CP780
+0x04a9 0x31dd blacklist
+
index dc32bd082ba6baf4a36cf6d63608d87df7dcb987..0eb4742467a226d4bf247f09ca6c4d87cdabcfcb 100644 (file)
  *   list_devices()      - List the available printers.
  *   print_device()      - Print a file to a USB device.
  *   close_device()      - Close the connection to the USB printer.
+ *   compare_quirks()    - Compare two quirks entries.
  *   find_device()       - Find or enumerate USB printers.
+ *   find_quirks()       - Find the quirks for the given printer, if any.
  *   get_device_id()     - Get the IEEE-1284 device ID for the printer.
  *   list_cb()           - List USB printers for discovery.
+ *   load_quirks()       - Load all quirks files in the /usr/share/cups/usb
+ *                         directory.
  *   make_device_uri()   - Create a device URI for a USB printer.
  *   open_device()       - Open a connection to the USB printer.
  *   print_cb()          - Find a USB printer for printing.
- *   printer_class_soft_reset()' - Do the soft reset request specific to
- *                          printers
- *   quirks()            - Get the known quirks of a given printer model
  *   read_thread()       - Thread to read the backchannel data on.
  *   sidechannel_thread() - Handle side-channel requests.
  *   soft_reset()        - Send a soft reset to the device.
+ *   soft_reset_printer() - Do the soft reset request specific to printers
  */
 
 /*
@@ -70,15 +72,15 @@ typedef struct usb_printer_s                /**** USB Printer Data ****/
                        read_endp,      /* Read endpoint */
                        protocol,       /* Protocol: 1 = Uni-di, 2 = Bi-di. */
                        usblp_attached, /* "usblp" kernel module attached? */
-                       reset_after_job; /* Set to 1 by print_device() */
-  unsigned int         quirks;         /* Quirks flags */
+                       reset_after_job;/* Set to 1 by print_device() */
+  unsigned             quirks;         /* Quirks flags */
   struct libusb_device_handle *handle; /* Open handle to device */
 } usb_printer_t;
 
 typedef int (*usb_cb_t)(usb_printer_t *, const char *, const char *,
                         const void *);
 
-typedef struct usb_globals_s
+typedef struct usb_globals_s           /* Global USB printer information */
 {
   usb_printer_t                *printer;       /* Printer */
 
@@ -105,141 +107,39 @@ typedef struct usb_globals_s
 } usb_globals_t;
 
 /*
- * Quirks: various printer quirks are handled by this table & its flags.
+ * Quirks: various printer quirks are handled by this structure and its flags.
  *
- * This is copied from the usblp kernel module. So we can easily copy and paste
- * new quirks from the module.
+ * The quirks table used to be compiled into the backend but is now loaded from
+ * one or more files in the /usr/share/cups/usb directory.
  */
 
-struct quirk_printer_struct {
-       int vendorId;
-       int 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 */
-#define USBLP_QUIRK_BAD_CLASS  0x4     /* descriptor uses vendor-specific
-                                          Class or SubClass */
-#define USBLP_QUIRK_BLACKLIST  0x8     /* these printers do not conform to the USB print spec */
-#define USBLP_QUIRK_RESET      0x4000  /* After printing do a reset
-                                          for clean-up */
-#define USBLP_QUIRK_NO_REATTACH        0x8000  /* After printing we cannot re-attach
+#define USB_QUIRK_BLACKLIST    0x0001  /* Does not conform to the spec */
+#define USB_QUIRK_NO_REATTACH  0x0002  /* After printing we cannot re-attach
                                           the usblp kernel module */
+#define USB_QUIRK_SOFT_RESET   0x0004  /* After printing do a soft reset
+                                          for clean-up */
+#define USB_QUIRK_UNIDIR       0x0008  /* Requires unidirectional mode */
+#define USB_QUIRK_USB_INIT     0x0010  /* Needs vendor USB init string */
+#define USB_QUIRK_VENDOR_CLASS 0x0020  /* Descriptor uses vendor-specific
+                                          Class or SubClass */
+#define USB_QUIRK_WHITELIST    0x0000  /* no quirks */
+
+
+typedef struct usb_quirk_s             /* USB "quirk" information */
+{
+  int          vendor_id,              /* Affected vendor ID */
+               product_id;             /* Affected product ID or 0 for all */
+  unsigned     quirks;                 /* Quirks bitfield */
+} usb_quirk_t;
+
 
-static const 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 */
-       { 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */
-       { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */
-       { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */
-       { 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */
-       { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
-       { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
-       { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
-       { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
-       { 0x043d, 0x00f3, USBLP_QUIRK_NO_REATTACH }, /* Lexmark International,
-                      Inc. (e250d), https://bugs.launchpad.net/bugs/1084164 */
-       { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820,
-                                                 by zut <kernel@zut.de> */
-       { 0x04a9, 0x1095, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP6000D
-                           Printer, https://bugs.launchpad.net/bugs/1160638 */
-       { 0x04a9, 0x10a2, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP4200
-                           Printer, http://www.cups.org/str.php?L4155 */
-       { 0x04a9, 0x10b6, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP4300
-                           Printer, https://bugs.launchpad.net/bugs/1032385 */
-       { 0x04a9, 0x1721, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP210
-                     https://bugzilla.redhat.com/show_bug.cgi?id=847923#c53 */
-       { 0x04a9, 0x170c, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP500
-                           Printer, https://bugs.launchpad.net/bugs/1032456 */
-       { 0x04a9, 0x1717, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP510
-                           Printer, https://bugs.launchpad.net/bugs/1050009 */
-       { 0x04a9, 0x173d, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP550
-                           Printer, http://www.cups.org/str.php?L4155 */
-       { 0x04a9, 0x173e, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP560
-                           Printer, http://www.cups.org/str.php?L4155 */
-       { 0x04a9, 0x26a3, USBLP_QUIRK_NO_REATTACH }, /* Canon, Inc. MF4150
-                           Printer, https://bugs.launchpad.net/bugs/1160638 */
-       { 0x04f9, 0x001a, USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd
-                                                 HL-1430 Laser Printer,
-                                    https://bugs.launchpad.net/bugs/1038695 */
-       { 0x04f9, 0x000d, USBLP_QUIRK_BIDIR |
-                         USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd
-                                                 HL-1440 Laser Printer,
-                                    https://bugs.launchpad.net/bugs/1000253 */
-       { 0x04f9, 0x000e, USBLP_QUIRK_BIDIR |
-                         USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd
-                                                 HL-1450 Laser Printer,
-                                    https://bugs.launchpad.net/bugs/1000253 */
-       { 0x06bc, 0x000b, USBLP_QUIRK_NO_REATTACH }, /* Oki Data Corp.
-                                                 Okipage 14ex Printer,
-                                    https://bugs.launchpad.net/bugs/872483 */
-       { 0x06bc, 0x01c7, USBLP_QUIRK_NO_REATTACH }, /* Oki Data Corp. B410d,
-                                    https://bugs.launchpad.net/bugs/872483 */
-       { 0x04b8, 0x0001, USBLP_QUIRK_BIDIR |
-                         USBLP_QUIRK_NO_REATTACH }, /* Seiko Epson Corp. Stylus Color 740 / Photo 750,
-                                    http://bugs.debian.org/697970 */
-       { 0x04b8, 0x0005, USBLP_QUIRK_NO_REATTACH }, /* Seiko Epson Corp. Stylus Color 670,
-                                    https://bugs.launchpad.net/bugs/872483 */
-       { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt
-                                                     Printer M129C */
-       { 0x067b, 0x2305, USBLP_QUIRK_BIDIR |
-                         USBLP_QUIRK_NO_REATTACH |
-                         USBLP_QUIRK_RESET },
-       /* Prolific Technology, Inc. PL2305 Parallel Port
-          (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/987485 */
-       { 0x0924, 0x3ce9, USBLP_QUIRK_NO_REATTACH }, /* Xerox Phaser 3124
-                         https://bugzilla.redhat.com/show_bug.cgi?id=867392 */
-       { 0x0924, 0x4293, USBLP_QUIRK_NO_REATTACH }, /* Xerox WorkCentre 3210
-                                    https://bugs.launchpad.net/bugs/1102470 */
-       { 0x1a86, 0x7584, USBLP_QUIRK_NO_REATTACH }, /* QinHeng Electronics
-   CH340S (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/1000253 */
-       { 0x04e8, 0x0000, USBLP_QUIRK_RESET }, /* All Samsung devices,
-                                    https://bugs.launchpad.net/bugs/1032456 */
-       { 0x0a5f, 0x0000, USBLP_QUIRK_BIDIR }, /* All Zebra devices,
-                                    https://bugs.launchpad.net/bugs/1001028 */
-       /* Canon */
-       { 0x04a9, 0x304a, USBLP_QUIRK_BLACKLIST }, /* Canon CP-10 */
-       { 0x04a9, 0x3063, USBLP_QUIRK_BLACKLIST }, /* Canon CP-100 */
-       { 0x04a9, 0x307c, USBLP_QUIRK_BLACKLIST }, /* Canon CP-200 */
-       { 0x04a9, 0x307d, USBLP_QUIRK_BLACKLIST }, /* Canon CP-300 */
-       { 0x04a9, 0x30bd, USBLP_QUIRK_BLACKLIST }, /* Canon CP-220 */
-       { 0x04a9, 0x30be, USBLP_QUIRK_BLACKLIST }, /* Canon CP-330 */
-       { 0x04a9, 0x30f6, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP400 */
-       { 0x04a9, 0x310b, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP600 */
-       { 0x04a9, 0x3127, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP710 */
-       { 0x04a9, 0x3128, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP510 */
-       { 0x04a9, 0x3141, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES1 */
-       { 0x04a9, 0x3142, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP730 */
-       { 0x04a9, 0x3143, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP720 */
-       { 0x04a9, 0x3170, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP750 */
-       { 0x04a9, 0x3171, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP740 */
-       { 0x04a9, 0x3185, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES2 */
-       { 0x04a9, 0x3186, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES20 */
-       { 0x04a9, 0x31aa, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP770 */
-       { 0x04a9, 0x31ab, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP760 */
-       { 0x04a9, 0x31b0, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES30 */
-       { 0x04a9, 0x31dd, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP780 */
-       { 0x04a9, 0x31ee, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES40 */
-       { 0x04a9, 0x3214, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP800 */
-       { 0x04a9, 0x3255, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP900 */
-       { 0x04a9, 0x3256, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP810 */
-       { 0x04a9, 0x30F5, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP500 */
-       { 0x04a9, 0x31AF, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES3 */
-       { 0x04a9, 0x31DD, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP780 */
-        /* MISSING PIDs: CP520, CP530, CP790 */
-       { 0, 0 }
-};
 
 
 /*
  * Globals...
  */
 
+cups_array_t           *all_quirks;    /* Array of printer quirks */
 usb_globals_t          g = { 0 };      /* Globals */
 libusb_device           **list;         /* List of connected USB devices */
 
@@ -249,22 +149,24 @@ libusb_device           **list;         /* List of connected USB devices */
  */
 
 static int             close_device(usb_printer_t *printer);
+static int             compare_quirks(usb_quirk_t *a, usb_quirk_t *b);
 static usb_printer_t   *find_device(usb_cb_t cb, const void *data);
+static unsigned                find_quirks(int vendor_id, int product_id);
 static int             get_device_id(usb_printer_t *printer, char *buffer,
                                      size_t bufsize);
 static int             list_cb(usb_printer_t *printer, const char *device_uri,
                                const char *device_id, const void *data);
+static void            load_quirks(void);
 static char            *make_device_uri(usb_printer_t *printer,
                                         const char *device_id,
                                         char *uri, size_t uri_size);
 static int             open_device(usb_printer_t *printer, int verbose);
 static int             print_cb(usb_printer_t *printer, const char *device_uri,
                                 const char *device_id, const void *data);
-static int             printer_class_soft_reset(usb_printer_t *printer);
-static unsigned int    quirks(int vendor, int product);
 static void            *read_thread(void *reference);
 static void            *sidechannel_thread(void *reference);
 static void            soft_reset(void);
+static int             soft_reset_printer(usb_printer_t *printer);
 
 
 /*
@@ -341,9 +243,9 @@ print_device(const char *uri,               /* I - Device URI */
 
  /*
   * Some devices need a reset after finishing a job, these devices are
-  * marked with the USBLP_QUIRK_RESET quirk.
+  * marked with the USB_QUIRK_SOFT_RESET quirk.
   */
-  g.printer->reset_after_job = (g.printer->quirks & USBLP_QUIRK_RESET ? 1 : 0);
+  g.printer->reset_after_job = (g.printer->quirks & USB_QUIRK_SOFT_RESET ? 1 : 0);
 
  /*
   * If we are printing data from a print driver on stdin, ignore SIGTERM
@@ -879,6 +781,23 @@ close_device(usb_printer_t *printer)       /* I - Printer */
 }
 
 
+/*
+ * 'compare_quirks()' - Compare two quirks entries.
+ */
+
+static int                             /* O - Result of comparison */
+compare_quirks(usb_quirk_t *a,         /* I - First quirk entry */
+               usb_quirk_t *b)         /* I - Second quirk entry */
+{
+  int result;                          /* Result of comparison */
+
+  if ((result = b->vendor_id - a->vendor_id) == 0)
+    result = b->product_id - a->product_id;
+
+  return (result);
+}
+
+
 /*
  * 'find_device()' - Find or enumerate USB printers.
  */
@@ -951,13 +870,13 @@ find_device(usb_cb_t   cb,                /* I - Callback function */
           !devdesc.idProduct)
        continue;
 
-      printer.quirks = quirks(devdesc.idVendor, devdesc.idProduct);
+      printer.quirks = find_quirks(devdesc.idVendor, devdesc.idProduct);
 
      /*
       * Ignore blacklisted printers...
       */
 
-      if (printer.quirks & USBLP_QUIRK_BLACKLIST)
+      if (printer.quirks & USB_QUIRK_BLACKLIST)
         continue;
 
       for (conf = 0; conf < devdesc.bNumConfigurations; conf ++)
@@ -986,13 +905,13 @@ find_device(usb_cb_t   cb,                /* I - Callback function */
 
            if (((altptr->bInterfaceClass != LIBUSB_CLASS_PRINTER ||
                  altptr->bInterfaceSubClass != 1) &&
-                ((printer.quirks & USBLP_QUIRK_BAD_CLASS) == 0)) ||
+                ((printer.quirks & USB_QUIRK_VENDOR_CLASS) == 0)) ||
                (altptr->bInterfaceProtocol != 1 &&     /* Unidirectional */
                 altptr->bInterfaceProtocol != 2) ||    /* Bidirectional */
                altptr->bInterfaceProtocol < protocol)
              continue;
 
-           if (printer.quirks & USBLP_QUIRK_BAD_CLASS)
+           if (printer.quirks & USB_QUIRK_VENDOR_CLASS)
              fprintf(stderr, "DEBUG: Printer does not report class 7 and/or "
                      "subclass 1 but works as a printer anyway\n");
 
@@ -1049,7 +968,7 @@ find_device(usb_cb_t   cb,         /* I - Callback function */
              {
                fprintf(stderr, "DEBUG: Device protocol: %d\n",
                        printer.protocol);
-               if (printer.quirks & USBLP_QUIRK_BIDIR)
+               if (printer.quirks & USB_QUIRK_UNIDIR)
                {
                  printer.read_endp = -1;
                  fprintf(stderr, "DEBUG: Printer reports bi-di support "
@@ -1069,7 +988,7 @@ find_device(usb_cb_t   cb,         /* I - Callback function */
                                           altsetting[printer.altset].
                                           endpoint[printer.write_endp].
                                           bEndpointAddress;
-               if (printer.quirks & USBLP_QUIRK_NO_REATTACH)
+               if (printer.quirks & USB_QUIRK_NO_REATTACH)
                {
                  printer.usblp_attached = 0;
                  fprintf(stderr, "DEBUG: Printer does not like usblp "
@@ -1104,6 +1023,35 @@ find_device(usb_cb_t   cb,               /* I - Callback function */
 }
 
 
+/*
+ * 'find_quirks()' - Find the quirks for the given printer, if any.
+ *
+ * First looks for an exact match, then looks for the vendor ID wildcard match.
+ */
+
+static unsigned                                /* O - Quirks flags */
+find_quirks(int vendor_id,             /* I - Vendor ID */
+            int product_id)            /* I - Product ID */
+{
+  usb_quirk_t  key,                    /* Search key */
+               *match;                 /* Matching quirk entry */
+
+
+  key.vendor_id  = vendor_id;
+  key.product_id = product_id;
+
+  if ((match = cupsArrayFind(all_quirks, &key)) != NULL)
+    return (match->quirks);
+
+  key.product_id = 0;
+
+  if ((match = cupsArrayFind(all_quirks, &key)) != NULL)
+    return (match->quirks);
+
+  return (USB_QUIRK_WHITELIST);
+}
+
+
 /*
  * 'get_device_id()' - Get the IEEE-1284 device ID for the printer.
  */
@@ -1209,6 +1157,104 @@ list_cb(usb_printer_t *printer,         /* I - Printer */
 }
 
 
+/*
+ * 'load_quirks()' - Load all quirks files in the /usr/share/cups/usb directory.
+ */
+
+static void
+load_quirks(void)
+{
+  const char   *datadir;               /* CUPS_DATADIR environment variable */
+  char         filename[1024],         /* Filename */
+               line[1024];             /* Line from file */
+  cups_dir_t   *dir;                   /* Directory */
+  cups_dentry_t        *dent;                  /* Directory entry */
+  cups_file_t  *fp;                    /* Quirks file */
+  usb_quirk_t  *quirk;                 /* New quirk */
+
+
+  all_quirks = cupsArrayNew((cups_array_func_t)compare_quirks, NULL);
+
+  if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+    datadir = CUPS_DATADIR;
+
+  snprintf(filename, sizeof(filename), "%s/usb", datadir);
+  if ((dir = cupsDirOpen(filename)) == NULL)
+  {
+    perror(filename);
+    return;
+  }
+
+  fprintf(stderr, "DEBUG: Loading USB quirks from \"%s\".\n", filename);
+
+  while (dent = cupsDirRead(dir))
+  {
+    if (!S_ISREG(dent->fileinfo.st_mode))
+      continue;
+
+    snprintf(filename, sizeof(filename), "%s/usb/%s", datadir, dent->filename);
+    if ((fp = cupsFileOpen(filename, "r")) == NULL)
+    {
+      perror(filename);
+      continue;
+    }
+
+    while (cupsFileGets(fp, line, sizeof(line)))
+    {
+     /*
+      * Skip blank and comment lines...
+      */
+
+      if (line[0] == '#' || !line[0])
+        continue;
+
+     /*
+      * Add a quirk...
+      */
+
+      if ((quirk = calloc(1, sizeof(usb_quirk_t))) == NULL)
+      {
+        perror("DEBUG: Unable to allocate memory for quirk");
+        break;
+      }
+
+      if (sscanf(line, "%x%x", &quirk->vendor_id, &quirk->product_id) < 1)
+      {
+        fprintf(stderr, "DEBUG: Bad line: %s\n", line);
+        free(quirk);
+        continue;
+      }
+
+      if (strstr(line, " blacklist"))
+        quirk->quirks |= USB_QUIRK_BLACKLIST;
+
+      if (strstr(line, " no-reattach"))
+        quirk->quirks |= USB_QUIRK_NO_REATTACH;
+
+      if (strstr(line, " soft-reset"))
+        quirk->quirks |= USB_QUIRK_SOFT_RESET;
+
+      if (strstr(line, " unidir"))
+        quirk->quirks |= USB_QUIRK_UNIDIR;
+
+      if (strstr(line, " usb-init"))
+        quirk->quirks |= USB_QUIRK_USB_INIT;
+
+      if (strstr(line, " vendor-class"))
+        quirk->quirks |= USB_QUIRK_VENDOR_CLASS;
+
+      cupsArrayAdd(all_quirks, quirk);
+    }
+
+    cupsFileClose(fp);
+  }
+
+  fprintf(stderr, "DEBUG: Loaded %d quirks.\n", cupsArrayCount(all_quirks));
+
+  cupsDirClose(dir);
+}
+
+
 /*
  * 'make_device_uri()' - Create a device URI for a USB printer.
  */
@@ -1635,65 +1681,6 @@ print_cb(usb_printer_t *printer, /* I - Printer */
 }
 
 
-/*
- * 'printer_class_soft_reset()' - Do the soft reset request specific to printers
- *
- * This soft reset is specific to the printer device class and is much less
- * invasive than the general USB reset libusb_reset_device(). Especially it
- * does never happen that the USB addressing and configuration changes. What
- * is actually done is that all buffers get flushed and the bulk IN and OUT
- * pipes get reset to their default states. This clears all stall conditions.
- * See http://cholla.mmto.org/computers/linux/usb/usbprint11.pdf
- */
-
-static int                             /* O - 0 on success, < 0 on error */
-printer_class_soft_reset(usb_printer_t *printer) /* I - Printer */
-{
-  struct libusb_config_descriptor *confptr = NULL;
-                                        /* Pointer to current configuration */
-  int interface,
-      errcode;
-
-  if (libusb_get_config_descriptor(printer->device, printer->conf, &confptr)
-      < 0)
-    interface = printer->iface;
-  else
-    interface = confptr->interface[printer->iface].
-      altsetting[printer->altset].bInterfaceNumber;
-  libusb_free_config_descriptor(confptr);
-  if ((errcode = libusb_control_transfer(printer->handle,
-                                        LIBUSB_REQUEST_TYPE_CLASS |
-                                        LIBUSB_ENDPOINT_OUT |
-                                        LIBUSB_RECIPIENT_OTHER,
-                                        2, 0, interface, NULL, 0, 5000)) < 0)
-    errcode = libusb_control_transfer(printer->handle,
-                                     LIBUSB_REQUEST_TYPE_CLASS |
-                                     LIBUSB_ENDPOINT_OUT |
-                                     LIBUSB_RECIPIENT_INTERFACE,
-                                     2, 0, interface, NULL, 0, 5000);
-  return errcode;
-}
-
-
-/*
- * 'quirks()' - Get the known quirks of a given printer model
- */
-
-static unsigned int quirks(int vendor, int product)
-{
-  int i;
-
-  for (i = 0; quirk_printers[i].vendorId; i++)
-  {
-    if (vendor == quirk_printers[i].vendorId &&
-       (quirk_printers[i].productId == 0x0000 ||
-        product == quirk_printers[i].productId))
-      return quirk_printers[i].quirks;
-  }
-  return 0;
-}
-
-
 /*
  * 'read_thread()' - Thread to read the backchannel data on.
  */
@@ -1917,13 +1904,15 @@ sidechannel_thread(void *reference)
  * 'soft_reset()' - Send a soft reset to the device.
  */
 
-static void soft_reset(void)
+static void
+soft_reset(void)
 {
   fd_set         input_set;            /* Input set for select() */
   struct timeval  tv;                  /* Time value */
   char           buffer[2048];         /* Buffer */
   struct timespec cond_timeout;                /* pthread condition timeout */
 
+
  /*
   * Send an abort once a second until the I/O lock is released by the main
   * thread...
@@ -1968,7 +1957,7 @@ static void soft_reset(void)
   * Send the reset...
   */
 
-  printer_class_soft_reset(g.printer);
+  soft_reset_printer(g.printer);
 
  /*
   * Release the I/O lock...
@@ -1981,6 +1970,51 @@ static void soft_reset(void)
 }
 
 
+/*
+ * 'soft_reset_printer()' - Do the soft reset request specific to printers
+ *
+ * This soft reset is specific to the printer device class and is much less
+ * invasive than the general USB reset libusb_reset_device(). Especially it
+ * does never happen that the USB addressing and configuration changes. What
+ * is actually done is that all buffers get flushed and the bulk IN and OUT
+ * pipes get reset to their default states. This clears all stall conditions.
+ * See http://cholla.mmto.org/computers/linux/usb/usbprint11.pdf
+ */
+
+static int                             /* O - 0 on success, < 0 on error */
+soft_reset_printer(
+    usb_printer_t *printer)            /* I - Printer */
+{
+  struct libusb_config_descriptor *confptr = NULL;
+                                        /* Pointer to current configuration */
+  int interface,                       /* Interface to reset */
+      errcode;                         /* Error code */
+
+
+  if (libusb_get_config_descriptor(printer->device, printer->conf,
+                                   &confptr) < 0)
+    interface = printer->iface;
+  else
+    interface = confptr->interface[printer->iface].
+                         altsetting[printer->altset].bInterfaceNumber;
+
+  libusb_free_config_descriptor(confptr);
+
+  if ((errcode = libusb_control_transfer(printer->handle,
+                                        LIBUSB_REQUEST_TYPE_CLASS |
+                                        LIBUSB_ENDPOINT_OUT |
+                                        LIBUSB_RECIPIENT_OTHER,
+                                        2, 0, interface, NULL, 0, 5000)) < 0)
+    errcode = libusb_control_transfer(printer->handle,
+                                     LIBUSB_REQUEST_TYPE_CLASS |
+                                     LIBUSB_ENDPOINT_OUT |
+                                     LIBUSB_RECIPIENT_INTERFACE,
+                                     2, 0, interface, NULL, 0, 5000);
+
+  return (errcode);
+}
+
+
 /*
  * End of "$Id$".
  */
index e93300615b0750213ae3bb0ebb4a48cfa49c474b..af1b8f1052d29b534258c725f520bc71f3cb67c7 100644 (file)
@@ -225,7 +225,9 @@ dnl See if we have libusb...
 AC_ARG_ENABLE(libusb, [  --enable-libusb         use libusb for USB printing])
 
 LIBUSB=""
+USBQUIRKS=""
 AC_SUBST(LIBUSB)
+AC_SUBST(USBQUIRKS)
 
 if test "x$PKGCONFIG" != x; then
        if test x$enable_libusb = xyes -o $uname != Darwin; then
@@ -235,6 +237,7 @@ if test "x$PKGCONFIG" != x; then
                        AC_DEFINE(HAVE_LIBUSB)
                        CFLAGS="$CFLAGS `$PKGCONFIG --cflags libusb-1.0`"
                        LIBUSB="`$PKGCONFIG --libs libusb-1.0`"
+                       USBQUIRKS="\$(DATADIR)/usb"
                else
                        AC_MSG_RESULT(no)
                fi
index 70535f116c7fb8a922ca07288d7a796d08b35a26..6059db6b4b8e957e69844cf571eea640a50d7bee 100644 (file)
@@ -5,7 +5,7 @@
 #
 #   Original version by Jason McMullan <jmcc@ontv.com>.
 #
-#   Copyright 2007-2012 by Apple Inc.
+#   Copyright 2007-2013 by Apple Inc.
 #   Copyright 1999-2007 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -222,6 +222,9 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/cups/ppdc/*
 %dir /usr/share/cups/templates
 /usr/share/cups/templates/*
+%dir /usr/share/cups/usb
+/usr/share/cups/usb/*
+
 %dir /usr/share/doc/cups
 /usr/share/doc/cups/*.*
 %dir /usr/share/doc/cups/help