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