4
SERVERROOT = $(BUILDROOT)@CUPS_SERVERROOT@
5
SMFMANIFESTDIR = @SMFMANIFESTDIR@
6
STATEDIR = $(BUILDROOT)@CUPS_STATEDIR@
7
+USBQUIRKS = @USBQUIRKS@
11
--- a/backend/Makefile
12
+++ b/backend/Makefile
17
+ if test "x$(USBQUIRKS)" != x; then \
18
+ echo Installing USB quirks in $(USBQUIRKS); \
19
+ $(INSTALL_DIR) -m 755 $(USBQUIRKS); \
20
+ $(INSTALL_DATA) org.cups.usb-quirks $(USBQUIRKS); \
28
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
29
"requesting-user-name", NULL, argv[2]);
31
- if ((i + 1) >= num_files)
32
- ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
33
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document",
34
+ (i + 1) >= num_files);
37
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
39
+++ b/backend/org.cups.usb-quirks
41
+# USB backend 'quirks' file.
43
+# This file lists known issues with various vendors or printers. Each
44
+# line contains either a comment (starting with #) or the USB vendor ID,
45
+# product ID (omit for all vendor products), and a list of known issues:
47
+# blacklist The printer is not functional with the USB backend.
48
+# no-reattach Do no re-attach usblp kernel module after printing.
49
+# soft-reset Do a soft reset after printing for cleanup.
50
+# unidir Only supported unidirectional I/O
51
+# usb-init Needs vendor USB initialization string.
52
+# vendor-class Uses vendor-specific class or subclass.
53
+# whitelist The printer is functional with the USB backend.
64
+# HP DeskJet 810C/812C
82
+# NEC Picty900 (HP OEM)
85
+# NEC Picty760 (HP OEM)
88
+# NEC Picty920 (HP OEM)
91
+# NEC Picty800 (HP OEM)
94
+# Lexmark International, Inc. (e250d), https://bugs.launchpad.net/bugs/1084164
95
+0x043d 0x00f3 no-reattach
97
+# Kyocera Mita FS 820, by zut <kernel@zut.de>
100
+# Canon, Inc. PIXMA iP6000D Printer, https://bugs.launchpad.net/bugs/1160638
101
+0x04a9 0x1095 unidir
103
+# Canon, Inc. PIXMA iP4200 Printer, http://www.cups.org/str.php?L4155
104
+0x04a9 0x10a2 unidir
106
+# Canon, Inc. PIXMA iP4300 Printer, https://bugs.launchpad.net/bugs/1032385
107
+0x04a9 0x10b6 unidir
109
+# Canon, Inc. MP210 https://bugzilla.redhat.com/show_bug.cgi?id=847923#c53
110
+0x04a9 0x1721 unidir
112
+# Canon, Inc. MP500 Printer, https://bugs.launchpad.net/bugs/1032456
113
+0x04a9 0x170c unidir
115
+# Canon, Inc. MP510 Printer, https://bugs.launchpad.net/bugs/1050009
116
+0x04a9 0x1717 unidir
118
+# Canon, Inc. MP550 Printer, http://www.cups.org/str.php?L4155
119
+0x04a9 0x173d unidir
121
+# Canon, Inc. MP560 Printer, http://www.cups.org/str.php?L4155
122
+0x04a9 0x173e unidir
124
+# Canon, Inc. MF4150 Printer, https://bugs.launchpad.net/bugs/1160638
125
+0x04a9 0x26a3 no-reattach
127
+# Brother Industries, Ltd HL-1430 Laser Printer, https://bugs.launchpad.net/bugs/1038695
128
+0x04f9 0x001a no-reattach
130
+# Brother Industries, Ltd HL-1440 Laser Printer, https://bugs.launchpad.net/bugs/1000253
131
+0x04f9 0x000d no-reattach unidir
133
+# Brother Industries, Ltd HL-1450 Laser Printer, https://bugs.launchpad.net/bugs/1000253
134
+0x04f9 0x000e no-reattach unidir
136
+# Oki Data Corp. Okipage 14ex Printer, https://bugs.launchpad.net/bugs/872483
137
+0x06bc 0x000b no-reattach
139
+# Oki Data Corp. B410d, https://bugs.launchpad.net/bugs/872483
140
+0x06bc 0x01c7 no-reattach
142
+# Seiko Epson Corp. Stylus Color 740 / Photo 750, http://bugs.debian.org/697970
143
+0x04b8 0x0001 no-reattach unidir
145
+# Seiko Epson Corp. Stylus Color 670, https://bugs.launchpad.net/bugs/872483
146
+0x04b8 0x0005 no-reattach
148
+# Seiko Epson Receipt Printer M129C
149
+0x04b8 0x0202 vendor-class
151
+# Prolific Technology, Inc. PL2305 Parallel Port (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/987485
152
+0x067b 0x2305 no-reattach soft-reset unidir
154
+# Xerox Phaser 3124 https://bugzilla.redhat.com/show_bug.cgi?id=867392
155
+0x0924 0x3ce9 no-reattach
157
+# Xerox WorkCentre 3210 https://bugs.launchpad.net/bugs/1102470
158
+0x0924 0x4293 no-reattach
160
+# QinHeng Electronics CH340S (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/1000253
161
+0x1a86 0x7584 no-reattach
163
+# All Samsung devices, https://bugs.launchpad.net/bugs/1032456
166
+# All Zebra devices, https://bugs.launchpad.net/bugs/1001028
170
+0x04a9 0x304a blacklist
173
+0x04a9 0x3063 blacklist
176
+0x04a9 0x307c blacklist
179
+0x04a9 0x307d blacklist
182
+0x04a9 0x30bd blacklist
185
+0x04a9 0x30be blacklist
187
+# Canon SELPHY CP400
188
+0x04a9 0x30f6 blacklist
190
+# Canon SELPHY CP600
191
+0x04a9 0x310b blacklist
193
+# Canon SELPHY CP710
194
+0x04a9 0x3127 blacklist
196
+# Canon SELPHY CP510
197
+0x04a9 0x3128 blacklist
200
+0x04a9 0x3141 blacklist
202
+# Canon SELPHY CP730
203
+0x04a9 0x3142 blacklist
205
+# Canon SELPHY CP720
206
+0x04a9 0x3143 blacklist
208
+# Canon SELPHY CP750
209
+0x04a9 0x3170 blacklist
211
+# Canon SELPHY CP740
212
+0x04a9 0x3171 blacklist
215
+0x04a9 0x3185 blacklist
218
+0x04a9 0x3186 blacklist
220
+# Canon SELPHY CP770
221
+0x04a9 0x31aa blacklist
223
+# Canon SELPHY CP760
224
+0x04a9 0x31ab blacklist
227
+0x04a9 0x31b0 blacklist
229
+# Canon SELPHY CP780
230
+0x04a9 0x31dd blacklist
233
+0x04a9 0x31ee blacklist
235
+# Canon SELPHY CP800
236
+0x04a9 0x3214 blacklist
238
+# Canon SELPHY CP900
239
+0x04a9 0x3255 blacklist
241
+# Canon SELPHY CP810
242
+0x04a9 0x3256 blacklist
244
+# Canon SELPHY CP500
245
+0x04a9 0x30f5 blacklist
248
+0x04a9 0x31af blacklist
250
+# Canon SELPHY CP780
251
+0x04a9 0x31dd blacklist
253
+# Lexmark E238 (<rdar://problem/14493054>)
254
+0x043d 0x00d7 no-reattach
255
--- a/backend/usb-libusb.c
256
+++ b/backend/usb-libusb.c
258
* list_devices() - List the available printers.
259
* print_device() - Print a file to a USB device.
260
* close_device() - Close the connection to the USB printer.
261
+ * compare_quirks() - Compare two quirks entries.
262
* find_device() - Find or enumerate USB printers.
263
+ * find_quirks() - Find the quirks for the given printer, if any.
264
* get_device_id() - Get the IEEE-1284 device ID for the printer.
265
* list_cb() - List USB printers for discovery.
266
+ * load_quirks() - Load all quirks files in the /usr/share/cups/usb
268
* make_device_uri() - Create a device URI for a USB printer.
269
* open_device() - Open a connection to the USB printer.
270
* print_cb() - Find a USB printer for printing.
271
- * printer_class_soft_reset()' - Do the soft reset request specific to
273
- * quirks() - Get the known quirks of a given printer model
274
* read_thread() - Thread to read the backchannel data on.
275
* sidechannel_thread() - Handle side-channel requests.
276
* soft_reset() - Send a soft reset to the device.
277
+ * soft_reset_printer() - Do the soft reset request specific to printers
284
#include <cups/cups-private.h>
285
+#include <cups/dir.h>
287
#include <sys/select.h>
288
#include <sys/types.h>
290
read_endp, /* Read endpoint */
291
protocol, /* Protocol: 1 = Uni-di, 2 = Bi-di. */
292
usblp_attached, /* "usblp" kernel module attached? */
293
- reset_after_job; /* Set to 1 by print_device() */
294
- unsigned int quirks; /* Quirks flags */
295
+ reset_after_job;/* Set to 1 by print_device() */
296
+ unsigned quirks; /* Quirks flags */
297
struct libusb_device_handle *handle; /* Open handle to device */
300
typedef int (*usb_cb_t)(usb_printer_t *, const char *, const char *,
303
-typedef struct usb_globals_s
304
+typedef struct usb_globals_s /* Global USB printer information */
306
usb_printer_t *printer; /* Printer */
308
@@ -105,143 +108,41 @@
312
- * Quirks: various printer quirks are handled by this table & its flags.
313
+ * Quirks: various printer quirks are handled by this structure and its flags.
315
- * This is copied from the usblp kernel module. So we can easily copy and paste
316
- * new quirks from the module.
317
+ * The quirks table used to be compiled into the backend but is now loaded from
318
+ * one or more files in the /usr/share/cups/usb directory.
321
-struct quirk_printer_struct {
324
- unsigned int quirks;
327
-#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires
328
- unidirectional mode (no INs/reads) */
329
-#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
330
-#define USBLP_QUIRK_BAD_CLASS 0x4 /* descriptor uses vendor-specific
331
- Class or SubClass */
332
-#define USBLP_QUIRK_BLACKLIST 0x8 /* these printers do not conform to the USB print spec */
333
-#define USBLP_QUIRK_RESET 0x4000 /* After printing do a reset
335
-#define USBLP_QUIRK_NO_REATTACH 0x8000 /* After printing we cannot re-attach
336
+#define USB_QUIRK_BLACKLIST 0x0001 /* Does not conform to the spec */
337
+#define USB_QUIRK_NO_REATTACH 0x0002 /* After printing we cannot re-attach
338
the usblp kernel module */
339
+#define USB_QUIRK_SOFT_RESET 0x0004 /* After printing do a soft reset
341
+#define USB_QUIRK_UNIDIR 0x0008 /* Requires unidirectional mode */
342
+#define USB_QUIRK_USB_INIT 0x0010 /* Needs vendor USB init string */
343
+#define USB_QUIRK_VENDOR_CLASS 0x0020 /* Descriptor uses vendor-specific
344
+ Class or SubClass */
345
+#define USB_QUIRK_WHITELIST 0x0000 /* no quirks */
348
+typedef struct usb_quirk_s /* USB "quirk" information */
350
+ int vendor_id, /* Affected vendor ID */
351
+ product_id; /* Affected product ID or 0 for all */
352
+ unsigned quirks; /* Quirks bitfield */
356
-static const struct quirk_printer_struct quirk_printers[] = {
357
- { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
358
- { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
359
- { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
360
- { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
361
- { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
362
- { 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */
363
- { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */
364
- { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */
365
- { 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */
366
- { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
367
- { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
368
- { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
369
- { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
370
- { 0x043d, 0x00f3, USBLP_QUIRK_NO_REATTACH }, /* Lexmark International,
371
- Inc. (e250d), https://bugs.launchpad.net/bugs/1084164 */
372
- { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820,
373
- by zut <kernel@zut.de> */
374
- { 0x04a9, 0x1095, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP6000D
375
- Printer, https://bugs.launchpad.net/bugs/1160638 */
376
- { 0x04a9, 0x10a2, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP4200
377
- Printer, http://www.cups.org/str.php?L4155 */
378
- { 0x04a9, 0x10b6, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP4300
379
- Printer, https://bugs.launchpad.net/bugs/1032385 */
380
- { 0x04a9, 0x1721, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP210
381
- https://bugzilla.redhat.com/show_bug.cgi?id=847923#c53 */
382
- { 0x04a9, 0x170c, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP500
383
- Printer, https://bugs.launchpad.net/bugs/1032456 */
384
- { 0x04a9, 0x1717, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP510
385
- Printer, https://bugs.launchpad.net/bugs/1050009 */
386
- { 0x04a9, 0x173d, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP550
387
- Printer, http://www.cups.org/str.php?L4155 */
388
- { 0x04a9, 0x173e, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP560
389
- Printer, http://www.cups.org/str.php?L4155 */
390
- { 0x04a9, 0x26a3, USBLP_QUIRK_NO_REATTACH }, /* Canon, Inc. MF4150
391
- Printer, https://bugs.launchpad.net/bugs/1160638 */
392
- { 0x04f9, 0x001a, USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd
393
- HL-1430 Laser Printer,
394
- https://bugs.launchpad.net/bugs/1038695 */
395
- { 0x04f9, 0x000d, USBLP_QUIRK_BIDIR |
396
- USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd
397
- HL-1440 Laser Printer,
398
- https://bugs.launchpad.net/bugs/1000253 */
399
- { 0x04f9, 0x000e, USBLP_QUIRK_BIDIR |
400
- USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd
401
- HL-1450 Laser Printer,
402
- https://bugs.launchpad.net/bugs/1000253 */
403
- { 0x06bc, 0x000b, USBLP_QUIRK_NO_REATTACH }, /* Oki Data Corp.
404
- Okipage 14ex Printer,
405
- https://bugs.launchpad.net/bugs/872483 */
406
- { 0x06bc, 0x01c7, USBLP_QUIRK_NO_REATTACH }, /* Oki Data Corp. B410d,
407
- https://bugs.launchpad.net/bugs/872483 */
408
- { 0x04b8, 0x0001, USBLP_QUIRK_BIDIR |
409
- USBLP_QUIRK_NO_REATTACH }, /* Seiko Epson Corp. Stylus Color 740 / Photo 750,
410
- http://bugs.debian.org/697970 */
411
- { 0x04b8, 0x0005, USBLP_QUIRK_NO_REATTACH }, /* Seiko Epson Corp. Stylus Color 670,
412
- https://bugs.launchpad.net/bugs/872483 */
413
- { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt
415
- { 0x067b, 0x2305, USBLP_QUIRK_BIDIR |
416
- USBLP_QUIRK_NO_REATTACH |
417
- USBLP_QUIRK_RESET },
418
- /* Prolific Technology, Inc. PL2305 Parallel Port
419
- (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/987485 */
420
- { 0x0924, 0x3ce9, USBLP_QUIRK_NO_REATTACH }, /* Xerox Phaser 3124
421
- https://bugzilla.redhat.com/show_bug.cgi?id=867392 */
422
- { 0x0924, 0x4293, USBLP_QUIRK_NO_REATTACH }, /* Xerox WorkCentre 3210
423
- https://bugs.launchpad.net/bugs/1102470 */
424
- { 0x1a86, 0x7584, USBLP_QUIRK_NO_REATTACH }, /* QinHeng Electronics
425
- CH340S (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/1000253 */
426
- { 0x04e8, 0x0000, USBLP_QUIRK_RESET }, /* All Samsung devices,
427
- https://bugs.launchpad.net/bugs/1032456 */
428
- { 0x0a5f, 0x0000, USBLP_QUIRK_BIDIR }, /* All Zebra devices,
429
- https://bugs.launchpad.net/bugs/1001028 */
431
- { 0x04a9, 0x304a, USBLP_QUIRK_BLACKLIST }, /* Canon CP-10 */
432
- { 0x04a9, 0x3063, USBLP_QUIRK_BLACKLIST }, /* Canon CP-100 */
433
- { 0x04a9, 0x307c, USBLP_QUIRK_BLACKLIST }, /* Canon CP-200 */
434
- { 0x04a9, 0x307d, USBLP_QUIRK_BLACKLIST }, /* Canon CP-300 */
435
- { 0x04a9, 0x30bd, USBLP_QUIRK_BLACKLIST }, /* Canon CP-220 */
436
- { 0x04a9, 0x30be, USBLP_QUIRK_BLACKLIST }, /* Canon CP-330 */
437
- { 0x04a9, 0x30f6, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP400 */
438
- { 0x04a9, 0x310b, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP600 */
439
- { 0x04a9, 0x3127, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP710 */
440
- { 0x04a9, 0x3128, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP510 */
441
- { 0x04a9, 0x3141, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES1 */
442
- { 0x04a9, 0x3142, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP730 */
443
- { 0x04a9, 0x3143, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP720 */
444
- { 0x04a9, 0x3170, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP750 */
445
- { 0x04a9, 0x3171, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP740 */
446
- { 0x04a9, 0x3185, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES2 */
447
- { 0x04a9, 0x3186, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES20 */
448
- { 0x04a9, 0x31aa, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP770 */
449
- { 0x04a9, 0x31ab, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP760 */
450
- { 0x04a9, 0x31b0, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES30 */
451
- { 0x04a9, 0x31dd, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP780 */
452
- { 0x04a9, 0x31ee, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES40 */
453
- { 0x04a9, 0x3214, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP800 */
454
- { 0x04a9, 0x3255, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP900 */
455
- { 0x04a9, 0x3256, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP810 */
456
- { 0x04a9, 0x30F5, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP500 */
457
- { 0x04a9, 0x31AF, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY ES3 */
458
- { 0x04a9, 0x31DD, USBLP_QUIRK_BLACKLIST }, /* Canon SELPHY CP780 */
459
- /* MISSING PIDs: CP520, CP530, CP790 */
468
+cups_array_t *all_quirks; /* Array of printer quirks */
469
usb_globals_t g = { 0 }; /* Globals */
470
-libusb_device **list; /* List of connected USB devices */
471
+libusb_device **all_list; /* List of connected USB devices */
475
@@ -249,22 +150,24 @@
478
static int close_device(usb_printer_t *printer);
479
+static int compare_quirks(usb_quirk_t *a, usb_quirk_t *b);
480
static usb_printer_t *find_device(usb_cb_t cb, const void *data);
481
+static unsigned find_quirks(int vendor_id, int product_id);
482
static int get_device_id(usb_printer_t *printer, char *buffer,
484
static int list_cb(usb_printer_t *printer, const char *device_uri,
485
const char *device_id, const void *data);
486
+static void load_quirks(void);
487
static char *make_device_uri(usb_printer_t *printer,
488
const char *device_id,
489
char *uri, size_t uri_size);
490
static int open_device(usb_printer_t *printer, int verbose);
491
static int print_cb(usb_printer_t *printer, const char *device_uri,
492
const char *device_id, const void *data);
493
-static int printer_class_soft_reset(usb_printer_t *printer);
494
-static unsigned int quirks(int vendor, int product);
495
static void *read_thread(void *reference);
496
static void *sidechannel_thread(void *reference);
497
static void soft_reset(void);
498
+static int soft_reset_printer(usb_printer_t *printer);
508
fputs("DEBUG: list_devices\n", stderr);
509
find_device(list_cb, NULL);
512
const char *val; /* Option value */
518
* See if the side-channel descriptor is valid...
523
* Some devices need a reset after finishing a job, these devices are
524
- * marked with the USBLP_QUIRK_RESET quirk.
525
+ * marked with the USB_QUIRK_SOFT_RESET quirk.
527
- g.printer->reset_after_job = (g.printer->quirks & USBLP_QUIRK_RESET ? 1 : 0);
528
+ g.printer->reset_after_job = (g.printer->quirks & USB_QUIRK_SOFT_RESET ? 1 : 0);
531
* If we are printing data from a print driver on stdin, ignore SIGTERM
536
- libusb_free_device_list(list, 1);
537
+ libusb_free_device_list(all_list, 1);
545
+ * 'compare_quirks()' - Compare two quirks entries.
548
+static int /* O - Result of comparison */
549
+compare_quirks(usb_quirk_t *a, /* I - First quirk entry */
550
+ usb_quirk_t *b) /* I - Second quirk entry */
552
+ int result; /* Result of comparison */
554
+ if ((result = b->vendor_id - a->vendor_id) == 0)
555
+ result = b->product_id - a->product_id;
562
* 'find_device()' - Find or enumerate USB printers.
568
fprintf(stderr, "DEBUG: Unable to initialize USB access via libusb, "
569
- "libusb error %i\n", err);
570
+ "libusb error %i\n", (int)err);
574
@@ -951,13 +875,13 @@
578
- printer.quirks = quirks(devdesc.idVendor, devdesc.idProduct);
579
+ printer.quirks = find_quirks(devdesc.idVendor, devdesc.idProduct);
582
* Ignore blacklisted printers...
585
- if (printer.quirks & USBLP_QUIRK_BLACKLIST)
586
+ if (printer.quirks & USB_QUIRK_BLACKLIST)
589
for (conf = 0; conf < devdesc.bNumConfigurations; conf ++)
590
@@ -986,13 +910,13 @@
592
if (((altptr->bInterfaceClass != LIBUSB_CLASS_PRINTER ||
593
altptr->bInterfaceSubClass != 1) &&
594
- ((printer.quirks & USBLP_QUIRK_BAD_CLASS) == 0)) ||
595
+ ((printer.quirks & USB_QUIRK_VENDOR_CLASS) == 0)) ||
596
(altptr->bInterfaceProtocol != 1 && /* Unidirectional */
597
altptr->bInterfaceProtocol != 2) || /* Bidirectional */
598
altptr->bInterfaceProtocol < protocol)
601
- if (printer.quirks & USBLP_QUIRK_BAD_CLASS)
602
+ if (printer.quirks & USB_QUIRK_VENDOR_CLASS)
603
fprintf(stderr, "DEBUG: Printer does not report class 7 and/or "
604
"subclass 1 but works as a printer anyway\n");
608
fprintf(stderr, "DEBUG: Device protocol: %d\n",
610
- if (printer.quirks & USBLP_QUIRK_BIDIR)
611
+ if (printer.quirks & USB_QUIRK_UNIDIR)
613
printer.read_endp = -1;
614
fprintf(stderr, "DEBUG: Printer reports bi-di support "
616
altsetting[printer.altset].
617
endpoint[printer.write_endp].
619
- if (printer.quirks & USBLP_QUIRK_NO_REATTACH)
620
+ if (printer.quirks & USB_QUIRK_NO_REATTACH)
622
printer.usblp_attached = 0;
623
fprintf(stderr, "DEBUG: Printer does not like usblp "
624
@@ -1105,6 +1029,35 @@
628
+ * 'find_quirks()' - Find the quirks for the given printer, if any.
630
+ * First looks for an exact match, then looks for the vendor ID wildcard match.
633
+static unsigned /* O - Quirks flags */
634
+find_quirks(int vendor_id, /* I - Vendor ID */
635
+ int product_id) /* I - Product ID */
637
+ usb_quirk_t key, /* Search key */
638
+ *match; /* Matching quirk entry */
641
+ key.vendor_id = vendor_id;
642
+ key.product_id = product_id;
644
+ if ((match = cupsArrayFind(all_quirks, &key)) != NULL)
645
+ return (match->quirks);
647
+ key.product_id = 0;
649
+ if ((match = cupsArrayFind(all_quirks, &key)) != NULL)
650
+ return (match->quirks);
652
+ return (USB_QUIRK_WHITELIST);
657
* 'get_device_id()' - Get the IEEE-1284 device ID for the printer.
660
@@ -1210,6 +1163,104 @@
664
+ * 'load_quirks()' - Load all quirks files in the /usr/share/cups/usb directory.
670
+ const char *datadir; /* CUPS_DATADIR environment variable */
671
+ char filename[1024], /* Filename */
672
+ line[1024]; /* Line from file */
673
+ cups_dir_t *dir; /* Directory */
674
+ cups_dentry_t *dent; /* Directory entry */
675
+ cups_file_t *fp; /* Quirks file */
676
+ usb_quirk_t *quirk; /* New quirk */
679
+ all_quirks = cupsArrayNew((cups_array_func_t)compare_quirks, NULL);
681
+ if ((datadir = getenv("CUPS_DATADIR")) == NULL)
682
+ datadir = CUPS_DATADIR;
684
+ snprintf(filename, sizeof(filename), "%s/usb", datadir);
685
+ if ((dir = cupsDirOpen(filename)) == NULL)
691
+ fprintf(stderr, "DEBUG: Loading USB quirks from \"%s\".\n", filename);
693
+ while ((dent = cupsDirRead(dir)) != NULL)
695
+ if (!S_ISREG(dent->fileinfo.st_mode))
698
+ snprintf(filename, sizeof(filename), "%s/usb/%s", datadir, dent->filename);
699
+ if ((fp = cupsFileOpen(filename, "r")) == NULL)
705
+ while (cupsFileGets(fp, line, sizeof(line)))
708
+ * Skip blank and comment lines...
711
+ if (line[0] == '#' || !line[0])
718
+ if ((quirk = calloc(1, sizeof(usb_quirk_t))) == NULL)
720
+ perror("DEBUG: Unable to allocate memory for quirk");
724
+ if (sscanf(line, "%x%x", &quirk->vendor_id, &quirk->product_id) < 1)
726
+ fprintf(stderr, "DEBUG: Bad line: %s\n", line);
731
+ if (strstr(line, " blacklist"))
732
+ quirk->quirks |= USB_QUIRK_BLACKLIST;
734
+ if (strstr(line, " no-reattach"))
735
+ quirk->quirks |= USB_QUIRK_NO_REATTACH;
737
+ if (strstr(line, " soft-reset"))
738
+ quirk->quirks |= USB_QUIRK_SOFT_RESET;
740
+ if (strstr(line, " unidir"))
741
+ quirk->quirks |= USB_QUIRK_UNIDIR;
743
+ if (strstr(line, " usb-init"))
744
+ quirk->quirks |= USB_QUIRK_USB_INIT;
746
+ if (strstr(line, " vendor-class"))
747
+ quirk->quirks |= USB_QUIRK_VENDOR_CLASS;
749
+ cupsArrayAdd(all_quirks, quirk);
755
+ fprintf(stderr, "DEBUG: Loaded %d quirks.\n", cupsArrayCount(all_quirks));
762
* 'make_device_uri()' - Create a device URI for a USB printer.
765
@@ -1636,65 +1687,6 @@
769
- * 'printer_class_soft_reset()' - Do the soft reset request specific to printers
771
- * This soft reset is specific to the printer device class and is much less
772
- * invasive than the general USB reset libusb_reset_device(). Especially it
773
- * does never happen that the USB addressing and configuration changes. What
774
- * is actually done is that all buffers get flushed and the bulk IN and OUT
775
- * pipes get reset to their default states. This clears all stall conditions.
776
- * See http://cholla.mmto.org/computers/linux/usb/usbprint11.pdf
779
-static int /* O - 0 on success, < 0 on error */
780
-printer_class_soft_reset(usb_printer_t *printer) /* I - Printer */
782
- struct libusb_config_descriptor *confptr = NULL;
783
- /* Pointer to current configuration */
787
- if (libusb_get_config_descriptor(printer->device, printer->conf, &confptr)
789
- interface = printer->iface;
791
- interface = confptr->interface[printer->iface].
792
- altsetting[printer->altset].bInterfaceNumber;
793
- libusb_free_config_descriptor(confptr);
794
- if ((errcode = libusb_control_transfer(printer->handle,
795
- LIBUSB_REQUEST_TYPE_CLASS |
796
- LIBUSB_ENDPOINT_OUT |
797
- LIBUSB_RECIPIENT_OTHER,
798
- 2, 0, interface, NULL, 0, 5000)) < 0)
799
- errcode = libusb_control_transfer(printer->handle,
800
- LIBUSB_REQUEST_TYPE_CLASS |
801
- LIBUSB_ENDPOINT_OUT |
802
- LIBUSB_RECIPIENT_INTERFACE,
803
- 2, 0, interface, NULL, 0, 5000);
809
- * 'quirks()' - Get the known quirks of a given printer model
812
-static unsigned int quirks(int vendor, int product)
816
- for (i = 0; quirk_printers[i].vendorId; i++)
818
- if (vendor == quirk_printers[i].vendorId &&
819
- (quirk_printers[i].productId == 0x0000 ||
820
- product == quirk_printers[i].productId))
821
- return quirk_printers[i].quirks;
828
* 'read_thread()' - Thread to read the backchannel data on.
831
@@ -1917,13 +1909,15 @@
832
* 'soft_reset()' - Send a soft reset to the device.
835
-static void soft_reset(void)
839
fd_set input_set; /* Input set for select() */
840
struct timeval tv; /* Time value */
841
char buffer[2048]; /* Buffer */
842
struct timespec cond_timeout; /* pthread condition timeout */
846
* Send an abort once a second until the I/O lock is released by the main
848
@@ -1968,7 +1962,7 @@
852
- printer_class_soft_reset(g.printer);
853
+ soft_reset_printer(g.printer);
856
* Release the I/O lock...
857
@@ -1981,6 +1975,51 @@
862
+ * 'soft_reset_printer()' - Do the soft reset request specific to printers
864
+ * This soft reset is specific to the printer device class and is much less
865
+ * invasive than the general USB reset libusb_reset_device(). Especially it
866
+ * does never happen that the USB addressing and configuration changes. What
867
+ * is actually done is that all buffers get flushed and the bulk IN and OUT
868
+ * pipes get reset to their default states. This clears all stall conditions.
869
+ * See http://cholla.mmto.org/computers/linux/usb/usbprint11.pdf
872
+static int /* O - 0 on success, < 0 on error */
874
+ usb_printer_t *printer) /* I - Printer */
876
+ struct libusb_config_descriptor *confptr = NULL;
877
+ /* Pointer to current configuration */
878
+ int interface, /* Interface to reset */
879
+ errcode; /* Error code */
882
+ if (libusb_get_config_descriptor(printer->device, printer->conf,
884
+ interface = printer->iface;
886
+ interface = confptr->interface[printer->iface].
887
+ altsetting[printer->altset].bInterfaceNumber;
889
+ libusb_free_config_descriptor(confptr);
891
+ if ((errcode = libusb_control_transfer(printer->handle,
892
+ LIBUSB_REQUEST_TYPE_CLASS |
893
+ LIBUSB_ENDPOINT_OUT |
894
+ LIBUSB_RECIPIENT_OTHER,
895
+ 2, 0, interface, NULL, 0, 5000)) < 0)
896
+ errcode = libusb_control_transfer(printer->handle,
897
+ LIBUSB_REQUEST_TYPE_CLASS |
898
+ LIBUSB_ENDPOINT_OUT |
899
+ LIBUSB_RECIPIENT_INTERFACE,
900
+ 2, 0, interface, NULL, 0, 5000);
907
* End of "$Id: usb-libusb.c 10977 2013-05-13 16:46:08Z msweet $".
909
--- a/conf/cups-files.conf.in
910
+++ b/conf/cups-files.conf.in
912
# List of events that are considered fatal errors for the scheduler...
913
#FatalErrors @CUPS_FATAL_ERRORS@
915
+# Do we call fsync() after writing configuration or status files?
918
# Default user and group for filters/backends/helper programs; this cannot be
919
# any user or group that resolves to ID 0 for security reasons...
921
--- a/config-scripts/cups-common.m4
922
+++ b/config-scripts/cups-common.m4
924
AC_ARG_ENABLE(libusb, [ --enable-libusb use libusb for USB printing])
931
if test "x$PKGCONFIG" != x; then
932
if test x$enable_libusb = xyes -o $uname != Darwin; then
934
AC_DEFINE(HAVE_LIBUSB)
935
CFLAGS="$CFLAGS `$PKGCONFIG --cflags libusb-1.0`"
936
LIBUSB="`$PKGCONFIG --libs libusb-1.0`"
937
+ USBQUIRKS="\$(DATADIR)/usb"
951
@@ -5232,6 +5233,8 @@
959
if test "x$PKGCONFIG" != x; then
960
@@ -5245,6 +5248,7 @@
962
CFLAGS="$CFLAGS `$PKGCONFIG --cflags libusb-1.0`"
963
LIBUSB="`$PKGCONFIG --libs libusb-1.0`"
964
+ USBQUIRKS="\$(DATADIR)/usb"
966
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
968
--- a/cups/pwg-media.c
969
+++ b/cups/pwg-media.c
970
@@ -233,13 +233,11 @@
971
_PWG_MEDIA_MM("prc_4_110x208mm", NULL, "EnvPRC4", 110, 208),
972
_PWG_MEDIA_MM("prc_8_120x309mm", NULL, "EnvPRC8", 120, 309),
973
_PWG_MEDIA_MM("prc_6_120x320mm", NULL, NULL, 120, 320),
974
- _PWG_MEDIA_MM("prc_3_125x176mm", NULL, "EnvPRC3", 125, 176),
975
_PWG_MEDIA_MM("prc_16k_146x215mm", NULL, "PRC16K", 146, 215),
976
_PWG_MEDIA_MM("prc_7_160x230mm", NULL, "EnvPRC7", 160, 230),
977
_PWG_MEDIA_MM("om_juuro-ku-kai_198x275mm", NULL, NULL, 198, 275),
978
_PWG_MEDIA_MM("om_pa-kai_267x389mm", NULL, NULL, 267, 389),
979
_PWG_MEDIA_MM("om_dai-pa-kai_275x395mm", NULL, NULL, 275, 395),
980
- _PWG_MEDIA_MM("prc_10_324x458mm", NULL, "EnvPRC10", 324, 458),
982
/* Chinese Standard Sheet Media Inch Sizes */
983
_PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, "roc16k", 7.75, 10.75),
985
/* Other Metric Standard Sheet Media Sizes */
986
_PWG_MEDIA_MM("om_small-photo_100x150mm", NULL, "om_small-photo", 100, 150),
987
_PWG_MEDIA_MM("om_italian_110x230mm", NULL, "EnvItalian", 110, 230),
988
- _PWG_MEDIA_MM("om_postfix_114x229mm", NULL, NULL, 114, 229),
989
_PWG_MEDIA_MM("om_large-photo_200x300", NULL, "om_large-photo", 200, 300),
990
_PWG_MEDIA_MM("om_folio_210x330mm", "folio", "Folio", 210, 330),
991
_PWG_MEDIA_MM("om_folio-sp_215x315mm", NULL, "FolioSP", 215, 315),
994
@@ -1018,13 +1018,14 @@
997
char ch; /* Connection check byte */
998
+ ssize_t n; /* Number of bytes */
1001
- if (recv(cg->http->fd, &ch, 1, MSG_PEEK) < 0 &&
1002
- WSAGetLastError() != WSAEWOULDBLOCK)
1003
+ if ((n = recv(cg->http->fd, &ch, 1, MSG_PEEK)) == 0 ||
1004
+ (n < 0 && WSAGetLastError() != WSAEWOULDBLOCK))
1006
- if (recv(cg->http->fd, &ch, 1, MSG_PEEK | MSG_DONTWAIT) < 0 &&
1007
- errno != EWOULDBLOCK)
1008
+ if ((n = recv(cg->http->fd, &ch, 1, MSG_PEEK | MSG_DONTWAIT)) == 0 ||
1009
+ (n < 0 && errno != EWOULDBLOCK))
1013
--- a/doc/help/ref-cups-files-conf.html.in
1014
+++ b/doc/help/ref-cups-files-conf.html.in
1015
@@ -429,6 +429,31 @@
1016
default server directory is <VAR>/etc/cups</VAR>.</P>
1019
+<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.6.4</SPAN><A NAME="SyncOnClose">SyncOnClose</A></H2>
1023
+<PRE CLASS="command">
1028
+<H3>Description</H3>
1030
+<P>The <CODE>SyncOnClose</CODE> directive determines whether the scheduler
1031
+flushes changes to configuration and state files to disk. The default is
1032
+<CODE>No</CODE> which relies on the operating system to schedule a suitable
1033
+time to write changes to disk.</P>
1035
+<BLOCKQUOTE><B>Note:</B>
1037
+<P>Setting <CODE>SyncOnClose</CODE> to <CODE>Yes</CODE> makes the scheduler use the <CODE>fsync(2)</CODE> system call to write all changes to disk, however the drive or network file system server may still delay writing data to disk. Do not depend on this functionality to prevent data loss in the event of unexpected hardware failure.</P>
1039
+<P>Enabling <CODE>SyncOnClose</CODE> may also cause the scheduler to periodically become unresponsive while it waits for changes to be written.</P>
1044
<H2 CLASS="title"><A NAME="SystemGroup">SystemGroup</A></H2>
1047
--- a/man/cups-files.conf.man.in
1048
+++ b/man/cups-files.conf.man.in
1050
.\" which should have been included with this file. If this file is
1051
.\" file is missing or damaged, see the license at "http://www.cups.org/".
1053
-.TH cups-files.conf 5 "CUPS" "8 July 2013" "Apple Inc."
1054
+.TH cups-files.conf 5 "CUPS" "26 July 2013" "Apple Inc."
1056
cups-files.conf \- file and directory configuration file for cups
1058
@@ -122,6 +122,12 @@
1060
Specifies the directory where the server configuration files can be found.
1065
+Specifies whether the scheduler calls \fIfsync(2)\fR after writing configuration
1066
+or state files. The default is No.
1068
SystemGroup group-name [group-name ...]
1070
Specifies the group(s) to use for System class authentication.
1071
--- a/packaging/cups.spec
1072
+++ b/packaging/cups.spec
1074
/usr/share/cups/ppdc/*
1075
%dir /usr/share/cups/templates
1076
/usr/share/cups/templates/*
1077
+%dir /usr/share/cups/usb
1078
+/usr/share/cups/usb/*
1080
%dir /usr/share/doc/cups
1081
/usr/share/doc/cups/*.*
1082
%dir /usr/share/doc/cups/help
1083
--- a/packaging/cups.spec.in
1084
+++ b/packaging/cups.spec.in
1086
/usr/share/cups/ppdc/*
1087
%dir /usr/share/cups/templates
1088
/usr/share/cups/templates/*
1089
+%dir /usr/share/cups/usb
1090
+/usr/share/cups/usb/*
1092
%dir /usr/share/doc/cups
1093
/usr/share/doc/cups/*.*
1094
%dir /usr/share/doc/cups/help
1095
--- a/scheduler/colorman.c
1096
+++ b/scheduler/colorman.c
1097
@@ -103,11 +103,10 @@
1098
# define COLORD_KIND_PRINTER "printer"
1099
/* printing output device */
1101
-# define COLORD_DBUS_MSG(p,m) dbus_message_new_method_call(\
1102
- "org.freedesktop.ColorManager", (p),\
1103
- "org.freedesktop.ColorManager", (m))
1104
- /* Macro to make new colord messages */
1105
-# define COLORD_DBUS_PATH "/org/freedesktop/ColorManager"
1106
+# define COLORD_DBUS_SERVICE "org.freedesktop.ColorManager"
1107
+# define COLORD_DBUS_INTERFACE "org.freedesktop.ColorManager"
1108
+# define COLORD_DBUS_INTERFACE_DEVICE "org.freedesktop.ColorManager.Device"
1109
+# define COLORD_DBUS_PATH "/org/freedesktop/ColorManager"
1110
/* Path for color management system */
1111
# define COLORD_DBUS_TIMEOUT 5000 /* Timeout for connecting to colord in ms */
1112
#endif /* __APPLE__ */
1113
@@ -939,7 +938,10 @@
1114
snprintf(device_id, sizeof(device_id), "cups-%s", p->name);
1115
device_path = device_id;
1117
- message = COLORD_DBUS_MSG(COLORD_DBUS_PATH, "CreateDevice");
1118
+ message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1120
+ COLORD_DBUS_INTERFACE,
1123
dbus_message_iter_init_append(message, &args);
1124
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_path);
1125
@@ -1048,7 +1050,10 @@
1126
* Create the profile...
1129
- message = COLORD_DBUS_MSG(COLORD_DBUS_PATH, "CreateProfile");
1130
+ message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1132
+ COLORD_DBUS_INTERFACE,
1135
idstrlen = strlen(printer_name) + 1 + strlen(qualifier) + 1;
1136
if ((idstr = malloc(idstrlen)) == NULL)
1137
@@ -1144,7 +1149,10 @@
1138
* Delete the device...
1141
- message = COLORD_DBUS_MSG(COLORD_DBUS_PATH, "DeleteDevice");
1142
+ message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1144
+ COLORD_DBUS_INTERFACE,
1147
dbus_message_iter_init_append(message, &args);
1148
dbus_message_iter_append_basic(&args, DBUS_TYPE_OBJECT_PATH, &device_path);
1149
@@ -1196,7 +1204,10 @@
1150
DBusError error; /* D-Bus error */
1153
- message = COLORD_DBUS_MSG(device_path, "AddProfile");
1154
+ message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1156
+ COLORD_DBUS_INTERFACE_DEVICE,
1159
dbus_message_iter_init_append(message, &args);
1160
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &relation);
1161
@@ -1266,7 +1277,10 @@
1162
char *device_path = NULL; /* Device object path */
1165
- message = COLORD_DBUS_MSG(COLORD_DBUS_PATH, "FindDeviceById");
1166
+ message = dbus_message_new_method_call(COLORD_DBUS_SERVICE,
1168
+ COLORD_DBUS_INTERFACE,
1169
+ "FindDeviceById");
1171
dbus_message_iter_init_append(message, &args);
1172
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &device_id);
1173
--- a/scheduler/conf.c
1174
+++ b/scheduler/conf.c
1176
{ "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME },
1177
{ "SMBConfigFile", &SMBConfigFile, CUPSD_VARTYPE_STRING },
1178
{ "StateDir", &StateDir, CUPSD_VARTYPE_STRING },
1179
+ { "SyncOnClose", &SyncOnClose, CUPSD_VARTYPE_BOOLEAN },
1180
#ifdef HAVE_AUTHORIZATION_H
1181
{ "SystemGroupAuthKey", &SystemGroupAuthKey, CUPSD_VARTYPE_STRING },
1182
#endif /* HAVE_AUTHORIZATION_H */
1184
ReloadTimeout = DEFAULT_KEEPALIVE;
1185
RootCertDuration = 300;
1186
StrictConformance = FALSE;
1187
+ SyncOnClose = FALSE;
1188
Timeout = DEFAULT_TIMEOUT;
1189
WebInterface = CUPS_DEFAULT_WEBIF;
1191
--- a/scheduler/conf.h
1192
+++ b/scheduler/conf.h
1194
/* Which errors are fatal? */
1195
StrictConformance VALUE(FALSE),
1196
/* Require strict IPP conformance? */
1197
+ SyncOnClose VALUE(FALSE),
1198
+ /* Call fsync() when closing files? */
1199
LogFilePerm VALUE(0644);
1200
/* Permissions for log files */
1201
VAR cupsd_loglevel_t LogLevel VALUE(CUPSD_LOG_WARN);
1202
--- a/scheduler/file.c
1203
+++ b/scheduler/file.c
1204
@@ -109,6 +109,29 @@
1208
+ * Synchronize changes to disk if SyncOnClose is enabled.
1213
+ if (cupsFileFlush(fp))
1215
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to write changes to \"%s\": %s",
1216
+ filename, strerror(errno));
1217
+ cupsFileClose(fp);
1221
+ if (fsync(cupsFileNumber(fp)))
1223
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to sync changes to \"%s\": %s",
1224
+ filename, strerror(errno));
1225
+ cupsFileClose(fp);
1231
* First close the file...