1 /*
2  *   Canon SELPHY ES/CP series CUPS backend -- libusb-1.0 version
3  *
4  *   (c) 2007-2018 Solomon Peachy <pizza@shaftnet.org>
5  *
6  *   The latest version of this program can be found at:
7  *
8  *     http://git.shaftnet.org/cgit/selphy_print.git
9  *
10  *   This program is free software; you can redistribute it and/or modify it
11  *   under the terms of the GNU General Public License as published by the Free
12  *   Software Foundation; either version 2 of the License, or (at your option)
13  *   any later version.
14  *
15  *   This program is distributed in the hope that it will be useful, but
16  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  *   for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
22  *
23  *          [http://www.gnu.org/licenses/gpl-2.0.html]
24  *
25  *   SPDX-License-Identifier: GPL-2.0+
26  *
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <signal.h>
38 
39 #define BACKEND canonselphy_backend
40 
41 #include "backend_common.h"
42 
43 #define P_ES40_CP790 (P_END + 1) // used for detection only
44 
45 /* Exported */
46 #define USB_VID_CANON       0x04a9
47 #define USB_PID_CANON_CP10  0x304A
48 #define USB_PID_CANON_CP100 0x3063
49 #define USB_PID_CANON_CP200 0x307C
50 #define USB_PID_CANON_CP220 0x30BD
51 #define USB_PID_CANON_CP300 0x307D
52 #define USB_PID_CANON_CP330 0x30BE
53 #define USB_PID_CANON_CP400 0x30F6
54 #define USB_PID_CANON_CP500 0x30F5
55 #define USB_PID_CANON_CP510 0x3128
56 #define USB_PID_CANON_CP520 0x3172
57 #define USB_PID_CANON_CP530 0x31b1
58 #define USB_PID_CANON_CP600 0x310B
59 #define USB_PID_CANON_CP710 0x3127
60 #define USB_PID_CANON_CP720 0x3143
61 #define USB_PID_CANON_CP730 0x3142
62 #define USB_PID_CANON_CP740 0x3171
63 #define USB_PID_CANON_CP750 0x3170
64 #define USB_PID_CANON_CP760 0x31AB
65 #define USB_PID_CANON_CP770 0x31AA
66 #define USB_PID_CANON_CP780 0x31DD
67 #define USB_PID_CANON_CP790 0x31E7
68 #define USB_PID_CANON_CP800 0x3214
69 #define USB_PID_CANON_CP810 0x3256
70 #define USB_PID_CANON_CP900 0x3255
71 #define USB_PID_CANON_ES1   0x3141
72 #define USB_PID_CANON_ES2   0x3185
73 #define USB_PID_CANON_ES20  0x3186
74 #define USB_PID_CANON_ES3   0x31AF
75 #define USB_PID_CANON_ES30  0x31B0
76 #define USB_PID_CANON_ES40  0x31EE
77 
78 #define READBACK_LEN 12
79 
80 struct printer_data {
81 	int  type;  /* P_??? */
82 	char *model; /* eg "SELPHY ES1" */
83 	uint16_t init_length;
84 	uint16_t  foot_length;
85 	int16_t init_readback[READBACK_LEN];
86 	int16_t ready_y_readback[READBACK_LEN];
87 	int16_t ready_m_readback[READBACK_LEN];
88 	int16_t ready_c_readback[READBACK_LEN];
89 	int16_t done_c_readback[READBACK_LEN];
90 	uint8_t clear_error[READBACK_LEN];
91 	uint8_t clear_error_len;
92 	int16_t paper_codes[256];
93 	int8_t  pgcode_offset;  /* Offset into printjob for paper type */
94 	int8_t  paper_code_offset; /* Offset in readback for paper type */
95 	int8_t  paper_code_offset2; /* Offset in readback for paper type (2nd) */
96 	uint8_t (*error_detect)(uint8_t *rdbuf);
97 	char    *(*pgcode_names)(uint8_t *rdbuf, struct printer_data *printer);
98 };
99 
generic_pgcode_names(uint8_t * rdbuf,struct printer_data * printer)100 static char *generic_pgcode_names(uint8_t *rdbuf, struct printer_data *printer)
101 {
102 	uint8_t pgcode = 0, pgcode2 = 0;
103 
104 	if (printer->paper_code_offset != -1)
105 		pgcode = rdbuf[printer->paper_code_offset];
106 	if (printer->paper_code_offset2 != -1)
107 		pgcode2 = rdbuf[printer->paper_code_offset2];
108 
109 	switch(pgcode & 0xf) {
110 	case 0x01: return "P";
111 	case 0x02: return "L";
112 	case 0x03: return pgcode2 ? "Cl" : "C";
113 	case 0x04: return "W";
114 	case 0x0f: return "None";
115 	default: return "Unknown";
116 	}
117 }
118 
es1_error_detect(uint8_t * rdbuf)119 static uint8_t es1_error_detect(uint8_t *rdbuf)
120 {
121 	if (rdbuf[1] == 0x01) {
122 		if (rdbuf[9] == 0x00)
123 			ERROR("Cover open!\n");
124 		else
125 			ERROR("Unknown error %02x\n", rdbuf[9]);
126 		return 1;
127 	} else if (rdbuf[4] == 0x01 && rdbuf[5] == 0xff &&
128 		   rdbuf[6] == 0xff && rdbuf[7] == 0xff) {
129 		ERROR("No media loaded!\n");
130 		return 1;
131 	} else if (rdbuf[0] == 0x0f) {
132 		ERROR("Out of media!\n");
133 		return 1;
134 	}
135 
136 	return 0;
137 }
138 
es2_error_detect(uint8_t * rdbuf)139 static uint8_t es2_error_detect(uint8_t *rdbuf)
140 {
141 	if (rdbuf[0] == 0x16 &&
142 	    rdbuf[1] == 0x01) {
143 		ERROR("Printer cover open!\n");
144 		return 1;
145 	}
146 
147 	if (rdbuf[0] == 0x02 &&
148 	    rdbuf[4] == 0x05 &&
149 	    rdbuf[5] == 0x05 &&
150 	    rdbuf[6] == 0x02) {
151 		ERROR("No media loaded!\n");
152 		return 1;
153 	}
154 
155 	if (rdbuf[0] == 0x14) {
156 		ERROR("Out of media!\n");
157 		return 1;
158 	}
159 
160 	return 0;
161 }
162 
es3_error_detect(uint8_t * rdbuf)163 static uint8_t es3_error_detect(uint8_t *rdbuf)
164 {
165 	if (rdbuf[8] == 0x01) {
166 		if (rdbuf[10] == 0x0f)
167 			ERROR("Communications Error\n");
168 		else if (rdbuf[10] == 0x01)
169 			ERROR("No media loaded!\n");
170 		else
171 			ERROR("Unknown error - %02x + %02x\n",
172 			      rdbuf[8], rdbuf[10]);
173 		return 1;
174 	} else if (rdbuf[8] == 0x03 &&
175 		   rdbuf[10] == 0x02) {
176 		ERROR("No media loaded!\n");
177 		return 1;
178 	} else if (rdbuf[8] == 0x08 &&
179 		   rdbuf[10] == 0x04) {
180 		ERROR("Printer cover open!\n");
181 		return 1;
182 	} else if (rdbuf[8] == 0x05 &&
183 		   rdbuf[10] == 0x01) {
184 		ERROR("Incorrect media loaded!\n");
185 		return 1;
186 	}
187 
188 	if (rdbuf[8] || rdbuf[10]) {
189 		ERROR("Unknown error - %02x + %02x\n",
190 		      rdbuf[8], rdbuf[10]);
191 		return 1;
192 	}
193 
194 	return 0;
195 }
196 
es40_error_detect(uint8_t * rdbuf)197 static uint8_t es40_error_detect(uint8_t *rdbuf)
198 {
199 	/* ES40 */
200 	if (!rdbuf[3])
201 		return 0;
202 
203 	if (rdbuf[3] == 0x01)
204 		ERROR("Generic communication error\n");
205 	else if (rdbuf[3] == 0x32)
206 		ERROR("Cover open or media empty!\n");
207 	else
208 		ERROR("Unknown error - %02x\n", rdbuf[3]);
209 
210 	return 1;
211 }
212 
cp790_error_detect(uint8_t * rdbuf)213 static uint8_t cp790_error_detect(uint8_t *rdbuf)
214 {
215 	/* CP790 */
216 	if (rdbuf[5] == 0xff) {
217 		ERROR("No ribbon loaded!\n");
218 		return 1;
219 	} else if (rdbuf[4] == 0xff) {
220 		ERROR("No paper tray loaded!\n");
221 		return 1;
222 	} else if (rdbuf[3]) {
223 		if ((rdbuf[3] & 0xf) == 0x02) // 0x12 0x22
224 			ERROR("No paper tray loaded!\n");
225 		else if ((rdbuf[3] & 0xf) == 0x03) // 0x13 0x23
226 			ERROR("Empty paper tray or feed error!\n");
227 		else if (rdbuf[3] == 0x11)
228 			ERROR("Paper feed error!\n");
229 		else if (rdbuf[3] == 0x21)
230 			ERROR("Ribbon depleted!\n");
231 		else
232 			ERROR("Unknown error - %02x\n", rdbuf[3]);
233 		return 1;
234 	}
235 
236 	return 0;
237 }
238 
cp10_pgcode_names(uint8_t * rdbuf,struct printer_data * printer)239 static char *cp10_pgcode_names(uint8_t *rdbuf, struct printer_data *printer)
240 {
241 	UNUSED(rdbuf);
242 	UNUSED(printer);
243 
244 	return "C";   /* Printer only supports one media type */
245 }
246 
cp10_error_detect(uint8_t * rdbuf)247 static uint8_t cp10_error_detect(uint8_t *rdbuf)
248 {
249 	if (!rdbuf[2])
250 		return 0;
251 
252 	if (rdbuf[2] == 0x80)
253 		ERROR("No ribbon loaded\n");
254 	else if (rdbuf[2] == 0x08)
255 		ERROR("Ribbon depleted!\n");
256 	else if (rdbuf[2] == 0x01)
257 		ERROR("No paper loaded!\n");
258 	else
259 		ERROR("Unknown error - %02x\n", rdbuf[2]);
260 	return 1;
261 }
262 
cpxxx_error_detect(uint8_t * rdbuf)263 static uint8_t cpxxx_error_detect(uint8_t *rdbuf)
264 {
265 	if (!rdbuf[2])
266 		return 0;
267 
268 	if (rdbuf[2] == 0x01)
269 		ERROR("Paper feed problem!\n");
270 	else if (rdbuf[2] == 0x04)
271 		ERROR("Ribbon problem!\n");
272 	else if (rdbuf[2] == 0x08)
273 		ERROR("Ribbon depleted!\n");
274 	else
275 		ERROR("Unknown error - %02x\n", rdbuf[2]);
276 	return 1;
277 }
278 
279 static struct printer_data selphy_printers[] = {
280 	{ .type = P_ES1,
281 	  .model = "SELPHY ES1",
282 	  .init_length = 12,
283 	  .foot_length = 0,
284 	  .init_readback = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, -1, 0x01, 0x00, 0x00, 0x00, 0x00 },
285 	  .ready_y_readback = { 0x04, 0x00, 0x01, 0x00, 0x02, 0x01, -1, 0x01, 0x00, 0x00, 0x00, 0x00 },
286 	  .ready_m_readback = { 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, -1, 0x01, 0x00, 0x00, 0x00, 0x00 },
287 	  .ready_c_readback = { 0x04, 0x00, 0x07, 0x00, 0x02, 0x01, -1, 0x01, 0x00, 0x00, 0x00, 0x00 },
288 	  .done_c_readback = { 0x04, 0x00, 0x00, 0x00, 0x02, 0x01, -1, 0x01, 0x00, 0x00, 0x00, 0x00 },
289 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
290 	  .clear_error_len = 12,
291 	  .pgcode_offset = 3,
292 	  .paper_code_offset = 6,
293 	  .paper_code_offset2 = -1,
294 	  .error_detect = es1_error_detect,
295 	  .pgcode_names = generic_pgcode_names,
296 	},
297 	{ .type = P_ES2_20,
298 	  .model = "SELPHY ES2/ES20",
299 	  .init_length = 16,
300 	  .foot_length = 0,
301 	  .init_readback = { 0x02, 0x00, 0x00, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00 },
302 	  .ready_y_readback = { 0x03, 0x00, 0x01, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00 },
303 	  .ready_m_readback = { 0x06, 0x00, 0x03, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00 },
304 	  .ready_c_readback = { 0x09, 0x00, 0x07, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00 },
305 	  .done_c_readback = { 0x09, 0x00, 0x00, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00 },
306 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
307 	  .clear_error_len = 12,
308 	  .pgcode_offset = 2,
309 	  .paper_code_offset = 4,
310 	  .paper_code_offset2 = 6,
311 	  .error_detect = es2_error_detect,
312 	  .pgcode_names = generic_pgcode_names,
313 	},
314 	{ .type = P_ES3_30,
315 	  .model = "SELPHY ES3/ES30",
316 	  .init_length = 16,
317 	  .foot_length = 12,
318 	  .init_readback = { 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
319 	  .ready_y_readback = { 0x01, 0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
320 	  .ready_m_readback = { 0x03, 0xff, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
321 	  .ready_c_readback = { 0x05, 0xff, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
322 	  .done_c_readback = { 0x00, 0xff, 0x10, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 },
323 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
324 	  .clear_error_len = 12,
325 	  .pgcode_offset = 2,
326 	  .paper_code_offset = -1,
327 	  .paper_code_offset2 = -1,
328 	  .error_detect = es3_error_detect,
329 	  .pgcode_names = NULL,
330 	},
331 	{ .type = P_ES40,
332 	  .model = "SELPHY ES40",
333 	  .init_length = 16,
334 	  .foot_length = 12,
335 	  .init_readback = { 0x00, 0x00, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1 },
336 	  .ready_y_readback = { 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1 },
337 	  .ready_m_readback = { 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1 },
338 	  .ready_c_readback = { 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1 },
339 	  .done_c_readback = { 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -1 },
340 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
341 	  .clear_error_len = 12,
342 	  .pgcode_offset = 2,
343 	  .paper_code_offset = 11,
344 	  .paper_code_offset2 = -1,
345 	  .error_detect = es40_error_detect,
346 	  .pgcode_names = generic_pgcode_names,
347 	},
348 	{ .type = P_CP790,
349 	  .model = "SELPHY CP790",
350 	  .init_length = 16,
351 	  .foot_length = 12,
352 	  .init_readback = { 0x00, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
353 	  .ready_y_readback = { 0x00, 0x01, 0x01, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
354 	  .ready_m_readback = { 0x00, 0x03, 0x02, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
355 	  .ready_c_readback = { 0x00, 0x05, 0x03, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
356 	  .done_c_readback = { 0x00, 0x00, 0x10, 0x00, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 },
357 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
358 	  .clear_error_len = 12,
359 	  .pgcode_offset = 2,
360 	  .paper_code_offset = -1, /* Uses a different technique */
361 	  .paper_code_offset2 = -1,
362 	  .error_detect = cp790_error_detect,
363 	  .pgcode_names = generic_pgcode_names,
364 	},
365 	{ .type = P_CP_XXX,
366 	  .model = "SELPHY CP Series (!CP-10/CP790)",
367 	  .init_length = 12,
368 	  .foot_length = 0,  /* CP900 has four-byte NULL footer that can be safely ignored */
369 	  .init_readback = { 0x01, 0x00, 0x00, 0x00, -1, 0x00, -1, -1, 0x00, 0x00, 0x00, -1 },
370 	  .ready_y_readback = { 0x02, 0x00, 0x00, 0x00, 0x70, 0x00, -1, -1, 0x00, 0x00, 0x00, -1 },
371 	  .ready_m_readback = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -1, -1, 0x00, 0x00, 0x00, -1 },
372 	  .ready_c_readback = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, -1, -1, 0x00, 0x00, 0x00, -1 },
373 	  .done_c_readback = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, -1, -1, 0x00, 0x00, 0x00, -1 },
374 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
375 	  .clear_error_len = 12,
376 	  .pgcode_offset = 3,
377 	  .paper_code_offset = 6,
378 	  .paper_code_offset2 = -1,
379 	  .error_detect = cpxxx_error_detect,
380 	  .pgcode_names = generic_pgcode_names,
381 	},
382 	{ .type = P_CP10,
383 	  .model = "SELPHY CP-10",
384 	  .init_length = 12,
385 	  .foot_length = 0,
386 	  .init_readback = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
387 	  .ready_y_readback = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
388 	  .ready_m_readback = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
389 	  .ready_c_readback = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
390 	  .done_c_readback = { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
391 	  .clear_error = { 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
392 	  .clear_error_len = 12,
393 	  .pgcode_offset = 2,
394 	  .paper_code_offset = -1,
395 	  .paper_code_offset2 = -1,
396 	  .error_detect = cp10_error_detect,
397 	  .pgcode_names = cp10_pgcode_names,
398 	},
399 	{ .type = -1 },
400 };
401 
402 #define MAX_HEADER 28
403 
404 static const uint32_t es40_cp790_plane_lengths[4] = { 2227456, 1601600, 698880, 2976512 };
405 
setup_paper_codes(void)406 static void setup_paper_codes(void)
407 {
408 	int i, j;
409 	for (i = 0 ; ; i++) {
410 		if (selphy_printers[i].type == -1)
411 			break;
412 		/* Default all to IGNORE */
413 		for (j = 0 ; j < 256 ; j++)
414 			selphy_printers[i].paper_codes[j] = -1;
415 
416 		/* Set up specifics */
417 		switch (selphy_printers[i].type) {
418 		case P_ES1:
419 			selphy_printers[i].paper_codes[0x11] = 0x01;
420 			selphy_printers[i].paper_codes[0x12] = 0x02;
421 			selphy_printers[i].paper_codes[0x13] = 0x03;
422 			break;
423 		case P_ES2_20:
424 			selphy_printers[i].paper_codes[0x01] = 0x01;
425 			selphy_printers[i].paper_codes[0x02] = 0x02;
426 			selphy_printers[i].paper_codes[0x03] = 0x03;
427 			break;
428 		case P_ES40:
429 			selphy_printers[i].paper_codes[0x00] = 0x11;
430 			selphy_printers[i].paper_codes[0x01] = 0x22;
431 			selphy_printers[i].paper_codes[0x02] = 0x33;
432 			selphy_printers[i].paper_codes[0x03] = 0x44;
433 			break;
434 		case P_CP_XXX:
435 			selphy_printers[i].paper_codes[0x01] = 0x11;
436 			selphy_printers[i].paper_codes[0x02] = 0x22;
437 			selphy_printers[i].paper_codes[0x03] = 0x33;
438 			selphy_printers[i].paper_codes[0x04] = 0x44;
439 			break;
440 		case P_ES3_30:
441 			/* N/A, printer does not report types */
442 		case P_CP790:
443 			/* N/A, printer uses different technique */
444 		case P_CP10:
445 			/* N/A, printer supports one type only */
446 			break;
447 		}
448 	}
449 }
450 
451 #define INCORRECT_PAPER -999
452 
453 /* Program states */
454 enum {
455 	S_IDLE = 0,
456 	S_PRINTER_READY,
457 	S_PRINTER_INIT_SENT,
458 	S_PRINTER_READY_Y,
459 	S_PRINTER_Y_SENT,
460 	S_PRINTER_READY_M,
461 	S_PRINTER_M_SENT,
462 	S_PRINTER_READY_C,
463 	S_PRINTER_C_SENT,
464 	S_PRINTER_CP900_FOOTER,
465 	S_PRINTER_DONE,
466 	S_FINISHED,
467 };
468 
fancy_memcmp(const uint8_t * buf_a,const int16_t * buf_b,uint len)469 static int fancy_memcmp(const uint8_t *buf_a, const int16_t *buf_b, uint len)
470 {
471 	uint i;
472 
473 	for (i = 0 ; i < len ; i++) {
474 		if (buf_b[i] == -1)
475 			continue;
476 		else if (buf_a[i] > buf_b[i])
477 			return 1;
478 		else if (buf_a[i] < buf_b[i])
479 			return -1;
480 	}
481 	return 0;
482 }
483 
parse_printjob(uint8_t * buffer,uint8_t * bw_mode,uint32_t * plane_len)484 static int parse_printjob(uint8_t *buffer, uint8_t *bw_mode, uint32_t *plane_len)
485 {
486 	int printer_type = -1;
487 
488 	if (buffer[0] != 0x40 &&
489 	    buffer[1] != 0x00) {
490 		goto done;
491 	}
492 
493 	if (buffer[12] == 0x40 &&
494 	    buffer[13] == 0x01) {
495 		*plane_len = *(uint32_t*)(&buffer[16]);
496 		*plane_len = le32_to_cpu(*plane_len);
497 
498 		if (buffer[2] == 0x00) {
499 			if (*plane_len == 688480)
500 				printer_type = P_CP10;
501 			else
502 				printer_type = P_CP_XXX;
503 		} else {
504 			printer_type = P_ES1;
505 			*bw_mode = (buffer[2] == 0x20);
506 		}
507 		goto done;
508 	}
509 
510 	*plane_len = *(uint32_t*)(&buffer[12]);
511 	*plane_len = le32_to_cpu(*plane_len);
512 
513 	if (buffer[16] == 0x40 &&
514 	    buffer[17] == 0x01) {
515 
516 		if (buffer[4] == 0x02) {
517 			printer_type = P_ES2_20;
518 			*bw_mode = (buffer[7] == 0x01);
519 			goto done;
520 		}
521 
522 		if (es40_cp790_plane_lengths[buffer[2]] == *plane_len) {
523 			printer_type = P_ES40_CP790;
524 			*bw_mode = (buffer[3] == 0x01);
525 			goto done;
526 		} else {
527 			printer_type = P_ES3_30;
528 			*bw_mode = (buffer[3] == 0x01);
529 			goto done;
530 		}
531 	}
532 
533 done:
534 	return printer_type;
535 }
536 
537 /* Private data structure */
538 struct canonselphy_printjob {
539 	int16_t paper_code;
540 	uint8_t bw_mode;
541 
542 	uint32_t plane_len;
543 
544 	uint8_t *header;
545 	uint8_t *plane_y;
546 	uint8_t *plane_m;
547 	uint8_t *plane_c;
548 	uint8_t *footer;
549 
550 	int copies;
551 };
552 
553 struct canonselphy_ctx {
554 	struct libusb_device_handle *dev;
555 	uint8_t endp_up;
556 	uint8_t endp_down;
557 	int type;
558 
559 	struct printer_data *printer;
560 	struct marker marker;
561 
562 	uint8_t cp900;
563 };
564 
canonselphy_get_status(struct canonselphy_ctx * ctx)565 static int canonselphy_get_status(struct canonselphy_ctx *ctx)
566 {
567 	uint8_t rdbuf[READBACK_LEN];
568 	int ret, num;
569 
570 	/* Read in the printer status, twice. */
571 	ret = read_data(ctx->dev, ctx->endp_up,
572 			(uint8_t*) rdbuf, READBACK_LEN, &num);
573 	if (ret < 0)
574 		return CUPS_BACKEND_FAILED;
575 
576 	ret = read_data(ctx->dev, ctx->endp_up,
577 			(uint8_t*) rdbuf, READBACK_LEN, &num);
578 
579 	if (ret < 0)
580 		return CUPS_BACKEND_FAILED;
581 
582 	INFO("Media type: %s\n", ctx->printer->pgcode_names? ctx->printer->pgcode_names(rdbuf, ctx->printer) : "Unknown");
583 	ctx->printer->error_detect(rdbuf);
584 
585 	return CUPS_BACKEND_OK;
586 }
587 
canonselphy_send_reset(struct canonselphy_ctx * ctx)588 static int canonselphy_send_reset(struct canonselphy_ctx *ctx)
589 {
590 	uint8_t rstcmd[12] = { 0x40, 0x10, 0x00, 0x00,
591 			       0x00, 0x00, 0x00, 0x00,
592 			       0x00, 0x00, 0x00, 0x00 };
593 	int ret;
594 
595 	if ((ret = send_data(ctx->dev, ctx->endp_down,
596 			     rstcmd, sizeof(rstcmd))))
597 		return CUPS_BACKEND_FAILED;
598 
599 	return CUPS_BACKEND_OK;
600 }
601 
canonselphy_init(void)602 static void *canonselphy_init(void)
603 {
604 	struct canonselphy_ctx *ctx = malloc(sizeof(struct canonselphy_ctx));
605 	if (!ctx) {
606 		ERROR("Memory Allocation Failure!\n");
607 		return NULL;
608 	}
609 	memset(ctx, 0, sizeof(struct canonselphy_ctx));
610 
611 	/* Static initialization */
612 	setup_paper_codes();
613 
614 	return ctx;
615 }
616 
617 extern struct dyesub_backend canonselphy_backend;
618 
canonselphy_attach(void * vctx,struct libusb_device_handle * dev,int type,uint8_t endp_up,uint8_t endp_down,uint8_t jobid)619 static int canonselphy_attach(void *vctx, struct libusb_device_handle *dev, int type,
620 			      uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
621 {
622 	struct canonselphy_ctx *ctx = vctx;
623 	int i, num;
624 	uint8_t rdbuf[READBACK_LEN];
625 
626 	UNUSED(jobid);
627 
628 	ctx->dev = dev;
629 	ctx->endp_up = endp_up;
630 	ctx->endp_down = endp_down;
631 	ctx->type = type;
632 
633 	if (ctx->type == P_CP900) {
634 		ctx->type = P_CP_XXX;
635 		ctx->cp900 = 1;
636 	}
637 	for (i = 0 ; selphy_printers[i].type != -1; i++) {
638 		if (selphy_printers[i].type == ctx->type) {
639 			ctx->printer = &selphy_printers[i];
640 		}
641 	}
642 	if (!ctx->printer) {
643 		ERROR("Error looking up printer type!\n");
644 		return CUPS_BACKEND_FAILED;
645 	}
646 
647 	/* Fill out marker structure */
648 	ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
649 	ctx->marker.levelmax = -1; /* Unknown */
650 
651 	if (test_mode < TEST_MODE_NOATTACH) {
652 		/* Read printer status. Twice. */
653 		i = read_data(ctx->dev, ctx->endp_up,
654 			      rdbuf, READBACK_LEN, &num);
655 		if (i < 0)
656 			return CUPS_BACKEND_FAILED;
657 
658 		i = read_data(ctx->dev, ctx->endp_up,
659 			      rdbuf, READBACK_LEN, &num);
660 		if (i < 0)
661 			return CUPS_BACKEND_FAILED;
662 
663 		if (ctx->printer->error_detect(rdbuf))
664 			ctx->marker.levelnow = 0;  /* Out of media */
665 		else
666 			ctx->marker.levelnow = -3; /* Unknown but OK */
667 		ctx->marker.name = ctx->printer->pgcode_names? ctx->printer->pgcode_names(rdbuf, ctx->printer) : "Unknown";
668 	} else {
669 		// XXX handle MEDIA_CODE at some point.
670 		// we don't do any error checking here.
671 		ctx->marker.name = "Unknown";
672 	}
673 
674 	return CUPS_BACKEND_OK;
675 }
676 
canonselphy_cleanup_job(const void * vjob)677 static void canonselphy_cleanup_job(const void *vjob) {
678 	const struct canonselphy_printjob *job = vjob;
679 
680 	if (job->header)
681 		free(job->header);
682 	if (job->plane_y)
683 		free(job->plane_y);
684 	if (job->plane_m)
685 		free(job->plane_m);
686 	if (job->plane_c)
687 		free(job->plane_c);
688 	if (job->footer)
689 		free(job->footer);
690 
691 	free((void*)job);
692 }
693 
canonselphy_read_parse(void * vctx,const void ** vjob,int data_fd,int copies)694 static int canonselphy_read_parse(void *vctx, const void **vjob, int data_fd, int copies)
695 {
696 	struct canonselphy_ctx *ctx = vctx;
697 	int i, remain;
698 	int printer_type;
699 	int offset = 0;
700 	uint8_t rdbuf[MAX_HEADER];
701 
702 	struct canonselphy_printjob *job = NULL;
703 
704 	if (!ctx)
705 		return CUPS_BACKEND_FAILED;
706 
707 	job = malloc(sizeof(*job));
708 	if (!job) {
709 		ERROR("Memory allocation failure!\n");
710 		return CUPS_BACKEND_RETRY_CURRENT;
711 	}
712 	memset(job, 0, sizeof(*job));
713 	job->copies = copies;
714 
715 	/* The CP900 job *may* have a 4-byte null footer after the
716 	   job contents.  Ignore it if it comes through here.. */
717 	i = read(data_fd, rdbuf, 4);
718 	if (i != 4) {
719 		if (i == 0) {
720 			canonselphy_cleanup_job(job);
721 			return CUPS_BACKEND_CANCEL;
722 		}
723 		ERROR("Read failed (%d/%d)\n", i, 4);
724 		perror("ERROR: Read failed");
725 		canonselphy_cleanup_job(job);
726 		return CUPS_BACKEND_FAILED;
727 	}
728 	/* if it's not the null header.. don't ignore! */
729 	if (rdbuf[0] != 0 ||
730 	    rdbuf[1] != 0 ||
731 	    rdbuf[2] != 0 ||
732 	    rdbuf[3] != 0) {
733 		offset = 4;
734 	}
735 
736 	/* Read the rest of the header.. */
737 	i = read(data_fd, rdbuf + offset, MAX_HEADER - offset);
738 	if (i != MAX_HEADER - offset) {
739 		if (i == 0) {
740 			canonselphy_cleanup_job(job);
741 			return CUPS_BACKEND_CANCEL;
742 		}
743 		ERROR("Read failed (%d/%d)\n",
744 		      i, MAX_HEADER - offset);
745 		perror("ERROR: Read failed");
746 		canonselphy_cleanup_job(job);
747 		return CUPS_BACKEND_FAILED;
748 	}
749 
750 	/* Figure out printer this file is intended for */
751 	printer_type = parse_printjob(rdbuf, &job->bw_mode, &job->plane_len);
752 	/* Special cases for some models */
753 	if (printer_type == P_ES40_CP790) {
754 		if (ctx->type == P_CP790)
755 			printer_type = P_CP790;
756 		else
757 			printer_type = P_ES40;
758 	}
759 
760 	if (printer_type != ctx->type) {
761 		ERROR("Printer/Job mismatch (%d/%d/%d)\n", ctx->type, ctx->printer->type, printer_type);
762 		canonselphy_cleanup_job(job);
763 		return CUPS_BACKEND_CANCEL;
764 	}
765 
766 	INFO("%sFile intended for a '%s' printer\n",  job->bw_mode? "B/W " : "", ctx->printer->model);
767 
768 	/* Paper code setup */
769 	if (ctx->printer->pgcode_offset != -1)
770 		job->paper_code = ctx->printer->paper_codes[rdbuf[ctx->printer->pgcode_offset]];
771 	else
772 		job->paper_code = -1;
773 
774 	/* Add in plane header length! */
775 	job->plane_len += 12;
776 
777 	/* Set up buffers */
778 	job->plane_y = malloc(job->plane_len);
779 	job->plane_m = malloc(job->plane_len);
780 	job->plane_c = malloc(job->plane_len);
781 	job->header = malloc(ctx->printer->init_length);
782 	job->footer = malloc(ctx->printer->foot_length);
783 	if (!job->plane_y || !job->plane_m || !job->plane_c || !job->header ||
784 	    (ctx->printer->foot_length && !job->footer)) {
785 		ERROR("Memory allocation failure!\n");
786 		canonselphy_cleanup_job(job);
787 		return CUPS_BACKEND_RETRY_CURRENT;
788 	}
789 
790 	/* Move over chunks already read in */
791 	memcpy(job->header, rdbuf, ctx->printer->init_length);
792 	memcpy(job->plane_y, rdbuf+ctx->printer->init_length,
793 	       MAX_HEADER-ctx->printer->init_length);
794 
795 	/* Read in YELLOW plane */
796 	remain = job->plane_len - (MAX_HEADER-ctx->printer->init_length);
797 	while (remain > 0) {
798 		i = read(data_fd, job->plane_y + (job->plane_len - remain), remain);
799 		if (i < 0) {
800 			canonselphy_cleanup_job(job);
801 			return CUPS_BACKEND_CANCEL;
802 		}
803 		remain -= i;
804 	}
805 
806 	/* Read in MAGENTA plane */
807 	remain = job->plane_len;
808 	while (remain > 0) {
809 		i = read(data_fd, job->plane_m + (job->plane_len - remain), remain);
810 		if (i < 0) {
811 			canonselphy_cleanup_job(job);
812 			return CUPS_BACKEND_CANCEL;
813 		}
814 		remain -= i;
815 	}
816 
817 	/* Read in CYAN plane */
818 	remain = job->plane_len;
819 	while (remain > 0) {
820 		i = read(data_fd, job->plane_c + (job->plane_len - remain), remain);
821 		if (i < 0) {
822 			canonselphy_cleanup_job(job);
823 			return CUPS_BACKEND_CANCEL;
824 		}
825 		remain -= i;
826 	}
827 
828 	/* Read in footer */
829 	if (ctx->printer->foot_length) {
830 		remain = ctx->printer->foot_length;
831 		while (remain > 0) {
832 			i = read(data_fd, job->footer + (ctx->printer->foot_length - remain), remain);
833 			if (i < 0) {
834 				canonselphy_cleanup_job(job);
835 				return CUPS_BACKEND_CANCEL;
836 			}
837 			remain -= i;
838 		}
839 	}
840 
841 	*vjob = job;
842 
843 	return CUPS_BACKEND_OK;
844 }
845 
canonselphy_main_loop(void * vctx,const void * vjob)846 static int canonselphy_main_loop(void *vctx, const void *vjob) {
847 	struct canonselphy_ctx *ctx = vctx;
848 
849 	uint8_t rdbuf[READBACK_LEN], rdbuf2[READBACK_LEN];
850 	int last_state = -1, state = S_IDLE;
851 	int ret, num;
852 	int copies;
853 
854 	const struct canonselphy_printjob *job = vjob;
855 
856 	if (!ctx)
857 		return CUPS_BACKEND_FAILED;
858 	if (!job)
859 		return CUPS_BACKEND_FAILED;
860 
861 	copies = job->copies;
862 
863 	/* Read in the printer status to clear last state */
864 	ret = read_data(ctx->dev, ctx->endp_up,
865 			rdbuf, READBACK_LEN, &num);
866 
867 	if (ret < 0)
868 		return CUPS_BACKEND_FAILED;
869 top:
870 
871 	if (state != last_state) {
872 		if (dyesub_debug)
873 			DEBUG("last_state %d new %d\n", last_state, state);
874 	}
875 
876 	/* Read in the printer status */
877 	ret = read_data(ctx->dev, ctx->endp_up,
878 			rdbuf, READBACK_LEN, &num);
879 	if (ret < 0)
880 		return CUPS_BACKEND_FAILED;
881 
882 	if (num != READBACK_LEN) {
883 		ERROR("Short read! (%d/%d)\n", num, READBACK_LEN);
884 		return CUPS_BACKEND_FAILED;
885 	}
886 
887 	/* Error detection */
888 	if (ctx->printer->error_detect(rdbuf)) {
889 		dump_markers(&ctx->marker, 1, 0);
890 		if (ctx->printer->clear_error_len)
891 			/* Try to clear error state */
892 			if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->printer->clear_error, ctx->printer->clear_error_len)))
893 				return CUPS_BACKEND_FAILED;
894 		return CUPS_BACKEND_HOLD;
895 	}
896 
897 	if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
898 		memcpy(rdbuf2, rdbuf, READBACK_LEN);
899 	} else if (state == last_state) {
900 		sleep(1);
901 	}
902 	last_state = state;
903 
904 	fflush(stderr);
905 
906 	switch(state) {
907 	case S_IDLE:
908 		INFO("Waiting for printer idle\n");
909 		if (fancy_memcmp(rdbuf, ctx->printer->init_readback, READBACK_LEN))
910 			break;
911 
912 		/* Make sure paper/ribbon is correct */
913 		if (job->paper_code != -1) {
914 			if (ctx->type == P_CP_XXX) {
915 				uint8_t pc = rdbuf[ctx->printer->paper_code_offset];
916 				if (((pc >> 4) & 0xf) != (job->paper_code & 0x0f)) {
917 
918 					if (pc & 0xf0) {
919 						ERROR("Incorrect paper tray loaded, aborting job!\n");
920 						return CUPS_BACKEND_HOLD;
921 					} else {
922 						ERROR("No paper tray loaded, aborting!\n");
923 						return CUPS_BACKEND_STOP;
924 					}
925 				}
926 				if ((pc & 0xf) != (job->paper_code & 0xf)) {
927 					if (pc & 0x0f) {
928 						ERROR("Incorrect ribbon loaded, aborting job!\n");
929 						return CUPS_BACKEND_HOLD;
930 					} else {
931 
932 						ERROR("No ribbon loaded, aborting job!\n");
933 						return CUPS_BACKEND_STOP;
934 					}
935 				}
936 			} else {
937 				if (rdbuf[ctx->printer->paper_code_offset] !=
938 				    job->paper_code) {
939 					ERROR("Incorrect media/ribbon loaded (%02x vs %02x), aborting job!\n",
940 					      job->paper_code,
941 					      rdbuf[ctx->printer->paper_code_offset]);
942 					return CUPS_BACKEND_HOLD;  /* Hold this job, don't stop queue */
943 				}
944 			}
945 		} else if (ctx->type == P_CP790) {
946 			uint8_t ribbon = rdbuf[4] >> 4;
947 			uint8_t paper = rdbuf[5];
948 
949 			if (ribbon == 0xf) {
950 				ERROR("No ribbon loaded, aborting!\n");
951 				return CUPS_BACKEND_STOP;
952 			} else if (ribbon != job->paper_code) {
953 				ERROR("Incorrect ribbon loaded, aborting job!\n");
954 				return CUPS_BACKEND_HOLD;
955 			}
956 			if (paper == 0xf) {
957 				ERROR("No paper tray loaded, aborting!\n");
958 				return CUPS_BACKEND_STOP;
959 			} else if (paper != job->paper_code) {
960 				ERROR("Incorrect paper loaded, aborting job!\n");
961 				return CUPS_BACKEND_HOLD;
962 			}
963 		}
964 
965 		state = S_PRINTER_READY;
966 		break;
967 	case S_PRINTER_READY:
968 		INFO("Printing started; Sending init sequence\n");
969 		/* Send printer init */
970 		if ((ret = send_data(ctx->dev, ctx->endp_down, job->header, ctx->printer->init_length)))
971 			return CUPS_BACKEND_FAILED;
972 
973 		state = S_PRINTER_INIT_SENT;
974 		break;
975 	case S_PRINTER_INIT_SENT:
976 		if (!fancy_memcmp(rdbuf, ctx->printer->ready_y_readback, READBACK_LEN)) {
977 			state = S_PRINTER_READY_Y;
978 		}
979 		break;
980 	case S_PRINTER_READY_Y:
981 		if (job->bw_mode)
982 			INFO("Sending BLACK plane\n");
983 		else
984 			INFO("Sending YELLOW plane\n");
985 
986 		if ((ret = send_data(ctx->dev, ctx->endp_down, job->plane_y, job->plane_len)))
987 			return CUPS_BACKEND_FAILED;
988 
989 		state = S_PRINTER_Y_SENT;
990 		break;
991 	case S_PRINTER_Y_SENT:
992 		if (!fancy_memcmp(rdbuf, ctx->printer->ready_m_readback, READBACK_LEN)) {
993 			if (job->bw_mode)
994 				state = S_PRINTER_DONE;
995 			else
996 				state = S_PRINTER_READY_M;
997 		}
998 		break;
999 	case S_PRINTER_READY_M:
1000 		INFO("Sending MAGENTA plane\n");
1001 
1002 		if ((ret = send_data(ctx->dev, ctx->endp_down, job->plane_m, job->plane_len)))
1003 			return CUPS_BACKEND_FAILED;
1004 
1005 		state = S_PRINTER_M_SENT;
1006 		break;
1007 	case S_PRINTER_M_SENT:
1008 		if (!fancy_memcmp(rdbuf, ctx->printer->ready_c_readback, READBACK_LEN)) {
1009 			state = S_PRINTER_READY_C;
1010 		}
1011 		break;
1012 	case S_PRINTER_READY_C:
1013 		INFO("Sending CYAN plane\n");
1014 
1015 		if ((ret = send_data(ctx->dev, ctx->endp_down, job->plane_c, job->plane_len)))
1016 			return CUPS_BACKEND_FAILED;
1017 
1018 		state = S_PRINTER_C_SENT;
1019 		break;
1020 	case S_PRINTER_C_SENT:
1021 		if (!fancy_memcmp(rdbuf, ctx->printer->done_c_readback, READBACK_LEN)) {
1022 			if (ctx->cp900)
1023 				state = S_PRINTER_CP900_FOOTER;
1024 			else
1025 				state = S_PRINTER_DONE;
1026 		}
1027 		break;
1028 	case S_PRINTER_CP900_FOOTER: {
1029 		uint32_t empty = 0;
1030 
1031 		INFO("Sending CP900 Footer\n");
1032 		if ((ret = send_data(ctx->dev, ctx->endp_down,
1033 				     (uint8_t*)&empty, sizeof(empty))))
1034 			return CUPS_BACKEND_FAILED;
1035 
1036 		state = S_PRINTER_DONE;
1037 		break;
1038 	}
1039 	case S_PRINTER_DONE:
1040 		if (ctx->printer->foot_length) {
1041 			INFO("Cleaning up\n");
1042 
1043 			if ((ret = send_data(ctx->dev, ctx->endp_down, job->footer, ctx->printer->foot_length)))
1044 				return CUPS_BACKEND_FAILED;
1045 		}
1046 		state = S_FINISHED;
1047 		/* Intentional Fallthrough */
1048 	case S_FINISHED:
1049 		INFO("All data sent to printer!\n");
1050 		break;
1051 	}
1052 	if (state != S_FINISHED)
1053 		goto top;
1054 
1055 	/* Clean up */
1056 	if (terminate)
1057 		copies = 1;
1058 
1059 	INFO("Print complete (%d copies remaining)\n", copies - 1);
1060 
1061 	if (copies && --copies) {
1062 		state = S_IDLE;
1063 		goto top;
1064 	}
1065 
1066 	return CUPS_BACKEND_OK;
1067 }
1068 
canonselphy_cmdline_arg(void * vctx,int argc,char ** argv)1069 static int canonselphy_cmdline_arg(void *vctx, int argc, char **argv)
1070 {
1071 	struct canonselphy_ctx *ctx = vctx;
1072 	int i, j = 0;
1073 
1074 	if (!ctx)
1075 		return -1;
1076 
1077 	while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "Rs")) >= 0) {
1078 		switch(i) {
1079 		GETOPT_PROCESS_GLOBAL
1080 		case 'R':
1081 			canonselphy_send_reset(ctx);
1082 			break;
1083 		case 's':
1084 			canonselphy_get_status(ctx);
1085 			break;
1086 		}
1087 
1088 		if (j) return j;
1089 	}
1090 
1091 	return 0;
1092 }
1093 
canonselphy_cmdline(void)1094 static void canonselphy_cmdline(void)
1095 {
1096 	DEBUG("\t\t[ -R ]           # Reset printer\n");
1097 	DEBUG("\t\t[ -s ]           # Query printer status\n");
1098 }
1099 
canonselphy_query_markers(void * vctx,struct marker ** markers,int * count)1100 static int canonselphy_query_markers(void *vctx, struct marker **markers, int *count)
1101 {
1102 	struct canonselphy_ctx *ctx = vctx;
1103 	uint8_t rdbuf[READBACK_LEN];
1104 	int ret, num;
1105 
1106 	/* Read in the printer status, twice. */
1107 	ret = read_data(ctx->dev, ctx->endp_up,
1108 			(uint8_t*) rdbuf, READBACK_LEN, &num);
1109 	if (ret < 0)
1110 		return CUPS_BACKEND_FAILED;
1111 
1112 	ret = read_data(ctx->dev, ctx->endp_up,
1113 			(uint8_t*) rdbuf, READBACK_LEN, &num);
1114 
1115 	if (ret < 0)
1116 		return CUPS_BACKEND_FAILED;
1117 
1118 	if (ctx->printer->error_detect(rdbuf))
1119 		ctx->marker.levelnow = 0;
1120 	else
1121 		ctx->marker.levelnow = -3;
1122 
1123 	*markers = &ctx->marker;
1124 	*count = 1;
1125 
1126 	return CUPS_BACKEND_OK;
1127 }
1128 
1129 static const char *canonselphy_prefixes[] = {
1130 	"canonselphy", // Family name
1131 	"canon-cp10", "canon-cp100", "canon-cp200", "canon-cp220",
1132 	"canon-cp300", "canon-cp330", "canon-cp400", "canon-cp500",
1133 	"canon-cp510", "canon-cp520", "canon-cp530", "canon-cp600",
1134 	"canon-cp710", "canon-cp720", "canon-cp730", "canon-cp740",
1135 	"canon-cp750", "canon-cp760", "canon-cp770", "canon-cp780",
1136 	"canon-cp790", "canon-cp800", "canon-cp810", "canon-cp900",
1137 	"canon-es1", "canon-es2", "canon-es20", "canon-es3",
1138 	"canon-es30", "canon-es40",
1139 	// backwards compatibility
1140 	"selphycp10", "selphycp100", "selphycp200", "selphycp220",
1141 	"selphycp300", "selphycp330", "selphycp400", "selphycp500",
1142 	"selphycp510", "selphycp520", "selphycp530", "selphycp600",
1143 	"selphycp710", "selphycp720", "selphycp730", "selphycp740",
1144 	"selphycp750", "selphycp760", "selphycp770", "selphycp780",
1145 	"selphycp790", "selphycp800", "selphycp810", "selphycp900",
1146 	"selphyes1", "selphyes2", "selphyes20", "selphyes3",
1147 	"selphyes30", "selphyes40",
1148 	NULL
1149 };
1150 
1151 struct dyesub_backend canonselphy_backend = {
1152 	.name = "Canon SELPHY CP/ES (legacy)",
1153 	.version = "0.104",
1154 	.uri_prefixes = canonselphy_prefixes,
1155 	.cmdline_usage = canonselphy_cmdline,
1156 	.cmdline_arg = canonselphy_cmdline_arg,
1157 	.init = canonselphy_init,
1158 	.attach = canonselphy_attach,
1159 	.read_parse = canonselphy_read_parse,
1160 	.cleanup_job = canonselphy_cleanup_job,
1161 	.main_loop = canonselphy_main_loop,
1162 	.query_markers = canonselphy_query_markers,
1163 	.devices = {
1164 		{ USB_VID_CANON, USB_PID_CANON_CP10, P_CP10, NULL, "canon-cp10"},
1165 		{ USB_VID_CANON, USB_PID_CANON_CP100, P_CP_XXX, NULL, "canon-cp100"},
1166 		{ USB_VID_CANON, USB_PID_CANON_CP200, P_CP_XXX, NULL, "canon-cp200"},
1167 		{ USB_VID_CANON, USB_PID_CANON_CP220, P_CP_XXX, NULL, "canon-cp220"},
1168 		{ USB_VID_CANON, USB_PID_CANON_CP300, P_CP_XXX, NULL, "selpyhcp300"},
1169 		{ USB_VID_CANON, USB_PID_CANON_CP330, P_CP_XXX, NULL, "canon-cp330"},
1170 		{ USB_VID_CANON, USB_PID_CANON_CP400, P_CP_XXX, NULL, "canon-cp400"},
1171 		{ USB_VID_CANON, USB_PID_CANON_CP500, P_CP_XXX, NULL, "canon-cp500"},
1172 		{ USB_VID_CANON, USB_PID_CANON_CP510, P_CP_XXX, NULL, "canon-cp510"},
1173 		{ USB_VID_CANON, USB_PID_CANON_CP520, P_CP_XXX, NULL, "canon-cp520"},
1174 		{ USB_VID_CANON, USB_PID_CANON_CP530, P_CP_XXX, NULL, "canon-cp530"},
1175 		{ USB_VID_CANON, USB_PID_CANON_CP600, P_CP_XXX, NULL, "canon-cp600"},
1176 		{ USB_VID_CANON, USB_PID_CANON_CP710, P_CP_XXX, NULL, "canon-cp710"},
1177 		{ USB_VID_CANON, USB_PID_CANON_CP720, P_CP_XXX, NULL, "canon-cp720"},
1178 		{ USB_VID_CANON, USB_PID_CANON_CP730, P_CP_XXX, NULL, "canon-cp730"},
1179 		{ USB_VID_CANON, USB_PID_CANON_CP740, P_CP_XXX, NULL, "canon-cp740"},
1180 		{ USB_VID_CANON, USB_PID_CANON_CP750, P_CP_XXX, NULL, "canon-cp750"},
1181 		{ USB_VID_CANON, USB_PID_CANON_CP760, P_CP_XXX, NULL, "canon-cp760"},
1182 		{ USB_VID_CANON, USB_PID_CANON_CP770, P_CP_XXX, NULL, "canon-cp770"},
1183 		{ USB_VID_CANON, USB_PID_CANON_CP780, P_CP_XXX, NULL, "canon-cp780"},
1184 		{ USB_VID_CANON, USB_PID_CANON_CP790, P_CP790, NULL, "canon-cp790"},
1185 		{ USB_VID_CANON, USB_PID_CANON_CP800, P_CP_XXX, NULL, "canon-cp800"},
1186 		{ USB_VID_CANON, USB_PID_CANON_CP810, P_CP_XXX, NULL, "canon-cp810"},
1187 		{ USB_VID_CANON, USB_PID_CANON_CP900, P_CP_XXX, NULL, "canon-cp900"},
1188 		{ USB_VID_CANON, USB_PID_CANON_ES1, P_ES1, NULL, "canon-es1"},
1189 		{ USB_VID_CANON, USB_PID_CANON_ES2, P_ES2_20, NULL, "canon-es2"},
1190 		{ USB_VID_CANON, USB_PID_CANON_ES20, P_ES2_20, NULL, "canon-es20"},
1191 		{ USB_VID_CANON, USB_PID_CANON_ES3, P_ES3_30, NULL, "canon-es3"},
1192 		{ USB_VID_CANON, USB_PID_CANON_ES30, P_ES3_30, NULL, "canon-es30"},
1193 		{ USB_VID_CANON, USB_PID_CANON_ES40, P_ES40, NULL, "canon-es40"},
1194 		{ 0, 0, 0, NULL, NULL}
1195 	}
1196 };
1197 /*
1198 
1199  ***************************************************************************
1200 
1201 	Stream formats and readback codes for supported printers
1202 
1203  ***************************************************************************
1204  Selphy ES1:
1205 
1206    Init func:   40 00 [typeA] [pgcode]  00 00 00 00  00 00 00 00
1207    Plane func:  40 01 [typeB] [plane]  [length, 32-bit LE]  00 00 00 00
1208 
1209    TypeA codes are 0x10 for Color papers, 0x20 for B&W papers.
1210    TypeB codes are 0x01 for Color papers, 0x02 for B&W papers.
1211 
1212    Plane codes are 0x01, 0x03, 0x07 for Y, M, and C, respectively.
1213    B&W Jobs have a single plane code of 0x01.
1214 
1215    'P' papers pgcode of 0x11 and a plane length of 2227456 bytes
1216    'L'        pgcode of 0x12 and a plane length of 1601600 bytes.
1217    'C'        pgcode of 0x13 and a plane length of  698880 bytes.
1218 
1219    Readback values seen:
1220 
1221    02 00 00 00  02 01 [pg] 01  00 00 00 00   [idle, waiting for init seq]
1222    04 00 00 00  02 01 [pg] 01  00 00 00 00   [init received, not ready..]
1223    04 00 01 00  02 01 [pg] 01  00 00 00 00   [waiting for Y data]
1224    04 00 03 00  02 01 [pg] 01  00 00 00 00   [waiting for M data]
1225    04 00 07 00  02 01 [pg] 01  00 00 00 00   [waiting for C data]
1226    04 00 00 00  02 01 [pg] 01  00 00 00 00   [all data sent; not ready..]
1227    05 00 00 00  02 01 [pg] 01  00 00 00 00   [?? transitions to this]
1228    06 00 00 00  02 01 [pg] 01  00 00 00 00   [?? transitions to this]
1229    02 00 00 00  02 01 [pg] 01  00 00 00 00   [..transitions back to idle]
1230 
1231    02 01 00 00  01 ff ff ff  00 80 00 00     [error, no media]
1232    02 00 00 00  01 ff ff ff  00 00 00 00     [error, cover open]
1233    0f 00 00 00  02 01 01 01  00 00 00 00     [error, out of media]
1234 
1235    Known paper types for all ES printers:  P, Pbw, L, C, Cl
1236    Additional types for ES3/30/40:         Pg, Ps
1237 
1238    [pg] is:  0x01 for P-papers
1239    	     0x02 for L-papers
1240              0x03 for C-papers
1241 
1242  ***************************************************************************
1243  Selphy ES2/20:
1244 
1245    Init func:   40 00 [pgcode] 00  02 00 00 [type]  00 00 00 [pg2] [length, 32-bit LE]
1246    Plane func:  40 01 [plane] 00  00 00 00 00  00 00 00 00
1247 
1248    Type codes are 0x00 for Color papers, 0x01 for B&W papers.
1249 
1250    Plane codes are 0x01, 0x02, 0x03 for Y, M, and C, respectively.
1251    B&W Jobs have a single plane code of 0x01.
1252 
1253    'P' papers pgcode of 0x01 and a plane length of 2227456 bytes
1254    'L' 	      pgcode of 0x02 and a plane length of 1601600 bytes.
1255    'C'	      pgcode of 0x03 and a plane length of  698880 bytes.
1256 
1257    pg2 is 0x00 for all media types except for 'C', which is 0x01.
1258 
1259    Readback values seen on an ES2:
1260 
1261    02 00 00 00  [pg] 00 [pg2] [xx]  00 00 00 00   [idle, waiting for init seq]
1262    03 00 01 00  [pg] 00 [pg2] [xx]  00 00 00 00   [init complete, ready for Y]
1263    04 00 01 00  [pg] 00 [pg2] [xx]  00 00 00 00   [? paper loaded]
1264    05 00 01 00  [pg] 00 [pg2] [xx]  00 00 00 00   [? transitions to this]
1265    06 00 03 00  [pg] 00 [pg2] [xx]  00 00 00 00   [ready for M]
1266    08 00 03 00  [pg] 00 [pg2] [xx]  00 00 00 00   [? transitions to this]
1267    09 00 07 00  [pg] 00 [pg2] [xx]  00 00 00 00   [ready for C]
1268    09 00 00 00  [pg] 00 [pg2] 00  00 00 00 00   [? transitions to this]
1269    0b 00 00 00  [pg] 00 [pg2] 00  00 00 00 00   [? transitions to this]
1270    0c 00 00 00  [pg] 00 [pg2] 00  00 00 00 00   [? transitions to this]
1271    0f 00 00 00  [pg] 00 [pg2] 00  00 00 00 00   [? transitions to this]
1272    13 00 00 00  [pg] 00 [pg2] 00  00 00 00 00   [? transitions to this]
1273 
1274    14 00 00 00  [pg] 00 [pg2] 00  00 00 00 00   [out of paper/ink]
1275    14 00 01 00  [pg] 00 [pg2] 00  01 00 00 00   [out of paper/ink]
1276 
1277    16 01 00 00  [pg] 00 [pg2] 00  00 00 00 00   [error, cover open]
1278    02 00 00 00  05 05 02 00  00 00 00 00        [error, no media]
1279 
1280    [xx] can be 0x00 or 0xff, depending on if a previous print job has
1281 	completed or not.
1282 
1283    [pg] is:  0x01 for P-papers
1284    	     0x02 for L-papers
1285              0x03 for C-papers
1286 
1287    [pg2] is: 0x00 for Normal papers
1288              0x01 for Label papers
1289 
1290  ***************************************************************************
1291  Selphy ES3/30:
1292 
1293    Init func:   40 00 [pgcode] [type]  00 00 00 00  00 00 00 00 [length, 32-bit LE]
1294    Plane func:  40 01 [plane] 00  00 00 00 00  00 00 00 00
1295 
1296    End func:    40 20 00 00  00 00 00 00  00 00 00 00
1297 
1298    Type codes are 0x00 for Color papers, 0x01 for B&W papers.
1299 
1300    Plane codes are 0x01, 0x02, 0x03 for Y, M, and C, respectively.
1301    B&W Jobs have a single plane code of 0x01.
1302 
1303    'P' papers pgcode of 0x01 and a plane length of 2227456 bytes.
1304    'L' 	      pgcode of 0x02 and a plane length of 1601600 bytes.
1305    'C' 	      pgcode of 0x03 and a plane length of  698880 bytes.
1306 
1307    Readback values seen on an ES3 & ES30:
1308 
1309    00 ff 00 00  ff ff ff ff  00 00 00 00   [idle, waiting for init seq]
1310    01 ff 01 00  ff ff ff ff  00 00 00 00   [init complete, ready for Y]
1311    03 ff 01 00  ff ff ff ff  00 00 00 00   [?]
1312    03 ff 02 00  ff ff ff ff  00 00 00 00   [ready for M]
1313    05 ff 02 00  ff ff ff ff  00 00 00 00   [?]
1314    05 ff 03 00  ff ff ff ff  00 00 00 00   [ready for C]
1315    07 ff 03 00  ff ff ff ff  00 00 00 00   [?]
1316    0b ff 03 00  ff ff ff ff  00 00 00 00   [?]
1317    13 ff 03 00  ff ff ff ff  00 00 00 00   [?]
1318    00 ff 10 00  ff ff ff ff  00 00 00 00   [ready for footer]
1319 
1320    01 ff 10 00  ff ff ff ff  01 00 0f 00   [communication error]
1321    00 ff 01 00  ff ff ff ff  01 00 01 00   [error, no media/ink]
1322    00 ff 01 00  ff ff ff ff  05 00 01 00   [error, incorrect media]
1323    00 ff 01 00  ff ff ff ff  03 00 02 00   [attempt to print with no media]
1324    00 ff 01 00  ff ff ff ff  08 00 04 00   [attempt to print with cover open]
1325 
1326    There appears to be no paper code in the readback; codes were identical for
1327    the standard 'P-Color' and 'Cl' cartridges:
1328 
1329  ***************************************************************************
1330  Selphy ES40:
1331 
1332    Init func:   40 00 [pgcode] [type]  00 00 00 00  00 00 00 00 [length, 32-bit LE]
1333    Plane func:  40 01 [plane] 00  00 00 00 00  00 00 00 00
1334 
1335    End func:    40 20 00 00  00 00 00 00  00 00 00 00
1336 
1337    Type codes are 0x00 for Color papers, 0x01 for B&W papers.
1338 
1339    Plane codes are 0x01, 0x02, 0x03 for Y, M, and C, respectively.
1340    B&W Jobs have a single plane code of 0x01.
1341 
1342    'P' papers pgcode of 0x00 and a plane length of 2227456 bytes.
1343    'L' 	      pgcode of 0x01 and a plane length of 1601600 bytes.
1344    'C'	      pgcode of 0x02 and a plane length of  698880 bytes.
1345 
1346    Readback values seen on an ES40:
1347 
1348    00 00 ff 00  00 00 00 00  00 00 00 [pg]
1349    00 00 00 00  00 00 00 00  00 00 00 [pg]   [idle, ready for header]
1350    00 01 01 00  00 00 00 00  00 00 00 [pg]   [ready for Y data]
1351    00 03 01 00  00 00 00 00  00 00 00 [pg]   [transitions to this]
1352    00 03 02 00  00 00 00 00  00 00 00 [pg]   [ready for M data]
1353    00 05 02 00  00 00 00 00  00 00 00 [pg]   [transitions to this]
1354    00 05 03 00  00 00 00 00  00 00 00 [pg]   [ready for C data]
1355    00 07 03 00  00 00 00 00  00 00 00 [pg]   [transitions to this]
1356    00 0b ff 00  00 00 00 00  00 00 00 [pg]   [transitions to this]
1357    00 0e ff 00  00 00 00 00  00 00 00 [pg]   [transitions to this]
1358    00 00 10 00  00 00 00 00  00 00 00 [pg]   [ready for footer]
1359 
1360    00 ** ** [xx]  00 00 00 00  00 00 00 [pg] [error]
1361 
1362    [xx]:
1363 	01:  Generic communication error
1364 	32:  Cover open / media empty
1365 
1366    [pg] is as follows:
1367 
1368       'P' paper 0x11
1369       'L' paper 0x22
1370       'C' paper 0x33
1371       'W' paper 0x44
1372 
1373  ***************************************************************************
1374  Selphy CP790:
1375 
1376    Init func:   40 00 [pgcode] 00  00 00 00 00  00 00 00 00 [length, 32-bit LE]
1377    Plane func:  40 01 [plane] 00  00 00 00 00  00 00 00 00
1378 
1379    End func:    40 20 00 00  00 00 00 00  00 00 00 00
1380 
1381    Reset func:  40 10 00 00  00 00 00 00  00 00 00 00
1382 
1383    Plane codes are 0x01, 0x02, 0x03 for Y, M, and C, respectively.
1384 
1385    'P' papers pgcode of 0x00 and a plane length of 2227456 bytes.
1386    'L' 	      pgcode of 0x01 and a plane length of 1601600 bytes.
1387    'C'	      pgcode of 0x02 and a plane length of  698880 bytes.
1388    'W' 	      pgcode of 0x03 and a plane length of 2976512 bytes.
1389 
1390    Readback values seen on an CP790:
1391 
1392    00 00 ff 00  [pg1] [pg2] 00 00  00 00 00 02
1393    00 00 00 00  [pg1] [pg2] 00 00  00 00 00 02   [idle, ready for header]
1394    00 00 01 00  [pg1] [pg2] 00 00  00 00 00 02
1395    00 01 01 00  [pg1] [pg2] 00 00  00 00 00 02   [ready for Y data]
1396    00 03 01 00  [pg1] [pg2] 00 00  00 00 00 02   [transitions to this]
1397    00 03 02 00  [pg1] [pg2] 00 00  00 00 00 02   [ready for M data]
1398    00 05 02 00  [pg1] [pg2] 00 00  00 00 00 02   [transitions to this]
1399    00 05 03 00  [pg1] [pg2] 00 00  00 00 00 02   [ready for C data]
1400    00 0b ff 00  [pg1] [pg2] 00 00  00 00 00 02   [transitions to this]
1401    00 0e ff 00  [pg1] [pg2] 00 00  00 00 00 02   [transitions to this]
1402    00 00 10 00  [pg1] [pg2] 00 00  00 00 00 02   [ready for footer]
1403 
1404    [pg1] is:                  [pg2] is:
1405 
1406       0x00  'P' ribbon         0x00 'P' paper
1407       0x10  'L' ribbon         0x01 'L' paper
1408       0x20  'C' ribbon         0x02 'C' paper
1409       0x30  'W' ribbon         0x03 'W' paper
1410       0xff  NO RIBBON          0xff  NO PAPER TRAY
1411 
1412    Other readbacks seen:
1413 
1414    00 00 01 11  [pg1] [pg2] 00 00  00 00 00 02   [emptytray, ink match job ]
1415    00 00 01 12  [pg1] [pg2] 00 00  00 00 00 02   [ notray, ink match job ]
1416    00 00 01 13  [pg1] [pg2] 00 00  00 00 00 02   [ empty tray + mismatch ink ]
1417    00 00 01 21  [pg1] [pg2] 00 00  00 00 00 02   [ depleted ribbon, match ink ]
1418    00 00 01 22  [pg1] [pg2] 00 00  00 00 00 02   [ no paper tray ]
1419    00 00 01 23  [pg1] [pg2] 00 00  00 00 00 02   [ empty tray, ink mismatch ]
1420 
1421     Note : These error conditions are confusing.
1422 
1423  ***************************************************************************
1424  Selphy CP-10:
1425 
1426    Init func:   40 00 00 00  00 00 00 00  00 00 00 00
1427    Plane func:  40 01 00 [plane]  [length, 32-bit LE]  00 00 00 00
1428 
1429    plane codes are 0x00, 0x01, 0x02 for Y, M, and C, respectively.
1430 
1431    length is always '00 60 81 0a' which is 688480 bytes.
1432 
1433    Error clear: 40 10 00 00  00 00 00 00  00 00 00 00
1434 
1435    Known readback values:
1436 
1437    01 00 00 00  00 00 00 00  00 00 00 00   [idle, waiting for init]
1438    02 00 00 00  00 00 00 00  00 00 00 00   [init sent, paper feeding]
1439    02 00 00 00  00 00 00 00  00 00 00 00   [init sent, paper feeding]
1440    02 00 00 00  00 00 00 00  00 00 00 00   [waiting for Y data]
1441    04 00 00 00  00 00 00 00  00 00 00 00   [waiting for M data]
1442    08 00 00 00  00 00 00 00  00 00 00 00   [waiting for C data]
1443    10 00 00 00  00 00 00 00  00 00 00 00   [C done, waiting]
1444    20 00 00 00  00 00 00 00  00 00 00 00   [All done]
1445 
1446    02 00 80 00  00 00 00 00  00 00 00 00   [No ribbon]
1447    02 00 80 00  00 00 00 00  00 00 00 00   [Ribbon depleted]
1448    02 00 01 00  00 00 00 00  00 00 00 00   [No paper]
1449 
1450   There are no media type codes; the printer only supports one type.
1451 
1452  ***************************************************************************
1453  Selphy CP-series (except for CP790 & CP-10):
1454 
1455     This is known to apply to:
1456 	CP-100, CP-200, CP-300, CP-330, CP400, CP500, CP510, CP710,
1457 	CP720, CP730, CP740, CP750, CP760, CP770, CP780, CP800, CP900
1458 
1459    Init func:   40 00 00 [pgcode]  00 00 00 00  00 00 00 00
1460    Plane func:  40 01 00 [plane]  [length, 32-bit LE]  00 00 00 00
1461    End func:    00 00 00 00       # NOTE: Present (and necessary) on CP900 only.
1462 
1463    Error clear: 40 10 00 00  00 00 00 00  00 00 00 00
1464 
1465    plane codes are 0x00, 0x01, 0x02 for Y, M, and C, respectively.
1466 
1467    'P' papers pgcode 0x01   plane length 2227456 bytes.
1468    'L' 	      pgcode 0x02   plane length 1601600 bytes.
1469    'C' 	      pgcode 0x03   plane length  698880 bytes.
1470    'W'	      pgcode 0x04   plane length 2976512 bytes.
1471 
1472    Known readback values:
1473 
1474    01 00 00 00  [ss] 00 [pg] [zz]  00 00 00 [xx]   [idle, waiting for init]
1475    02 00 [rr] 00  00 00 [pg] [zz]  00 00 00 [xx]   [init sent, paper feeding]
1476    02 00 [rr] 00  10 00 [pg] [zz]  00 00 00 [xx]   [init sent, paper feeding]
1477    02 00 [rr] 00  70 00 [pg] [zz]  00 00 00 [xx]   [waiting for Y data]
1478    04 00 00 00  00 00 [pg] [zz]  00 00 00 [xx]   [waiting for M data]
1479    08 00 00 00  00 00 [pg] [zz]  00 00 00 [xx]   [waiting for C data]
1480    10 00 00 00  00 00 [pg] [zz]  00 00 00 [xx]   [C done, waiting]
1481    20 00 00 00  00 00 [pg] [zz]  00 00 00 [xx]   [All done]
1482 
1483    [xx] is 0x01 on the CP780/CP800/CP900, 0x00 on all others.
1484 
1485    [rr] is error code:
1486    	0x00 no error
1487 	0x01 paper out
1488 	0x04 ribbon problem
1489 	0x08 ribbon depleted
1490 
1491    [ss] is either 0x00 or 0x70.  Unsure as to its significance; perhaps it
1492 	means paper or ribbon is already set to go?
1493 
1494    [pg] is as follows:
1495 
1496       'P' paper 0x11
1497       'L' paper 0x22
1498       'C' paper 0x33
1499       'W' paper 0x44
1500 
1501       First four bits are paper, second four bits are the ribbon.  They aren't
1502       necessarily identical.  So it's possible to have a code of, say,
1503       0x41 if the 'Wide' paper tray is loaded with a 'P' ribbon. A '0' is used
1504       to signify nothing being loaded.
1505 
1506    [zz] is 0x01 when on battery power, 0x00 otherwise.
1507 
1508 */
1509