1 /*
2  *   Canon SELPHY CPneo series CUPS backend -- libusb-1.0 version
3  *
4  *   (c) 2016-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 canonselphyneo_backend
40 
41 #include "backend_common.h"
42 
43 /* Exported */
44 #define USB_VID_CANON        0x04a9
45 #define USB_PID_CANON_CP820  0x327b
46 #define USB_PID_CANON_CP910  0x327a
47 #define USB_PID_CANON_CP1000 0x32ae
48 #define USB_PID_CANON_CP1200 0x32b1
49 #define USB_PID_CANON_CP1300 0x32db
50 
51 /* Header data structure */
52 struct selphyneo_hdr {
53 	uint8_t data[24];
54 	uint32_t cols;  /* LE */
55 	uint32_t rows;  /* LE */
56 } __attribute((packed));
57 
58 /* Readback data structure */
59 struct selphyneo_readback {
60 	uint8_t data[12];
61 } __attribute((packed));
62 
63 /* Private data structure */
64 struct selphyneo_printjob {
65 	uint8_t *databuf;
66 	uint32_t datalen;
67 
68 	int copies;
69 };
70 
71 struct selphyneo_ctx {
72 	struct libusb_device_handle *dev;
73 	uint8_t endp_up;
74 	uint8_t endp_down;
75 	int type;
76 
77 	struct marker marker;
78 };
79 
selphyneo_statuses(uint8_t sts)80 static char *selphyneo_statuses(uint8_t sts)
81 {
82 	switch(sts) {
83 	case 0x01:
84 		return "Idle";
85 	case 0x02:
86 		return "Feeding Paper";
87 	case 0x04:
88 		return "Printing YELLOW";
89 	case 0x08:
90 		return "Printing MAGENTA";
91 	case 0x10:
92 		return "Printing CYAN";
93 	case 0x20:
94 		return "Printing LAMINATE";
95 	default:
96 		return "Unknown state!";
97 	}
98 }
99 
selphyneo_errors(uint8_t err)100 static char *selphyneo_errors(uint8_t err)
101 {
102 	switch(err) {
103 	case 0x00:
104 		return "None";
105 	case 0x02:
106 		return "Paper Feed";
107 	case 0x03:
108 		return "No Paper";
109 	case 0x05:
110 		return "Incorrect Paper loaded";
111 	case 0x06:
112 		return "Ink Cassette Empty";
113 	case 0x07:
114 		return "No Ink";
115 	case 0x09:
116 		return "No Paper and Ink";
117 	case 0x0A:
118 		return "Incorrect media for job";
119 	case 0x0B:
120 		return "Paper jam";
121 	default:
122 		return "Unknown Error";
123 	}
124 }
125 
selphynew_pgcodes(uint8_t type)126 static char *selphynew_pgcodes(uint8_t type) {
127 
128 	switch (type & 0xf) {
129 	case 0x01:
130 		return "P";
131 	case 0x02:
132 		return "L";
133 	case 0x03:
134 		return "C";
135 	case 0x00:
136 		return "None";
137 	default:
138 		return "Unknown";
139 	}
140 }
141 
selphyneo_send_reset(struct selphyneo_ctx * ctx)142 static int selphyneo_send_reset(struct selphyneo_ctx *ctx)
143 {
144 	uint8_t rstcmd[12] = { 0x40, 0x10, 0x00, 0x00,
145 			       0x00, 0x00, 0x00, 0x00,
146 			       0x00, 0x00, 0x00, 0x00 };
147 	int ret;
148 
149 	if ((ret = send_data(ctx->dev, ctx->endp_down,
150 			     rstcmd, sizeof(rstcmd))))
151 		return CUPS_BACKEND_FAILED;
152 
153 	return CUPS_BACKEND_OK;
154 }
155 
selphyneo_get_status(struct selphyneo_ctx * ctx)156 static int selphyneo_get_status(struct selphyneo_ctx *ctx)
157 {
158 	struct selphyneo_readback rdback;
159 	int ret, num;
160 
161 	/* Read in the printer status to clear last state */
162 	ret = read_data(ctx->dev, ctx->endp_up,
163 			(uint8_t*) &rdback, sizeof(rdback), &num);
164 
165 	if (ret < 0)
166 		return CUPS_BACKEND_FAILED;
167 
168 	/* And again, for the markers */
169 	ret = read_data(ctx->dev, ctx->endp_up,
170 			(uint8_t*) &rdback, sizeof(rdback), &num);
171 
172 	if (ret < 0)
173 		return CUPS_BACKEND_FAILED;
174 
175 	INFO("Printer state: %s\n", selphyneo_statuses(rdback.data[0]));
176 	INFO("Media type: %s\n", selphynew_pgcodes(rdback.data[6]));
177 	if (rdback.data[2]) {
178 		INFO("Printer error: %s\n", selphyneo_errors(rdback.data[2]));
179 	}
180 
181 	return CUPS_BACKEND_OK;
182 }
183 
selphyneo_init(void)184 static void *selphyneo_init(void)
185 {
186 	struct selphyneo_ctx *ctx = malloc(sizeof(struct selphyneo_ctx));
187 	if (!ctx) {
188 		ERROR("Memory Allocation Failure!\n");
189 		return NULL;
190 	}
191 	memset(ctx, 0, sizeof(struct selphyneo_ctx));
192 
193 	return ctx;
194 }
195 
196 extern struct dyesub_backend selphyneo_backend;
197 
selphyneo_attach(void * vctx,struct libusb_device_handle * dev,int type,uint8_t endp_up,uint8_t endp_down,uint8_t jobid)198 static int selphyneo_attach(void *vctx, struct libusb_device_handle *dev, int type,
199 			    uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
200 {
201 	struct selphyneo_ctx *ctx = vctx;
202 	struct selphyneo_readback rdback;
203 	int ret, num;
204 
205 	UNUSED(jobid);
206 
207 	ctx->dev = dev;
208 	ctx->endp_up = endp_up;
209 	ctx->endp_down = endp_down;
210 	ctx->type = type;
211 
212 	if (test_mode < TEST_MODE_NOATTACH) {
213 		/* Read in the printer status to clear last state */
214 		ret = read_data(ctx->dev, ctx->endp_up,
215 				(uint8_t*) &rdback, sizeof(rdback), &num);
216 
217 		if (ret < 0)
218 			return CUPS_BACKEND_FAILED;
219 
220 		/* And again, for the markers */
221 		ret = read_data(ctx->dev, ctx->endp_up,
222 				(uint8_t*) &rdback, sizeof(rdback), &num);
223 
224 		if (ret < 0)
225 			return CUPS_BACKEND_FAILED;
226 	} else {
227 		rdback.data[2] = 0;
228 		rdback.data[6] = 0x01;
229 		if (getenv("MEDIA_CODE"))
230 			rdback.data[6] = atoi(getenv("MEDIA_CODE"));
231 	}
232 
233 	ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
234 	ctx->marker.name = selphynew_pgcodes(rdback.data[6]);
235 	ctx->marker.levelmax = -1;
236 	if (rdback.data[2]) {
237 		ctx->marker.levelnow = 0;
238 	} else {
239 		ctx->marker.levelnow = -3;
240 	}
241 
242 	return CUPS_BACKEND_OK;
243 }
244 
selphyneo_cleanup_job(const void * vjob)245 static void selphyneo_cleanup_job(const void *vjob) {
246 	const struct selphyneo_printjob *job = vjob;
247 
248 	if (job->databuf)
249 		free(job->databuf);
250 
251 	free((void*)job);
252 }
253 
selphyneo_read_parse(void * vctx,const void ** vjob,int data_fd,int copies)254 static int selphyneo_read_parse(void *vctx, const void **vjob, int data_fd, int copies)
255 {
256 	struct selphyneo_ctx *ctx = vctx;
257 	struct selphyneo_hdr hdr;
258 	int i, remain;
259 
260 	struct selphyneo_printjob *job = NULL;
261 
262 	if (!ctx)
263 		return CUPS_BACKEND_FAILED;
264 
265 	job = malloc(sizeof(*job));
266 	if (!job) {
267 		ERROR("Memory allocation failure!\n");
268 		return CUPS_BACKEND_RETRY_CURRENT;
269 	}
270 	memset(job, 0, sizeof(*job));
271 	job->copies = copies;
272 
273 	/* Read the header.. */
274 	i = read(data_fd, &hdr, sizeof(hdr));
275 	if (i != sizeof(hdr)) {
276 		if (i == 0) {
277 			selphyneo_cleanup_job(job);
278 			return CUPS_BACKEND_CANCEL;
279 		}
280 		ERROR("Read failed (%d/%d)\n",
281 		      i, (int)sizeof(hdr));
282 		perror("ERROR: Read failed");
283 		selphyneo_cleanup_job(job);
284 		return CUPS_BACKEND_FAILED;
285 	}
286 
287 	/* Determine job length */
288 	switch(hdr.data[18]) {
289 	case 0x50:  /* P */
290 	case 0x4c:  /* L */
291 	case 0x43:  /* C */
292 		remain = le32_to_cpu(hdr.cols) * le32_to_cpu(hdr.rows) * 3;
293 		break;
294 	default:
295 		ERROR("Unknown print size! (%02x, %ux%u)\n",
296 		      hdr.data[10], le32_to_cpu(hdr.cols), le32_to_cpu(hdr.rows));
297 		selphyneo_cleanup_job(job);
298 		return CUPS_BACKEND_CANCEL;
299 	}
300 
301 	// XXX Sanity check job against loaded media?
302 
303 	/* Allocate a buffer */
304 	job->datalen = 0;
305 	job->databuf = malloc(remain + sizeof(hdr));
306 	if (!job->databuf) {
307 		ERROR("Memory allocation failure!\n");
308 		selphyneo_cleanup_job(job);
309 		return CUPS_BACKEND_RETRY_CURRENT;
310 	}
311 
312 	/* Store the read-in header */
313 	memcpy(job->databuf, &hdr, sizeof(hdr));
314 	job->datalen += sizeof(hdr);
315 
316 	/* Read in data */
317 	while (remain > 0) {
318 		i = read(data_fd, job->databuf + job->datalen, remain);
319 		if (i < 0) {
320 			selphyneo_cleanup_job(job);
321 			return CUPS_BACKEND_CANCEL;
322 		}
323 		remain -= i;
324 		job->datalen += i;
325 	}
326 
327 	*vjob = job;
328 
329 	return CUPS_BACKEND_OK;
330 }
331 
selphyneo_main_loop(void * vctx,const void * vjob)332 static int selphyneo_main_loop(void *vctx, const void *vjob) {
333 	struct selphyneo_ctx *ctx = vctx;
334 	struct selphyneo_readback rdback;
335 
336 	int ret, num;
337 	int copies;
338 
339 	const struct selphyneo_printjob *job = vjob;
340 
341 	if (!ctx)
342 		return CUPS_BACKEND_FAILED;
343 	if (!job)
344 		return CUPS_BACKEND_FAILED;
345 
346 	copies = job->copies;
347 
348 	/* Read in the printer status to clear last state */
349 	ret = read_data(ctx->dev, ctx->endp_up,
350 			(uint8_t*) &rdback, sizeof(rdback), &num);
351 
352 	if (ret < 0)
353 		return CUPS_BACKEND_FAILED;
354 
355 top:
356 	INFO("Waiting for printer idle\n");
357 
358 	do {
359 		ret = read_data(ctx->dev, ctx->endp_up,
360 				(uint8_t*) &rdback, sizeof(rdback), &num);
361 
362 		if (ret < 0)
363 			return CUPS_BACKEND_FAILED;
364 
365 		if (rdback.data[0] == 0x01)
366 			break;
367 
368 		INFO("Printer state: %s\n", selphyneo_statuses(rdback.data[0]));
369 
370 		switch (rdback.data[2]) {
371 		case 0x00:
372 			break;
373 		case 0x0A:
374 			ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
375 			ctx->marker.levelnow = 0;
376 			dump_markers(&ctx->marker, 1, 0);
377 			return CUPS_BACKEND_CANCEL;
378 		default:
379 			ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
380 			ctx->marker.levelnow = 0;
381 			dump_markers(&ctx->marker, 1, 0);
382 			return CUPS_BACKEND_STOP;
383 		}
384 
385 		sleep(1);
386 	} while(1);
387 
388 	dump_markers(&ctx->marker, 1, 0);
389 
390 	INFO("Sending spool data\n");
391 	/* Send the data over in 256K chunks */
392 	{
393 		int chunk = 256*1024;
394 		int sent = 0;
395 		while (chunk > 0) {
396 			if ((ret = send_data(ctx->dev, ctx->endp_down,
397 					     job->databuf + sent, chunk)))
398 				return CUPS_BACKEND_FAILED;
399 			sent += chunk;
400 			chunk = job->datalen - sent;
401 			if (chunk > 256*1024)
402 				chunk = 256*1024;
403 		}
404 	}
405 
406 	/* Read in the printer status to clear last state */
407 	ret = read_data(ctx->dev, ctx->endp_up,
408 			(uint8_t*) &rdback, sizeof(rdback), &num);
409 
410 	if (ret < 0)
411 		return CUPS_BACKEND_FAILED;
412 
413 	INFO("Waiting for printer acknowledgement\n");
414 	do {
415 		ret = read_data(ctx->dev, ctx->endp_up,
416 				(uint8_t*) &rdback, sizeof(rdback), &num);
417 
418 		if (ret < 0)
419 			return CUPS_BACKEND_FAILED;
420 
421 		if (rdback.data[0] == 0x01)
422 			break;
423 
424 		INFO("Printer state: %s\n", selphyneo_statuses(rdback.data[0]));
425 
426 		switch (rdback.data[2]) {
427 		case 0x00:
428 			break;
429 		case 0x0A:
430 			ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
431 			ctx->marker.levelnow = 0;
432 			dump_markers(&ctx->marker, 1, 0);
433 			return CUPS_BACKEND_CANCEL;
434 		default:
435 			ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
436 			ctx->marker.levelnow = 0;
437 			dump_markers(&ctx->marker, 1, 0);
438 			return CUPS_BACKEND_STOP;
439 		}
440 
441 		if (rdback.data[0] > 0x02 && fast_return && copies <= 1) {
442 			INFO("Fast return mode enabled.\n");
443 			break;
444 		}
445 
446 		sleep(1);
447 	} while(1);
448 
449 	/* Clean up */
450 	if (terminate)
451 		copies = 1;
452 
453 	INFO("Print complete (%d copies remaining)\n", copies - 1);
454 
455 	if (copies && --copies) {
456 		goto top;
457 	}
458 
459 	return CUPS_BACKEND_OK;
460 }
461 
selphyneo_cmdline_arg(void * vctx,int argc,char ** argv)462 static int selphyneo_cmdline_arg(void *vctx, int argc, char **argv)
463 {
464 	struct selphyneo_ctx *ctx = vctx;
465 	int i, j = 0;
466 
467 	if (!ctx)
468 		return -1;
469 
470 	while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "Rs")) >= 0) {
471 		switch(i) {
472 		GETOPT_PROCESS_GLOBAL
473 		case 'R':
474 			selphyneo_send_reset(ctx);
475 			break;
476 		case 's':
477 			selphyneo_get_status(ctx);
478 			break;
479 		}
480 
481 		if (j) return j;
482 	}
483 
484 	return 0;
485 }
486 
selphyneo_cmdline(void)487 static void selphyneo_cmdline(void)
488 {
489 	DEBUG("\t\t[ -R ]           # Reset printer\n");
490 	DEBUG("\t\t[ -s ]           # Query printer status\n");
491 }
492 
selphyneo_query_markers(void * vctx,struct marker ** markers,int * count)493 static int selphyneo_query_markers(void *vctx, struct marker **markers, int *count)
494 {
495 	struct selphyneo_ctx *ctx = vctx;
496 	struct selphyneo_readback rdback;
497 	int ret, num;
498 
499 	/* Read in the printer status to clear last state */
500 	ret = read_data(ctx->dev, ctx->endp_up,
501 			(uint8_t*) &rdback, sizeof(rdback), &num);
502 
503 	if (ret < 0)
504 		return CUPS_BACKEND_FAILED;
505 
506 	/* And again, for the markers */
507 	ret = read_data(ctx->dev, ctx->endp_up,
508 			(uint8_t*) &rdback, sizeof(rdback), &num);
509 
510 	if (ret < 0)
511 		return CUPS_BACKEND_FAILED;
512 
513 	if (rdback.data[2])
514 		ctx->marker.levelnow = 0;
515 	else
516 		ctx->marker.levelnow = -3;
517 
518 	*markers = &ctx->marker;
519 	*count = 1;
520 
521 	return CUPS_BACKEND_OK;
522 }
523 
524 static const char *canonselphyneo_prefixes[] = {
525 	"canonselphyneo", // Family name
526 	"canon-cp820", "canon-cp910", "canon-cp1000", "canon-cp1200", "canon-cp1300",
527 	// backwards compatibility
528 	"selphycp820", "selphycp910", "selphycp1000", "selphycp1200", "selphycp1300",
529 	NULL
530 };
531 
532 struct dyesub_backend canonselphyneo_backend = {
533 	.name = "Canon SELPHY CP (new)",
534 	.version = "0.20",
535 	.uri_prefixes = canonselphyneo_prefixes,
536 	.cmdline_usage = selphyneo_cmdline,
537 	.cmdline_arg = selphyneo_cmdline_arg,
538 	.init = selphyneo_init,
539 	.attach = selphyneo_attach,
540 	.cleanup_job = selphyneo_cleanup_job,
541 	.read_parse = selphyneo_read_parse,
542 	.main_loop = selphyneo_main_loop,
543 	.query_markers = selphyneo_query_markers,
544 	.devices = {
545 		{ USB_VID_CANON, USB_PID_CANON_CP820, P_CP910, NULL, "canon-cp820"},
546 		{ USB_VID_CANON, USB_PID_CANON_CP910, P_CP910, NULL, "canon-cp910"},
547 		{ USB_VID_CANON, USB_PID_CANON_CP1000, P_CP910, NULL, "canon-cp1000"},
548 		{ USB_VID_CANON, USB_PID_CANON_CP1200, P_CP910, NULL, "canon-cp1200"},
549 		{ USB_VID_CANON, USB_PID_CANON_CP1300, P_CP910, NULL, "canon-cp1300"},
550 		{ 0, 0, 0, NULL, NULL}
551 	}
552 };
553 /*
554 
555  ***************************************************************************
556 
557 	Stream formats and readback codes for supported printers
558 
559  ***************************************************************************
560  Selphy CP820/CP910/CP1000/CP1200:
561 
562   Radically different spool file format!  300dpi, same print sizes, but also
563   adding a 50x50mm sticker and 22x17.3mm ministickers, though I think the
564   driver treats all of those as 'C' sizes for printing purposes.
565 
566   32-byte header:
567 
568   0f 00 00 40 00 00 00 00  00 00 00 00 00 00 01 00
569   01 00 TT 00 00 00 00 ZZ  XX XX XX XX YY YY YY YY
570 
571                            cols (le32) rows (le32)
572         50                 e0 04       50 07          1248 * 1872  (P)
573         4c                 80 04       c0 05          1152 * 1472  (L)
574         43                 40 04       9c 02          1088 * 668   (C)
575 
576   TT == 50  (P)
577      == 4c  (L)
578      == 43  (C)
579 
580   ZZ == 00  Y'CbCr data follows
581      == 01  CMY    data follows
582 
583   Followed by three planes of image data.
584 
585   P == 7008800  == 2336256 * 3 + 32 (1872*1248)
586   L == 5087264  == 1695744 * 3 + 32 (1472*1152)
587   C == 2180384  == 726784 * 3 + 32  (1088*668)
588 
589   It is worth mentioning that the Y'CbCr image data is surmised to use the
590   JPEG coefficients, although we realistically have no way of confirming this.
591 
592   Other questions:
593 
594     * Printer supports different lamination types, how to control?
595 
596  Data Readback:
597 
598  XX 00 YY 00  00 00 ZZ 00 00 00 00 00
599 
600  XX == Status
601 
602    01  Idle
603    02  Feeding Paper
604    04  Printing Y
605    08  Printing M
606    10  Printing C
607    20  Printing L
608 
609  YY == Error
610 
611    00  None
612    02  No Paper (?)
613    03  No Paper
614    05  Wrong Paper
615    07  No Ink
616    09  No Paper and Ink
617    0A  Media/Job mismatch
618    0B  Paper Jam
619 
620  ZZ == Media?
621 
622    01
623    10
624    11
625     ^-- Ribbon
626    ^-- Paper
627 
628    1 == P
629    2 == L ??
630    3 == C
631 
632 Also, the first time a readback happens after plugging in the printer:
633 
634 34 44 35 31  01 00 01 00  01 00 45 00      "4D51" ...??
635 
636 
637 ** ** ** ** This is what windows sends if you print over the network:
638 
639 00 00 00 00 40 00 00 00  02 00 00 00 00 00 04 00  Header [unknown]
640 00 00 02 00 00 00 00 00  00 00 00 00 00 00 00 00
641 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
642 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
643 
644 00 00 01 00 HH HH HH HH  02 00 00 00 PP PP PP PP  Header2 [unknown] PP == payload len, HH == payload + header2 len [ie + 3 ]
645 CC CC CC CC RR RR RR RR  00 00 00 00 LL LL LL LL  CC == cols, RR == rows, LL == plane len (ie RR * CC)
646 L2 L2 L2 L2                                       L2 == LL * 2, apparently.
647 
648 [ ..followed by three planes of LL bytes, totalling PP bytes.. ]
649 
650 */
651