1 /*
2  *   Shinko/Sinfonia CHC-S1245 CUPS backend -- libusb-1.0 version
3  *
4  *   (c) 2015-2019 Solomon Peachy <pizza@shaftnet.org>
5  *
6  *   Low-level documentation was provided by Sinfonia, Inc.  Thank you!
7  *
8  *   The latest version of this program can be found at:
9  *
10  *     http://git.shaftnet.org/cgit/selphy_print.git
11  *
12  *   This program is free software; you can redistribute it and/or modify it
13  *   under the terms of the GNU General Public License as published by the Free
14  *   Software Foundation; either version 2 of the License, or (at your option)
15  *   any later version.
16  *
17  *   This program is distributed in the hope that it will be useful, but
18  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  *   for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
24  *
25  *          [http://www.gnu.org/licenses/gpl-2.0.html]
26  *
27  *   SPDX-License-Identifier: GPL-2.0+
28  *
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <signal.h>
40 
41 #define BACKEND shinkos1245_backend
42 
43 #include "backend_common.h"
44 #include "backend_sinfonia.h"
45 
46 /* Printer data structures */
47 struct shinkos1245_cmd_hdr {
48 	uint8_t prefix; /* 0x03 */
49 	uint8_t hdr[4]; /* 0x1b 0x43 0x48 0x43 */
50 } __attribute__((packed));
51 
52 /* Get Printer ID */
53 struct shinkos1245_cmd_getid {
54 	struct shinkos1245_cmd_hdr hdr;
55 	uint8_t cmd[1]; /* 0x12 */
56 	uint8_t pad[11];
57 } __attribute__((packed));
58 
59 struct shinkos1245_resp_getid {
60 	uint8_t id;       /* 0x00 */
61 	uint8_t data[23]; /* padded with 0x20 (space) */
62 	uint8_t reserved[8]; // XXX actual serial number?
63 } __attribute__((packed));
64 
65 /* Set Printer ID -- Returns Status */
66 struct shinkos1245_cmd_setid {
67 	struct shinkos1245_cmd_hdr hdr;
68 	uint8_t cmd[2];   /* 0x0a 0x22 */
69 	uint8_t id;       /* 0x00 */
70 	uint8_t data[23]; /* pad with 0x20 (space) */
71 } __attribute__((packed));
72 
73 /* Print -- Returns Status */
74 struct shinkos1245_cmd_print {
75 	struct shinkos1245_cmd_hdr hdr;
76 	uint8_t  cmd[2];   /* 0x0a 0x00 */
77 	uint8_t  id;       /* 1-255 */
78 	uint16_t count;    /* # Copies in BCD, 1-9999 */
79 	uint16_t columns;  /* Fixed at 2446 */
80 	uint16_t rows;
81 	uint8_t  media;    /* Fixed at 0x10 */
82 	uint8_t  mode;     /* dust removal and lamination mode */
83 	uint8_t  combo;    /* aka "print method" in the spool file */
84 } __attribute__((packed));
85 
86 /* Get Status */
87 struct shinkos1245_cmd_getstatus {
88 	struct shinkos1245_cmd_hdr hdr;
89 	uint8_t cmd[1];   /* 0x03 */
90 	uint8_t pad[10];
91 } __attribute__((packed));
92 
93 struct shinkos1245_resp_status {
94 	uint8_t  code;
95 	uint8_t  print_status;
96 	struct {
97 		uint8_t  status1;
98 		uint32_t status2; /* BE */
99 		uint8_t  error;
100 	} __attribute__((packed)) state;
101 	struct {
102 		uint32_t lifetime;  /* BE */
103 		uint32_t maint;     /* BE */
104 		uint32_t media;     /* BE */
105 		uint32_t cutter;    /* BE */
106 		uint8_t  reserved;
107 		uint8_t  ver_boot;
108 		uint8_t  ver_ctrl;
109 		uint8_t  control_flag; // 0x00 == epson, 0x01 == cypress
110 	} __attribute__((packed)) counters;
111 	struct {
112 		uint16_t main_boot;
113 		uint16_t main_control;
114 		uint16_t dsp_boot;
115 		uint16_t dsp_control;
116 	} __attribute__((packed)) versions;
117 	struct {
118 		uint8_t  bank1_id;
119 		uint8_t  bank2_id;
120 		uint16_t bank1_remain;   /* BE */
121 		uint16_t bank1_complete; /* BE */
122 		uint16_t bank1_spec;     /* BE */
123 		uint16_t bank2_remain;   /* BE */
124 		uint16_t bank2_complete; /* BE */
125 		uint16_t bank2_spec;     /* BE */
126 	} __attribute__((packed)) counters2;
127 	uint8_t curve_status;
128 } __attribute__((packed));
129 
130 /* Query media info */
131 struct shinkos1245_cmd_getmedia {
132 	struct shinkos1245_cmd_hdr hdr;
133 	uint8_t cmd[1];   /* 0x1a/0x2a/0x3a for A/B/C */
134 	uint8_t pad[10];
135 } __attribute__((packed));
136 
137 #define NUM_MEDIAS 5 /* Maximum per message */
138 
139 struct shinkos1245_resp_media {
140 	uint8_t  code;
141 	uint8_t  reserved[6];
142 	uint8_t  count;  /* 1-5? */
143 	struct sinfonia_mediainfo_item data[NUM_MEDIAS];
144 } __attribute__((packed));
145 
146 
147 enum {
148 	PRINT_TYPE_STANDARD = 0x00,
149 	PRINT_TYPE_8x5_2up  = 0x01,
150 	PRINT_TYPE_8x4_2up  = 0x02,
151 	PRINT_TYPE_8x6_8x4  = 0x03,
152 	PRINT_TYPE_8x5      = 0x04,
153 	PRINT_TYPE_8x4      = 0x05,
154 	PRINT_TYPE_8x6      = 0x06,
155 	PRINT_TYPE_8x6_2up  = 0x07,
156 	PRINT_TYPE_8x4_3up  = 0x08,
157 	PRINT_TYPE_8x8      = 0x09,
158 };
159 
160 /* Cancel Job -- returns Status */
161 struct shinkos1245_cmd_canceljob {
162 	struct shinkos1245_cmd_hdr hdr;
163 	uint8_t cmd[1];   /* 0x13 */
164 	uint8_t id;       /* 1-255 */
165 	uint8_t pad[9];
166 } __attribute__((packed));
167 
168 /* Reset printer -- returns Status */
169 struct shinkos1245_cmd_reset {
170 	struct shinkos1245_cmd_hdr hdr;
171 	uint8_t cmd[1];   /* 0xc0 */
172 	uint8_t pad[10];
173 } __attribute__((packed));
174 
175 /* Tone curve manipulation -- returns Status */
176 struct shinkos1245_cmd_tone {
177 	struct shinkos1245_cmd_hdr hdr;
178 	uint8_t cmd[1];   /* 0xc0 */
179 	uint8_t tone[4];  /* 0x54 0x4f 0x4e 0x45 */
180 	uint8_t cmd2[1];  /* 0x72/0x77/0x65/0x20 for read/write/end/data */
181 	union {
182 		struct {
183 			uint8_t tone_table;
184 			uint8_t param_table;
185 			uint8_t pad[3];
186 		} read_write;
187 		struct {
188 			uint8_t pad[5];
189 		} end_data;
190 	};
191 } __attribute__((packed));
192 
193 enum {
194 	TONE_TABLE_STANDARD = 0,
195 	TONE_TABLE_USER = 1,
196 	TONE_TABLE_CURRENT = 2,
197 };
198 enum {
199 	PARAM_TABLE_STANDARD = 1,
200 	PARAM_TABLE_FINE = 2,
201 };
202 
203 #define TONE_CURVE_DATA_BLOCK_SIZE 64
204 
205 /* Query Model information */
206 struct shinkos1245_cmd_getmodel {
207 	struct shinkos1245_cmd_hdr hdr;
208 	uint8_t cmd[1];   /* 0x02 */
209 	uint8_t pad[10];
210 } __attribute__((packed));
211 
212 struct shinkos1245_resp_getmodel {
213 	uint8_t vendor_id[4];
214 	uint8_t product_id[4];
215 	uint8_t strings[40];
216 } __attribute__((packed));
217 
218 
219 /* Query and Set Matte info, returns a Matte response */
220 struct shinkos1245_cmd_getmatte {
221 	struct shinkos1245_cmd_hdr hdr;
222 	uint8_t cmd[1]; /* 0x20 */
223 	uint8_t mode;   /* Fixed at 0x00 */
224 	uint8_t pad[9];
225 } __attribute__((packed));
226 
227 struct shinkos1245_cmd_setmatte {
228 	struct shinkos1245_cmd_hdr hdr;
229 	uint8_t cmd[1]; /* 0x21 */
230 	uint8_t mode;   /* Fixed at 0x00 */
231 	 int8_t level;  /* -25->+25 */
232 	uint8_t pad[8];
233 } __attribute__((packed));
234 
235 struct shinkos1245_resp_matte {
236 	uint8_t code;
237 	uint8_t mode;
238 	 int8_t level;
239 	uint8_t reserved[4];
240 } __attribute__((packed));
241 
242 #define MATTE_MODE_MATTE 0x00
243 #define MAX_MEDIA_ITEMS 15
244 
245 /* Private data structure */
246 struct shinkos1245_ctx {
247 	struct libusb_device_handle *dev;
248 	uint8_t endp_up;
249 	uint8_t endp_down;
250 	int type;
251 
252 	uint8_t jobid;
253 
254 	struct sinfonia_mediainfo_item medias[MAX_MEDIA_ITEMS];
255 	int num_medias;
256 	int media_8x12;
257 
258 	struct marker marker;
259 
260 	int tonecurve;
261 };
262 
263 enum {
264 	S_IDLE = 0,
265 	S_PRINTER_READY_CMD,
266 	S_PRINTER_SENT_DATA,
267 	S_FINISHED,
268 };
269 
270 
271 /* Basic printer I/O stuffs */
shinkos1245_fill_hdr(struct shinkos1245_cmd_hdr * hdr)272 static void shinkos1245_fill_hdr(struct shinkos1245_cmd_hdr *hdr)
273 {
274 	hdr->prefix = 0x03;
275 	hdr->hdr[0] = 0x1b;
276 	hdr->hdr[1] = 0x43;
277 	hdr->hdr[2] = 0x48;
278 	hdr->hdr[3] = 0x43;
279 }
280 
shinkos1245_do_cmd(struct shinkos1245_ctx * ctx,void * cmd,int cmd_len,void * resp,int resp_len,int * actual_len)281 static int shinkos1245_do_cmd(struct shinkos1245_ctx *ctx,
282 			      void *cmd, int cmd_len,
283 			      void *resp, int resp_len,
284 			      int *actual_len)
285 {
286 	int ret;
287 
288 	/* Write command */
289 	if ((ret = send_data(ctx->dev, ctx->endp_down,
290 			     cmd, cmd_len)))
291 		return (ret < 0) ? ret : -99;
292 
293 	/* Read response */
294 	ret = read_data(ctx->dev, ctx->endp_up,
295 			resp, resp_len, actual_len);
296 	if (ret < 0)
297 		return ret;
298 	if (*actual_len < resp_len) {
299 		ERROR("Short read! (%d/%d))\n", *actual_len, resp_len);
300 		return -99;
301 	}
302 
303 	return ret;
304 }
305 
shinkos1245_get_status(struct shinkos1245_ctx * ctx,struct shinkos1245_resp_status * resp)306 static int shinkos1245_get_status(struct shinkos1245_ctx *ctx,
307 				  struct shinkos1245_resp_status *resp)
308 {
309 	struct shinkos1245_cmd_getstatus cmd;
310 	int ret, num;
311 
312 	shinkos1245_fill_hdr(&cmd.hdr);
313 	cmd.cmd[0] = 0x03;
314 	memset(cmd.pad, 0, sizeof(cmd.pad));
315 
316 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
317 				resp, sizeof(*resp), &num);
318 	if (ret < 0) {
319 		ERROR("Failed to execute GET_STATUS command\n");
320 		return ret;
321 	}
322 	if (resp->code != CMD_CODE_OK) {
323 		ERROR("Bad return code on GET_STATUS (%02x)\n",
324 		      resp->code);
325 		return -99;
326 	}
327 
328 	/* Byteswap important stuff */
329         resp->state.status2 = be32_to_cpu(resp->state.status2);
330 
331 	return 0;
332 }
333 
shinkos1245_get_media(struct shinkos1245_ctx * ctx)334 static int shinkos1245_get_media(struct shinkos1245_ctx *ctx)
335 {
336 	struct shinkos1245_cmd_getmedia cmd;
337 	struct shinkos1245_resp_media resp;
338 	int i, j;
339 	int ret = 0, num;
340 
341 	shinkos1245_fill_hdr(&cmd.hdr);
342 	memset(cmd.pad, 0, sizeof(cmd.pad));
343 	ctx->media_8x12 = 0;
344 	for (i = 1 ; i <= 3 ; i++) {
345 		cmd.cmd[0] = 0x0a | (i << 4);
346 
347 		ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
348 					 &resp, sizeof(resp), &num);
349 		if (ret < 0) {
350 			ERROR("Failed to execute GET_MEDIA command\n");
351 			return ret;
352 		}
353 		if (resp.code != CMD_CODE_OK) {
354 			ERROR("Bad return code on GET_MEDIA (%02x)\n",
355 			      resp.code);
356 			return -99;
357 		}
358 
359 		/* Store media info */
360 		for (j = 0; j < NUM_MEDIAS && ctx->num_medias < resp.count ; j++) {
361 			ctx->medias[ctx->num_medias].code = resp.data[j].code;
362 			ctx->medias[ctx->num_medias].columns = be16_to_cpu(resp.data[j].columns);
363 			ctx->medias[ctx->num_medias].rows = be16_to_cpu(resp.data[j].rows);
364 			ctx->medias[ctx->num_medias].type = resp.data[j].type;
365 			ctx->medias[ctx->num_medias].method = resp.data[j].method;
366 			ctx->num_medias++;
367 
368 			if (ctx->medias[i].rows >= 3636)
369 				ctx->media_8x12 = 1;
370 		}
371 
372 		/* Once we've parsed them all.. we're done */
373 		if (ctx->num_medias == resp.count)
374 			break;
375 	}
376 	return ret;
377 }
378 
shinkos1245_get_printerid(struct shinkos1245_ctx * ctx,struct shinkos1245_resp_getid * resp)379 static int shinkos1245_get_printerid(struct shinkos1245_ctx *ctx,
380 				     struct shinkos1245_resp_getid *resp)
381 {
382 	struct shinkos1245_cmd_getid cmd;
383 	int ret, num;
384 
385 	shinkos1245_fill_hdr(&cmd.hdr);
386 	cmd.cmd[0] = 0x12;
387 	memset(cmd.pad, 0, sizeof(cmd.pad));
388 
389 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
390 				resp, sizeof(*resp), &num);
391 	if (ret < 0) {
392 		ERROR("Failed to execute GET_PRINTERID command\n");
393 		return ret;
394 	}
395 
396 	return 0;
397 }
398 
shinkos1245_set_printerid(struct shinkos1245_ctx * ctx,char * id)399 static int shinkos1245_set_printerid(struct shinkos1245_ctx *ctx,
400 				     char *id)
401 {
402 	struct shinkos1245_cmd_setid cmd;
403 	struct shinkos1245_resp_status sts;
404 
405 	int ret, num;
406 	int i;
407 
408 	shinkos1245_fill_hdr(&cmd.hdr);
409 	cmd.cmd[0] = 0x0a;
410 	cmd.cmd[1] = 0x22;
411 
412 	for (i = 0 ; i < (int)sizeof(cmd.data) ; i++) {
413 		if (*id)
414 			cmd.data[i] = (uint8_t) *id++;
415 		else
416 			cmd.data[i] = ' ';
417 	}
418 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
419 				 &sts, sizeof(sts), &num);
420 	if (ret < 0) {
421 		ERROR("Failed to execute SET_PRINTERID command\n");
422 		return ret;
423 	}
424 	if (sts.code != CMD_CODE_OK) {
425 		ERROR("Bad return code on SET_PRINTERID command\n");
426 		return -99;
427 	}
428 	return 0;
429 }
430 
shinkos1245_canceljob(struct shinkos1245_ctx * ctx,int id)431 static int shinkos1245_canceljob(struct shinkos1245_ctx *ctx,
432 				 int id)
433 {
434 	struct shinkos1245_cmd_canceljob cmd;
435 	struct shinkos1245_resp_status sts;
436 
437 	int ret, num;
438 
439 	shinkos1245_fill_hdr(&cmd.hdr);
440 	cmd.cmd[0] = 0x13;
441 	cmd.id = id;
442 
443 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
444 				 &sts, sizeof(sts), &num);
445 	if (ret < 0) {
446 		ERROR("Failed to execute CANCELJOB command\n");
447 		return ret;
448 	}
449 	if (sts.code != CMD_CODE_OK) {
450 		ERROR("Bad return code on CANCELJOB command\n");
451 		return -99;
452 	}
453 	return 0;
454 }
455 
shinkos1245_reset(struct shinkos1245_ctx * ctx)456 static int shinkos1245_reset(struct shinkos1245_ctx *ctx)
457 {
458 	struct shinkos1245_cmd_reset cmd;
459 	struct shinkos1245_resp_status sts;
460 
461 	int ret, num;
462 
463 	shinkos1245_fill_hdr(&cmd.hdr);
464 	cmd.cmd[0] = 0xc0;
465 
466 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
467 				 &sts, sizeof(sts), &num);
468 	if (ret < 0) {
469 		ERROR("Failed to execute RESET command\n");
470 		return ret;
471 	}
472 	if (sts.code != CMD_CODE_OK) {
473 		ERROR("Bad return code on RESET command\n");
474 		return -99;
475 	}
476 	return 0;
477 }
478 
479 
shinkos1245_set_matte(struct shinkos1245_ctx * ctx,int intensity)480 static int shinkos1245_set_matte(struct shinkos1245_ctx *ctx,
481 				 int intensity)
482 {
483 	struct shinkos1245_cmd_setmatte cmd;
484 	struct shinkos1245_resp_matte sts;
485 
486 	int ret, num;
487 
488 	shinkos1245_fill_hdr(&cmd.hdr);
489 	cmd.cmd[0] = 0x21;
490 	cmd.mode = MATTE_MODE_MATTE;
491 	cmd.level = intensity;
492 
493 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
494 				 &sts, sizeof(sts), &num);
495 	if (ret < 0) {
496 		ERROR("Failed to execute SET_MATTE command\n");
497 		return ret;
498 	}
499 	if (sts.code == CMD_CODE_OK)
500 		return 0;
501 	if (sts.code == CMD_CODE_BAD)
502 		return 1;
503 
504 	ERROR("Bad return code (%02x) on SET_MATTE command\n", sts.code);
505 	return -99;
506 }
507 
shinkos1245_get_matte(struct shinkos1245_ctx * ctx,int * intensity)508 static int shinkos1245_get_matte(struct shinkos1245_ctx *ctx,
509 				 int *intensity)
510 {
511 	struct shinkos1245_cmd_getmatte cmd;
512 	struct shinkos1245_resp_matte sts;
513 
514 	int ret, num;
515 
516 	shinkos1245_fill_hdr(&cmd.hdr);
517 	cmd.cmd[0] = 0x20;
518 	cmd.mode = MATTE_MODE_MATTE;
519 
520 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
521 				 &sts, sizeof(sts), &num);
522 	if (ret < 0) {
523 		ERROR("Failed to execute GET_MATTE command\n");
524 		return ret;
525 	}
526 	if (sts.code != CMD_CODE_OK) {
527 		ERROR("Bad return code (%02x) on GET_MATTE command\n", sts.code);
528 		return -99;
529 	}
530 	*intensity = sts.level;
531 
532 	return 0;
533 }
534 
shinkos1245_tonecurves(int type,int table)535 static char* shinkos1245_tonecurves(int type, int table)
536 {
537 	switch (type) {
538 	case TONE_TABLE_STANDARD:
539 		switch (table) {
540 		case PARAM_TABLE_STANDARD:
541 			return "Standard/Standard";
542 		case PARAM_TABLE_FINE:
543 			return "Standard/Fine";
544 		default:
545 			return "Standard/Unknown";
546 		}
547 	case TONE_TABLE_USER:
548 		switch (table) {
549 		case PARAM_TABLE_STANDARD:
550 			return "User/Standard";
551 		case PARAM_TABLE_FINE:
552 			return "User/Fine";
553 		default:
554 			return "User/Unknown";
555 		}
556 	case TONE_TABLE_CURRENT:
557 		switch (table) {
558 		case PARAM_TABLE_STANDARD:
559 			return "Current/Standard";
560 		case PARAM_TABLE_FINE:
561 			return "Current/Fine";
562 		default:
563 			return "Current/Unknown";
564 		}
565 	default:
566 		return "Unknown";
567 	}
568 }
569 
shinkos1245_dump_status(struct shinkos1245_ctx * ctx,struct shinkos1245_resp_status * sts)570 static void shinkos1245_dump_status(struct shinkos1245_ctx *ctx,
571 				    struct shinkos1245_resp_status *sts)
572 {
573 	char *detail;
574 	switch (sts->print_status) {
575 	case STATUS_PRINTING:
576 		detail = "Printing";
577 		break;
578 	case STATUS_IDLE:
579 		detail = "Idle";
580 		break;
581 	default:
582 		detail = "Unknown";
583 		break;
584 	}
585 	INFO("Printer Status:  %s\n", detail);
586 
587 	/* Byteswap */
588 	INFO("Printer State: %s # %02x %08x %02x\n",
589 	     sinfonia_1x45_status_str(sts->state.status1, sts->state.status2, sts->state.error),
590 	     sts->state.status1, sts->state.status2, sts->state.error);
591 	INFO("Counters:\n");
592 	INFO("\tLifetime     :  %u\n", be32_to_cpu(sts->counters.lifetime));
593 	INFO("\tThermal Head :  %u\n", be32_to_cpu(sts->counters.maint));
594 	INFO("\tMedia        :  %u\n", be32_to_cpu(sts->counters.media));
595 	INFO("\tRemaining    :  %u\n", ctx->marker.levelmax - be32_to_cpu(sts->counters.media));
596 	INFO("\tCutter       :  %u\n", be32_to_cpu(sts->counters.cutter));
597 	INFO("Versions:\n");
598 	INFO("\tUSB Boot    : %u\n", sts->counters.ver_boot);
599 	INFO("\tUSB Control : %u\n", sts->counters.ver_ctrl);
600 	INFO("\tMain Boot   : %u\n", be16_to_cpu(sts->versions.main_boot));
601 	INFO("\tMain Control: %u\n", be16_to_cpu(sts->versions.main_control));
602 	INFO("\tDSP Boot    : %u\n", be16_to_cpu(sts->versions.dsp_boot));
603 	INFO("\tDSP Control : %u\n", be16_to_cpu(sts->versions.dsp_control));
604 
605 //	INFO("USB TypeFlag: %02x\n", sts->counters.control_flag);
606 
607 	INFO("Bank 1 ID: %u\n", sts->counters2.bank1_id);
608 	INFO("\tPrints:  %d/%d complete\n",
609 	     be16_to_cpu(sts->counters2.bank1_complete),
610 	     be16_to_cpu(sts->counters2.bank1_spec));
611 	INFO("Bank 2 ID: %u\n", sts->counters2.bank2_id);
612 	INFO("\tPrints:  %d/%d complete\n",
613 	     be16_to_cpu(sts->counters2.bank2_complete),
614 	     be16_to_cpu(sts->counters2.bank2_spec));
615 
616 	switch (sts->curve_status) {
617 	case CURVE_TABLE_STATUS_INITIAL:
618 		detail = "Initial/Default";
619 		break;
620 	case CURVE_TABLE_STATUS_USERSET:
621 		detail = "User Stored";
622 		break;
623 	case CURVE_TABLE_STATUS_CURRENT:
624 		detail = "Current";
625 		break;
626 	default:
627 		detail = "Unknown";
628 		break;
629 	}
630 	INFO("Tone Curve Status: %s\n", detail);
631 }
632 
shinkos1245_dump_media(struct sinfonia_mediainfo_item * medias,int media_8x12,int count)633 static void shinkos1245_dump_media(struct sinfonia_mediainfo_item *medias,
634 				   int media_8x12,
635 				   int count)
636 {
637 	int i;
638 
639 	INFO("Loaded media type: %s\n", media_8x12 ? "8x12" : "8x10");
640 	INFO("Supported print sizes: %d\n", count);
641 
642 	for (i = 0 ; i < count ; i++) {
643 		INFO("\t %02d: %04u*%04u (%02x/%02u)\n",
644 		     i,
645 		     medias[i].columns,
646 		     medias[i].rows,
647 		     medias[i].type,
648 		     medias[i].method);
649 	}
650 }
651 
get_tonecurve(struct shinkos1245_ctx * ctx,int type,int table,char * fname)652 static int get_tonecurve(struct shinkos1245_ctx *ctx, int type, int table, char *fname)
653 {
654 	int ret = 0, num, remaining;
655 	uint8_t *data, *ptr;
656 
657 	struct shinkos1245_cmd_tone cmd;
658 	struct shinkos1245_resp_status resp;
659 
660 	INFO("Dump %s Tone Curve to '%s'\n", shinkos1245_tonecurves(type, table), fname);
661 
662 	/* Issue a tone_read_start */
663 	shinkos1245_fill_hdr(&cmd.hdr);
664 	cmd.cmd[0] = 0x0c;
665 	cmd.tone[0] = 0x54;
666 	cmd.tone[1] = 0x4f;
667 	cmd.tone[2] = 0x4e;
668 	cmd.tone[3] = 0x45;
669 	cmd.cmd2[0] = 0x72;
670 	cmd.read_write.tone_table = type;
671 	cmd.read_write.param_table = table;
672 
673 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
674 				&resp, sizeof(resp), &num);
675 
676 	if (ret < 0) {
677 		ERROR("Failed to execute TONE_READ command\n");
678 		return ret;
679 	}
680 	if (resp.code != CMD_CODE_OK) {
681 		ERROR("Bad return code on TONE_READ (%02x)\n",
682 		      resp.code);
683 		return -99;
684 	}
685 
686 	/* Get the data out */
687 	remaining = TONE_CURVE_SIZE;
688 	data = malloc(remaining);
689 	if (!data) {
690 		ERROR("Memory Allocation Failure!\n");
691 		return -11;
692 	}
693 	ptr = data;
694 
695 	while(remaining) {
696 		/* Issue a tone_data message */
697 		cmd.cmd2[0] = 0x20;
698 
699 		ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
700 					 &resp, sizeof(resp), &num);
701 
702 		if (ret < 0) {
703 			ERROR("Failed to execute TONE_DATA command\n");
704 			goto done;
705 		}
706 		if (resp.code != CMD_CODE_OK) {
707 			ERROR("Bad return code on TONE_DATA (%02x)\n",
708 			      resp.code);
709 			ret = -99;
710 			goto done;
711 		}
712 
713 		/* And read back 64-bytes of data */
714 		ret = read_data(ctx->dev, ctx->endp_up,
715 				ptr, TONE_CURVE_DATA_BLOCK_SIZE, &num);
716 		if (num != TONE_CURVE_DATA_BLOCK_SIZE) {
717 			ret = -99;
718 			goto done;
719 		}
720 		if (ret < 0)
721 			goto done;
722 		ptr += num;
723 		remaining -= num;
724 	}
725 
726 	/* Issue a tone_end */
727 	cmd.cmd2[0] = 0x65;
728 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
729 				&resp, sizeof(resp), &num);
730 
731 	if (ret < 0) {
732 		ERROR("Failed to execute TONE_END command\n");
733 		goto done;
734 	}
735 	if (resp.code != CMD_CODE_OK) {
736 		ERROR("Bad return code on TONE_END (%02x)\n",
737 		      resp.code);
738 		ret = -99;
739 		goto done;
740 	}
741 
742 	/* Open file and write it out */
743 	{
744 		int tc_fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
745 		if (tc_fd < 0) {
746 			ret = tc_fd;
747 			goto done;
748 		}
749 
750 		ret = write(tc_fd, data, TONE_CURVE_SIZE);
751 		if (ret < 0)
752 			goto done;
753 		close(tc_fd);
754 	}
755 
756 done:
757 	free(data);
758 
759 	return ret;
760 }
761 
set_tonecurve(struct shinkos1245_ctx * ctx,int type,int table,char * fname)762 static int set_tonecurve(struct shinkos1245_ctx *ctx, int type, int table, char *fname)
763 {
764 	int ret = 0, num, remaining;
765 	uint8_t *data, *ptr;
766 
767 	struct shinkos1245_cmd_tone cmd;
768 	struct shinkos1245_resp_status resp;
769 
770 	INFO("Read %d/%d Tone Curve from '%s'\n", type, table, fname);
771 
772 	/* Allocate space */
773 	remaining = TONE_CURVE_SIZE;
774 	data = malloc(remaining);
775 	if (!data) {
776 		ERROR("Memory Allocation Failure!\n");
777 		return -11;
778 	}
779 	ptr = data;
780 
781 
782 	/* Read in file */
783 	if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE, NULL))) {
784 		ERROR("Failed to read Tone Curve file\n");
785 		goto done;
786 	}
787 
788 	/* Issue a tone_write_start */
789 	shinkos1245_fill_hdr(&cmd.hdr);
790 	cmd.cmd[0] = 0x0c;
791 	cmd.tone[0] = 0x54;
792 	cmd.tone[1] = 0x4f;
793 	cmd.tone[2] = 0x4e;
794 	cmd.tone[3] = 0x45;
795 	cmd.cmd2[0] = 0x77;
796 	cmd.read_write.tone_table = type;
797 	cmd.read_write.param_table = table;
798 
799 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
800 				&resp, sizeof(resp), &num);
801 
802 	if (ret < 0) {
803 		ERROR("Failed to execute TONE_WRITE command\n");
804 		goto done;
805 	}
806 	if (resp.code != CMD_CODE_OK) {
807 		ERROR("Bad return code on TONE_WRITE (%02x)\n",
808 		      resp.code);
809 		ret = -99;
810 		goto done;
811 	}
812 
813 	while(remaining) {
814 		/* Issue a tone_data message */
815 		cmd.cmd2[0] = 0x20;
816 
817 		ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
818 					 &resp, sizeof(resp), &num);
819 
820 		if (ret < 0) {
821 			ERROR("Failed to execute TONE_DATA command\n");
822 			goto done;
823 		}
824 		if (resp.code != CMD_CODE_OK) {
825 			ERROR("Bad return code on TONE_DATA (%02x)\n",
826 			      resp.code);
827 			ret = -99;
828 			goto done;
829 		}
830 
831 		/* Write 64-bytes of data */
832 		ret = send_data(ctx->dev, ctx->endp_up,
833 				ptr, TONE_CURVE_DATA_BLOCK_SIZE);
834 		if (ret < 0)
835 			goto done;
836 		ptr += num;
837 		remaining -= num;
838 	}
839 
840 	/* Issue a tone_end */
841 	cmd.cmd2[0] = 0x65;
842 	ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
843 				&resp, sizeof(resp), &num);
844 
845 	if (ret < 0) {
846 		ERROR("Failed to execute TONE_END command\n");
847 		goto done;
848 	}
849 	if (resp.code != CMD_CODE_OK) {
850 		ERROR("Bad return code on TONE_END (%02x)\n",
851 		      resp.code);
852 		ret = -99;
853 		goto done;
854 	}
855 
856 done:
857 	free(data);
858 
859 	return ret;
860 }
861 
862 
863 /* Driver API */
864 
shinkos1245_cmdline(void)865 static void shinkos1245_cmdline(void)
866 {
867 	DEBUG("\t\t[ -m ]           # Query media\n");
868 	DEBUG("\t\t[ -s ]           # Query status\n");
869 	DEBUG("\t\t[ -u ]           # Query user string\n");
870 	DEBUG("\t\t[ -U sometext ]  # Set user string\n");
871 	DEBUG("\t\t[ -R ]           # Reset printer\n");
872 	DEBUG("\t\t[ -X jobid ]     # Abort a printjob\n");
873 	DEBUG("\t\t[ -F ]           # Tone curve refers to FINE mode\n");
874 	DEBUG("\t\t[ -c filename ]  # Get user/NV tone curve\n");
875 	DEBUG("\t\t[ -C filename ]  # Set user/NV tone curve\n");
876 	DEBUG("\t\t[ -l filename ]  # Get current tone curve\n");
877 	DEBUG("\t\t[ -L filename ]  # Set current tone curve\n");
878 }
879 
shinkos1245_cmdline_arg(void * vctx,int argc,char ** argv)880 int shinkos1245_cmdline_arg(void *vctx, int argc, char **argv)
881 {
882 	struct shinkos1245_ctx *ctx = vctx;
883 	int i, j = 0;
884 
885 	if (!ctx)
886 		return -1;
887 
888 	while ((i = getopt(argc, argv, GETOPT_LIST_GLOBAL "c:C:l:L:FmRsuU:X:")) >= 0) {
889 		switch(i) {
890 		GETOPT_PROCESS_GLOBAL
891 		case 'F':
892 			ctx->tonecurve = PARAM_TABLE_FINE;
893 			break;
894 		case 'c':
895 			j = get_tonecurve(ctx, TONE_TABLE_USER, ctx->tonecurve, optarg);
896 			break;
897 		case 'C':
898 			j = set_tonecurve(ctx, TONE_TABLE_USER, ctx->tonecurve, optarg);
899 			break;
900 		case 'l':
901 			j = get_tonecurve(ctx, TONE_TABLE_CURRENT, ctx->tonecurve, optarg);
902 			break;
903 		case 'L':
904 			j = set_tonecurve(ctx, TONE_TABLE_CURRENT, ctx->tonecurve, optarg);
905 			break;
906 		case 'm':
907 			j = shinkos1245_get_media(ctx);
908 			if (!j)
909 				shinkos1245_dump_media(ctx->medias, ctx->media_8x12, ctx->num_medias);
910 			break;
911 		case 'R':
912 			j = shinkos1245_reset(ctx);
913 			break;
914 		case 's': {
915 			struct shinkos1245_resp_status sts;
916 			j = shinkos1245_get_status(ctx, &sts);
917 			if (!j)
918 				shinkos1245_dump_status(ctx, &sts);
919 			break;
920 		}
921 		case 'u': {
922 			struct shinkos1245_resp_getid resp;
923 			j = shinkos1245_get_printerid(ctx, &resp);
924 			if (!j) {
925 				char buffer[sizeof(resp.data)+1];
926 				memcpy(buffer, resp.data, sizeof(resp.data));
927 				buffer[sizeof(resp.data)] = 0;
928 				INFO("Printer ID: %02x '%s'\n", resp.id, buffer);
929 			}
930 			break;
931 		}
932 		case 'U':
933 			j = shinkos1245_set_printerid(ctx, optarg);
934 			break;
935 		case 'X':
936 			j = shinkos1245_canceljob(ctx, atoi(optarg));
937 			break;
938 		default:
939 			break;  /* Ignore completely */
940 		}
941 
942 		if (j) return j;
943 	}
944 
945 	return 0;
946 }
947 
shinkos1245_init(void)948 static void *shinkos1245_init(void)
949 {
950 	struct shinkos1245_ctx *ctx = malloc(sizeof(struct shinkos1245_ctx));
951 	if (!ctx) {
952 		ERROR("Memory Allocation Failure!\n");
953 		return NULL;
954 	}
955 	memset(ctx, 0, sizeof(struct shinkos1245_ctx));
956 
957 	ctx->tonecurve = PARAM_TABLE_STANDARD;
958 
959 	return ctx;
960 }
961 
shinkos1245_attach(void * vctx,struct libusb_device_handle * dev,int type,uint8_t endp_up,uint8_t endp_down,uint8_t jobid)962 static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev, int type,
963 			      uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
964 {
965 	struct shinkos1245_ctx *ctx = vctx;
966 
967 	ctx->dev = dev;
968 	ctx->endp_up = endp_up;
969 	ctx->endp_down = endp_down;
970 	ctx->type = type;
971 
972 	/* Ensure jobid is sane */
973 	ctx->jobid = jobid & 0x7f;
974 	if (!ctx->jobid)
975 		ctx->jobid++;
976 
977 	if (test_mode < TEST_MODE_NOATTACH) {
978 		/* Query Media */
979 		if (shinkos1245_get_media(ctx))
980 			return CUPS_BACKEND_FAILED;
981 		if (!ctx->num_medias) {
982 			ERROR("Media Query Error\n");
983 			return CUPS_BACKEND_FAILED;
984 		}
985 	} else {
986 		int media_code = 1;
987 		if (getenv("MEDIA_CODE"))
988 			media_code = atoi(getenv("MEDIA_CODE"));
989 
990 		ctx->media_8x12 = media_code;
991 		ctx->num_medias = 0;
992 	}
993 	ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
994 	ctx->marker.name = ctx->media_8x12 ? "8x12" : "8x10";
995 	ctx->marker.levelmax = ctx->media_8x12 ? 230 : 280;
996 	ctx->marker.levelnow = -2;
997 
998 	return CUPS_BACKEND_OK;
999 }
1000 
shinkos1245_read_parse(void * vctx,const void ** vjob,int data_fd,int copies)1001 static int shinkos1245_read_parse(void *vctx, const void **vjob, int data_fd, int copies) {
1002 	struct shinkos1245_ctx *ctx = vctx;
1003 	int ret;
1004 
1005 	struct sinfonia_printjob *job = NULL;
1006 
1007 	if (!ctx)
1008 		return CUPS_BACKEND_FAILED;
1009 
1010 	job = malloc(sizeof(*job));
1011 	if (!job) {
1012 		ERROR("Memory allocation failure!\n");
1013 		return CUPS_BACKEND_RETRY_CURRENT;
1014 	}
1015 	memset(job, 0, sizeof(*job));
1016 
1017 	/* Common read/parse code */
1018 	ret = sinfonia_read_parse(data_fd, 1245, job);
1019 	if (ret) {
1020 		free(job);
1021 		return ret;
1022 	}
1023 
1024 	if (job->jp.copies > 1)
1025 		job->copies = job->jp.copies;
1026 	else
1027 		job->copies = copies;
1028 
1029 	*vjob = job;
1030 	return CUPS_BACKEND_OK;
1031 }
1032 
shinkos1245_main_loop(void * vctx,const void * vjob)1033 static int shinkos1245_main_loop(void *vctx, const void *vjob) {
1034 	struct shinkos1245_ctx *ctx = vctx;
1035 	int i, num, last_state = -1, state = S_IDLE;
1036 	struct shinkos1245_resp_status status1, status2;
1037 	int copies;
1038 
1039 	const struct sinfonia_printjob *job = vjob;
1040 
1041 	if (!ctx)
1042 		return CUPS_BACKEND_FAILED;
1043 	if (!job)
1044 		return CUPS_BACKEND_FAILED;
1045 
1046 	copies = job->copies;
1047 
1048 	/* Make sure print size is supported */
1049 	for (i = 0 ; i < ctx->num_medias ; i++) {
1050 		if (job->jp.media == ctx->medias[i].code &&
1051 		    job->jp.method == ctx->medias[i].method &&
1052 		    job->jp.rows == ctx->medias[i].rows &&
1053 		    job->jp.columns == ctx->medias[i].columns)
1054 			break;
1055 	}
1056 	if (i == ctx->num_medias) {
1057 		ERROR("Unsupported print type\n");
1058 		return CUPS_BACKEND_HOLD;
1059 	}
1060 
1061 	/* Fix max print count. */
1062 	if (copies > 9999) // XXX test against remaining media?
1063 		copies = 9999;
1064 
1065 top:
1066 	if (state != last_state) {
1067 		if (dyesub_debug)
1068 			DEBUG("last_state %d new %d\n", last_state, state);
1069 	}
1070 
1071 	/* Send status query */
1072 	i = shinkos1245_get_status(ctx, &status1);
1073 	if (i < 0)
1074 		return CUPS_BACKEND_FAILED;
1075 
1076 	if (memcmp(&status1, &status2, sizeof(status1))) {
1077 		memcpy(&status2, &status1, sizeof(status1));
1078 		// status changed.
1079 	} else if (state == last_state) {
1080 		sleep(1);
1081 		goto top;
1082 	}
1083 
1084 	/* Make sure we're not in an error state */
1085 	if (status1.state.status1 == STATE_STATUS1_ERROR)
1086 		goto printer_error;
1087 
1088 	last_state = state;
1089 
1090 	fflush(stderr);
1091 
1092 	switch (state) {
1093 	case S_IDLE:
1094 		if (status1.state.status1 == STATE_STATUS1_STANDBY) {
1095 			state = S_PRINTER_READY_CMD;
1096 			break;
1097 		}
1098 
1099 #if 0 // XXX is this necessary
1100 		if (status1.state.status1 == STATE_STATUS1_WAIT) {
1101 			INFO("Printer busy: %s\n",
1102 			     sinfonia_1x45_status_str(status1.state.status1, status1.state.status2, status1.state.error));
1103 			break;
1104 		}
1105 #endif
1106 		/* If the printer is "busy" check to see if there's any
1107 		   open memory banks so we can queue the next print */
1108 
1109 		/* make sure we're not colliding with an existing
1110 		   jobid */
1111 		while (ctx->jobid == status1.counters2.bank1_id ||
1112 		       ctx->jobid == status1.counters2.bank2_id) {
1113 			ctx->jobid++;
1114 			ctx->jobid &= 0x7f;
1115 			if (!ctx->jobid)
1116 				ctx->jobid++;
1117 		}
1118 
1119 		if (!status1.counters2.bank1_remain ||
1120 		    !status1.counters2.bank2_remain) {
1121 			state = S_PRINTER_READY_CMD;
1122 			break;
1123 		}
1124 		break;
1125 	case S_PRINTER_READY_CMD: {
1126 		struct shinkos1245_cmd_print cmd;
1127 
1128 		/* Set matte intensity */
1129 		if (job->jp.mattedepth != 0x7fffffff) {
1130 			int current = -1;
1131 			i = shinkos1245_get_matte(ctx, &current);
1132 			if (i < 0)
1133 				goto printer_error2;
1134 			if (current != job->jp.mattedepth) {
1135 				i = shinkos1245_set_matte(ctx, job->jp.mattedepth);
1136 				if (i < 0)
1137 					goto printer_error2;
1138 				if (i > 0) {
1139 					INFO("Can't set matte intensity when printing in progress...\n");
1140 					state = S_IDLE;
1141 					sleep(1);
1142 					break;
1143 				}
1144 			}
1145 		}
1146 
1147 		INFO("Sending print job (internal id %u)\n", ctx->jobid);
1148 
1149 		shinkos1245_fill_hdr(&cmd.hdr);
1150 		cmd.cmd[0] = 0x0a;
1151 		cmd.cmd[1] = 0x00;
1152 
1153 		cmd.id = ctx->jobid;
1154 		cmd.count = uint16_to_packed_bcd(copies);
1155 		cmd.columns = cpu_to_be16(job->jp.columns);
1156 		cmd.rows = cpu_to_be16(job->jp.rows);
1157 		cmd.media = job->jp.media;
1158 		cmd.mode = (job->jp.oc_mode & 0x3f) || ((job->jp.dust & 0x3) << 6);
1159 		cmd.combo = job->jp.method;
1160 
1161 		/* Issue print command */
1162 		i = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
1163 				       &status1, sizeof(status1),
1164 				       &num);
1165 		status1.state.status2 = be32_to_cpu(status1.state.status2);
1166 		if (i < 0)
1167 			goto printer_error;
1168 
1169 		/* Check for buffer full state, and wait if we're full */
1170 		if (status1.code != CMD_CODE_OK) {
1171 			if (status1.print_status == STATUS_PRINTING) {
1172 				sleep(1);
1173 				break;
1174 			} else {
1175 				goto printer_error;
1176 			}
1177 		}
1178 
1179 		/* Check for error states */
1180 		if (status1.state.status1 == STATE_STATUS1_ERROR)
1181 			goto printer_error;
1182 
1183 		/* Send over data */
1184 		INFO("Sending image data to printer\n");
1185 		if ((i = send_data(ctx->dev, ctx->endp_down,
1186 				   job->databuf, job->datalen)))
1187 			return CUPS_BACKEND_FAILED;
1188 
1189 		INFO("Waiting for printer to acknowledge completion\n");
1190 		sleep(1);
1191 		state = S_PRINTER_SENT_DATA;
1192 		break;
1193 	}
1194 	case S_PRINTER_SENT_DATA:
1195 		if (fast_return) {
1196 			INFO("Fast return mode enabled.\n");
1197 			state = S_FINISHED;
1198 		}
1199 		/* Check for completion */
1200 		if (status1.print_status == STATUS_IDLE)
1201 			state = S_FINISHED;
1202 
1203 		break;
1204 	default:
1205 		break;
1206 	}
1207 
1208 	if (state != S_FINISHED)
1209 		goto top;
1210 
1211 	INFO("Print complete\n");
1212 
1213 	return CUPS_BACKEND_OK;
1214 
1215 printer_error:
1216 	ERROR("Printer Error: %s # %02x %08x %02x\n",
1217 	      sinfonia_1x45_status_str(status1.state.status1, status1.state.status2, status1.state.error),
1218 	      status1.state.status1, status1.state.status2, status1.state.error);
1219 printer_error2:
1220 	return CUPS_BACKEND_FAILED;
1221 }
1222 
shinkos1245_query_serno(struct libusb_device_handle * dev,uint8_t endp_up,uint8_t endp_down,char * buf,int buf_len)1223 static int shinkos1245_query_serno(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len)
1224 {
1225 	struct shinkos1245_resp_getid resp;
1226 	int i;
1227 
1228 	struct shinkos1245_ctx ctx = {
1229 		.dev = dev,
1230 		.endp_up = endp_up,
1231 		.endp_down = endp_down,
1232 	};
1233 
1234 	i = shinkos1245_get_printerid(&ctx, &resp);
1235 	if (i < 0)
1236 		return CUPS_BACKEND_FAILED;
1237 
1238 	for (i = 0 ; i < (int) sizeof(resp.data) && i < buf_len; i++) {
1239 		buf[i] = resp.data[i];
1240 	}
1241 
1242 	/* Ensure null-termination */
1243 	if (i < buf_len)
1244 		buf[i] = 0;
1245 	else
1246 		buf[buf_len-1] = 0;
1247 
1248 	return CUPS_BACKEND_OK;
1249 }
1250 
shinkos1245_query_markers(void * vctx,struct marker ** markers,int * count)1251 static int shinkos1245_query_markers(void *vctx, struct marker **markers, int *count)
1252 {
1253 	struct shinkos1245_ctx *ctx = vctx;
1254 	struct shinkos1245_resp_status status;
1255 
1256 	/* Query status */
1257 	if (shinkos1245_get_status(ctx, &status))
1258 		return CUPS_BACKEND_FAILED;
1259 
1260 	ctx->marker.levelnow = ctx->marker.levelmax - be32_to_cpu(status.counters.media);
1261 
1262 	*markers = &ctx->marker;
1263 	*count = 1;
1264 
1265 	return CUPS_BACKEND_OK;
1266 }
1267 
1268 /* Exported */
1269 #define USB_VID_SHINKO       0x10CE
1270 #define USB_PID_SHINKO_S1245 0x0007
1271 
1272 static const char *shinkos1245_prefixes[] = {
1273 	"shinko-chcs1245",
1274 	// extra
1275 	"sinfonia-chcs1245",
1276 	// backwards-compatibility
1277 	"shinkos1245",
1278 	NULL
1279 };
1280 
1281 struct dyesub_backend shinkos1245_backend = {
1282 	.name = "Shinko/Sinfonia CHC-S1245/E1",
1283 	.version = "0.31" " (lib " LIBSINFONIA_VER ")",
1284 	.uri_prefixes = shinkos1245_prefixes,
1285 	.cmdline_usage = shinkos1245_cmdline,
1286 	.cmdline_arg = shinkos1245_cmdline_arg,
1287 	.init = shinkos1245_init,
1288 	.attach = shinkos1245_attach,
1289 	.cleanup_job = sinfonia_cleanup_job,
1290 	.read_parse = shinkos1245_read_parse,
1291 	.main_loop = shinkos1245_main_loop,
1292 	.query_serno = shinkos1245_query_serno,
1293 	.query_markers = shinkos1245_query_markers,
1294 	.devices = {
1295 		{ USB_VID_SHINKO, USB_PID_SHINKO_S1245, P_SHINKO_S1245, NULL, "shinko-chcs1245"},
1296 		{ 0, 0, 0, NULL, NULL}
1297 	}
1298 };
1299 
1300 /* CHC-S1245 data format
1301 
1302   Spool file consists of an 116-byte header, followed by RGB-packed data,
1303   followed by a 4-byte footer.  Header appears to consist of a series of
1304   4-byte Little Endian words.
1305 
1306    10 00 00 00 MM MM 00 00  00 00 00 00 01 00 00 00  MM == Model (ie 1245d)
1307    64 00 00 00 00 00 00 00  TT 00 00 00 00 00 00 00  TT == Media Size (0x10 fixed)
1308    MM 00 00 00 PP 00 00 00  00 00 00 00 ZZ ZZ ZZ ZZ  MM = Print Method (aka cut control), PP = Default/Glossy/Matte (0x01/0x03/0x05), ZZ == matte intensity (0x7fffffff for glossy, else 0x00000000 +- 25 for matte)
1309    VV 00 00 00 WW WW 00 00  HH HH 00 00 XX XX 00 00  VV == dust; 0x00 default, 0x01 off, 0x02 on, XX == Copies
1310    00 00 00 00 00 00 00 00  00 00 00 00 ce ff ff ff
1311    00 00 00 00 ce ff ff ff  QQ QQ 00 00 ce ff ff ff  QQ == DPI, ie 300.
1312    00 00 00 00 ce ff ff ff  00 00 00 00 00 00 00 00
1313    00 00 00 00
1314 
1315    [[Packed RGB payload of WW*HH*3 bytes]]
1316 
1317    04 03 02 01  [[ footer ]]
1318 
1319 
1320 */
1321