1  /*
2  *   Shinko/Sinfonia Common Code
3  *
4  *   (c) 2019 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, write to the Free Software
22  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  *
24  *          [http://www.gnu.org/licenses/gpl-2.0.html]
25  *
26  *   SPDX-License-Identifier: GPL-2.0+
27  *
28  */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 
40 #include "backend_common.h"
41 #include "backend_sinfonia.h"
42 
sinfonia_read_parse(int data_fd,uint32_t model,struct sinfonia_printjob * job)43 int sinfonia_read_parse(int data_fd, uint32_t model,
44 			struct sinfonia_printjob *job)
45 {
46 	uint32_t hdr[29];
47 	int ret, i;
48 	uint8_t tmpbuf[4];
49 
50 	/* Read in header */
51 	ret = read(data_fd, hdr, SINFONIA_HDR_LEN);
52 	if (ret < 0 || ret != SINFONIA_HDR_LEN) {
53 		if (ret == 0)
54 			return CUPS_BACKEND_CANCEL;
55 		ERROR("Read failed (%d/%d)\n",
56 		      ret, SINFONIA_HDR_LEN);
57 		perror("ERROR: Read failed");
58 		return ret;
59 	}
60 
61 	/* Byteswap everything */
62 	for (i = 0 ; i < (SINFONIA_HDR_LEN / 4) ; i++) {
63 		hdr[i] = le32_to_cpu(hdr[i]);
64 	}
65 
66 	/* Sanity-check headers */
67 	if (hdr[0] != SINFONIA_HDR1_LEN ||
68 	    hdr[4] != SINFONIA_HDR2_LEN ||
69 	    hdr[22] != SINFONIA_DPI) {
70 		ERROR("Unrecognized header data format!\n");
71 		return CUPS_BACKEND_CANCEL;
72 	}
73 	if (hdr[1] != model) {
74 		ERROR("job/printer mismatch (%u/%u)!\n", hdr[1], model);
75 		return CUPS_BACKEND_CANCEL;
76 	}
77 
78 	if (!hdr[13] || !hdr[14]) {
79 		ERROR("Bad job cols/rows!\n");
80 		return CUPS_BACKEND_CANCEL;
81 	}
82 
83 	/* Work out data length */
84 	job->datalen = hdr[13] * hdr[14] * 3;
85 	job->databuf = malloc(job->datalen);
86 	if (!job->databuf) {
87 		ERROR("Memory allocation failure!\n");
88 		return CUPS_BACKEND_RETRY_CURRENT;
89 	}
90 
91 	/* Read in payload data */
92 	{
93 		uint32_t remain = job->datalen;
94 		uint8_t *ptr = job->databuf;
95 		do {
96 			ret = read(data_fd, ptr, remain);
97 			if (ret < 0) {
98 				ERROR("Read failed (%d/%u/%d)\n",
99 				      ret, remain, job->datalen);
100 				perror("ERROR: Read failed");
101 				free(job->databuf);
102 				job->databuf = NULL;
103 				return ret;
104 			}
105 			ptr += ret;
106 			remain -= ret;
107 		} while (remain);
108 	}
109 
110 	/* Make sure footer is sane too */
111 	ret = read(data_fd, tmpbuf, 4);
112 	if (ret != 4) {
113 		ERROR("Read failed (%d/%d)\n", ret, 4);
114 		perror("ERROR: Read failed");
115 		free(job->databuf);
116 		job->databuf = NULL;
117 		return ret;
118 	}
119 	if (tmpbuf[0] != 0x04 ||
120 	    tmpbuf[1] != 0x03 ||
121 	    tmpbuf[2] != 0x02 ||
122 	    tmpbuf[3] != 0x01) {
123 		ERROR("Unrecognized footer data format!\n");
124 		free (job->databuf);
125 		job->databuf = NULL;
126 		return CUPS_BACKEND_CANCEL;
127 	}
128 
129 	/* Fill out job params */
130 	job->jp.media = hdr[6];
131 	if (hdr[1] != 6245)
132 		job->jp.method = hdr[8];
133 	if (hdr[1] == 2245 || hdr[1] == 6245)
134 		job->jp.quality = hdr[9];
135 	if (hdr[1] == 1245 || hdr[1] == 2145)
136 		job->jp.oc_mode = hdr[9];
137 	else
138 		job->jp.oc_mode = hdr[10];
139 	if (hdr[1] == 1245)
140 		job->jp.mattedepth = hdr[11];
141 	if (hdr[1] == 1245)
142 		job->jp.dust = hdr[12];
143 	job->jp.columns = hdr[13];
144 	job->jp.rows = hdr[14];
145 	job->jp.copies = hdr[15];
146 
147 	if (hdr[1] == 2245 || hdr[1] == 6145)
148 		job->jp.ext_flags = hdr[28];
149 
150 	return CUPS_BACKEND_OK;
151 }
152 
sinfonia_raw10_read_parse(int data_fd,struct sinfonia_printjob * job)153 int sinfonia_raw10_read_parse(int data_fd, struct sinfonia_printjob *job)
154 {
155 	struct sinfonia_printcmd10_hdr hdr;
156 	int ret;
157 
158 	/* Read in header */
159 	ret = read(data_fd, &hdr, sizeof(hdr));
160 	if (ret < 0 || ret != sizeof(hdr)) {
161 		if (ret == 0)
162 			return CUPS_BACKEND_CANCEL;
163 		ERROR("Read failed (%d/%d/%d)\n",
164 		      ret, 0, (int)sizeof(hdr));
165 		perror("ERROR: Read failed");
166 		return CUPS_BACKEND_CANCEL;
167 	}
168 	/* Validate header */
169 	if (le16_to_cpu(hdr.hdr.cmd) != 0x4001 ||
170 	    le16_to_cpu(hdr.hdr.len) != 10) {
171 		ERROR("Unrecognized data format!\n");
172 		return CUPS_BACKEND_CANCEL;
173 	}
174 	job->jp.copies = le16_to_cpu(hdr.copies);
175 	job->jp.rows = le16_to_cpu(hdr.rows);
176 	job->jp.columns = le16_to_cpu(hdr.columns);
177 	job->jp.media = hdr.media;
178 	job->jp.oc_mode = hdr.oc_mode;
179 	job->jp.method = hdr.method;
180 
181 	/* Allocate buffer */
182 	job->datalen = job->jp.rows * job->jp.columns * 3;
183 	job->databuf = malloc(job->datalen);
184 	if (!job->databuf) {
185 		ERROR("Memory allocation failure!\n");
186 		return CUPS_BACKEND_RETRY_CURRENT;
187 	}
188 
189 	{
190 		int remain = job->datalen;
191 		uint8_t *ptr = job->databuf;
192 		do {
193 			ret = read(data_fd, ptr, remain);
194 			if (ret < 0) {
195 				ERROR("Read failed (%d/%d/%d)\n",
196 				      ret, remain, job->datalen);
197 				perror("ERROR: Read failed");
198 				return CUPS_BACKEND_CANCEL;
199 			}
200 			ptr += ret;
201 			remain -= ret;
202 		} while (remain);
203 	}
204 
205 	return CUPS_BACKEND_OK;
206 }
207 
sinfonia_raw18_read_parse(int data_fd,struct sinfonia_printjob * job)208 int sinfonia_raw18_read_parse(int data_fd, struct sinfonia_printjob *job)
209 {
210 	struct sinfonia_printcmd18_hdr hdr;
211 	int ret;
212 
213 	/* Read in header */
214 	ret = read(data_fd, &hdr, sizeof(hdr));
215 	if (ret < 0 || ret != sizeof(hdr)) {
216 		if (ret == 0)
217 			return CUPS_BACKEND_CANCEL;
218 		ERROR("Read failed (%d/%d/%d)\n",
219 		      ret, 0, (int)sizeof(hdr));
220 		perror("ERROR: Read failed");
221 		return CUPS_BACKEND_CANCEL;
222 	}
223 	/* Validate header */
224 	if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB ||
225 	    le16_to_cpu(hdr.hdr.len) != 18) {
226 		ERROR("Unrecognized data format!\n");
227 		return CUPS_BACKEND_CANCEL;
228 	}
229 	job->jp.copies = le16_to_cpu(hdr.copies);
230 	job->jp.rows = le16_to_cpu(hdr.rows);
231 	job->jp.columns = le16_to_cpu(hdr.columns);
232 	job->jp.media = hdr.media;
233 	job->jp.oc_mode = hdr.oc_mode;
234 	job->jp.method = hdr.method;
235 
236 	/* Allocate buffer */
237 	job->datalen = job->jp.rows * job->jp.columns * 3;
238 	job->databuf = malloc(job->datalen);
239 	if (!job->databuf) {
240 		ERROR("Memory allocation failure!\n");
241 		return CUPS_BACKEND_RETRY_CURRENT;
242 	}
243 
244 	{
245 		int remain = job->datalen;
246 		uint8_t *ptr = job->databuf;
247 		do {
248 			ret = read(data_fd, ptr, remain);
249 			if (ret < 0) {
250 				ERROR("Read failed (%d/%d/%d)\n",
251 				      ret, remain, job->datalen);
252 				perror("ERROR: Read failed");
253 				return CUPS_BACKEND_CANCEL;
254 			}
255 			ptr += ret;
256 			remain -= ret;
257 		} while (remain);
258 	}
259 
260 	return CUPS_BACKEND_OK;
261 }
262 
sinfonia_raw28_read_parse(int data_fd,struct sinfonia_printjob * job)263 int sinfonia_raw28_read_parse(int data_fd, struct sinfonia_printjob *job)
264 {
265 	struct sinfonia_printcmd28_hdr hdr;
266 	int ret;
267 
268 	/* Read in header */
269 	ret = read(data_fd, &hdr, sizeof(hdr));
270 	if (ret < 0 || ret != sizeof(hdr)) {
271 		if (ret == 0)
272 			return CUPS_BACKEND_CANCEL;
273 		ERROR("Read failed (%d/%d/%d)\n",
274 		      ret, 0, (int)sizeof(hdr));
275 		perror("ERROR: Read failed");
276 		return CUPS_BACKEND_CANCEL;
277 	}
278 	/* Validate header */
279 	if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB ||
280 	    le16_to_cpu(hdr.hdr.len) != 28) {
281 		ERROR("Unrecognized data format!\n");
282 		return CUPS_BACKEND_CANCEL;
283 	}
284 	job->jp.copies = le16_to_cpu(hdr.copies);
285 	job->jp.rows = le16_to_cpu(hdr.rows);
286 	job->jp.columns = le16_to_cpu(hdr.columns);
287 	job->jp.media = hdr.media;
288 	job->jp.oc_mode = hdr.options & 0x03;
289 	job->jp.quality = hdr.options & 0x08;
290 	job->jp.method = hdr.method;
291 
292 	/* Allocate buffer */
293 	job->datalen = job->jp.rows * job->jp.columns * 3;
294 	job->databuf = malloc(job->datalen);
295 	if (!job->databuf) {
296 		ERROR("Memory allocation failure!\n");
297 		return CUPS_BACKEND_RETRY_CURRENT;
298 	}
299 
300 	{
301 		int remain = job->datalen;
302 		uint8_t *ptr = job->databuf;
303 		do {
304 			ret = read(data_fd, ptr, remain);
305 			if (ret < 0) {
306 				ERROR("Read failed (%d/%d/%d)\n",
307 				      ret, remain, job->datalen);
308 				perror("ERROR: Read failed");
309 				return CUPS_BACKEND_CANCEL;
310 			}
311 			ptr += ret;
312 			remain -= ret;
313 		} while (remain);
314 	}
315 
316 	return CUPS_BACKEND_OK;
317 }
318 
sinfonia_cleanup_job(const void * vjob)319 void sinfonia_cleanup_job(const void *vjob)
320 {
321 	const struct sinfonia_printjob *job = vjob;
322 
323 	if (job->databuf)
324 		free(job->databuf);
325 
326 	free((void*)job);
327 }
328 
sinfonia_docmd(struct sinfonia_usbdev * usbh,uint8_t * cmd,int cmdlen,uint8_t * resp,int resplen,int * num)329 int sinfonia_docmd(struct sinfonia_usbdev *usbh,
330 		   uint8_t *cmd, int cmdlen,
331 		   uint8_t *resp, int resplen,
332 		   int *num)
333 {
334 	libusb_device_handle *dev = usbh->dev;
335 	uint8_t endp_up = usbh->endp_up;
336 	uint8_t endp_down = usbh->endp_down;
337 	int ret;
338 
339 	struct sinfonia_cmd_hdr *cmdhdr =  (struct sinfonia_cmd_hdr *) cmd;
340 	struct sinfonia_status_hdr *resphdr = (struct sinfonia_status_hdr *)resp;
341 
342 	if ((ret = send_data(dev, endp_down,
343 			     cmd, cmdlen))) {
344 		goto fail;
345 	}
346 
347 	ret = read_data(dev, endp_up,
348 			(uint8_t *)resp, resplen, num);
349 
350 	if (ret < 0)
351 		goto fail;
352 
353 	if (resphdr->result != RESULT_SUCCESS) {
354 		INFO("Printer Status:  %02x (%s)\n", resphdr->status,
355 		     sinfonia_status_str(resphdr->status));
356 		INFO(" Result: 0x%02x  Error: 0x%02x (0x%02x/0x%02x = %s)\n",
357 		     resphdr->result, resphdr->error, resphdr->printer_major,
358 		     resphdr->printer_minor, usbh->error_codes(resphdr->printer_major, resphdr->printer_minor));
359 		goto fail;
360 	}
361 
362 	return 0;
363 fail:
364 	ERROR("Failed to execute %s command\n", sinfonia_cmd_names(cmdhdr->cmd));
365 	return ret;
366 }
367 
sinfonia_flashled(struct sinfonia_usbdev * usbh)368 int sinfonia_flashled(struct sinfonia_usbdev *usbh)
369 {
370 	struct sinfonia_cmd_hdr cmd;
371 	struct sinfonia_status_hdr resp;
372 	int ret, num = 0;
373 
374 	cmd.cmd = cpu_to_le16(SINFONIA_CMD_FLASHLED);
375 	cmd.len = cpu_to_le16(0);
376 
377 	if ((ret = sinfonia_docmd(usbh,
378 				  (uint8_t*)&cmd, sizeof(cmd),
379 				  (uint8_t*)&resp, sizeof(resp),
380 				  &num)) < 0) {
381 		return ret;
382 	}
383 
384 	return 0;
385 }
386 
sinfonia_canceljob(struct sinfonia_usbdev * usbh,int id)387 int sinfonia_canceljob(struct sinfonia_usbdev *usbh, int id)
388 {
389 	struct sinfonia_cancel_cmd cmd;
390 	struct sinfonia_status_hdr resp;
391 	int ret, num = 0;
392 
393 	cmd.id = id;
394 
395 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_CANCELJOB);
396 	cmd.hdr.len = cpu_to_le16(1);
397 
398 	if ((ret = sinfonia_docmd(usbh,
399 				  (uint8_t*)&cmd, sizeof(cmd),
400 				  (uint8_t*)&resp, sizeof(resp),
401 				  &num)) < 0) {
402 		return ret;
403 	}
404 
405 	return 0;
406 }
407 
sinfonia_getparam(struct sinfonia_usbdev * usbh,int target,uint32_t * param)408 int sinfonia_getparam(struct sinfonia_usbdev *usbh, int target, uint32_t *param)
409 {
410 	struct sinfonia_getparam_cmd cmd;
411 	struct sinfonia_getparam_resp resp;
412 	int ret, num = 0;
413 
414 	/* Set up command */
415 	cmd.target = target;
416 
417 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_GETPARAM);
418 	cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_getparam_cmd)-sizeof(cmd.hdr));
419 
420 	if ((ret = sinfonia_docmd(usbh,
421 				  (uint8_t*)&cmd, sizeof(cmd),
422 				  (uint8_t*)&resp, sizeof(resp),
423 				  &num)) < 0) {
424 	}
425 	*param = le32_to_cpu(resp.param);
426 
427 	return ret;
428 }
429 
sinfonia_setparam(struct sinfonia_usbdev * usbh,int target,uint32_t param)430 int sinfonia_setparam(struct sinfonia_usbdev *usbh, int target, uint32_t param)
431 {
432 	struct sinfonia_setparam_cmd cmd;
433 	struct sinfonia_status_hdr resp;
434 	int ret, num = 0;
435 
436 	/* Set up command */
437 	cmd.target = target;
438 	cmd.param = cpu_to_le32(param);
439 
440 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_SETPARAM);
441 	cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_setparam_cmd)-sizeof(cmd.hdr));
442 
443 	if ((ret = sinfonia_docmd(usbh,
444 				  (uint8_t*)&cmd, sizeof(cmd),
445 				  (uint8_t*)&resp, sizeof(resp),
446 				  &num)) < 0) {
447 	}
448 
449 	return ret;
450 }
451 
sinfonia_getfwinfo(struct sinfonia_usbdev * usbh)452 int sinfonia_getfwinfo(struct sinfonia_usbdev *usbh)
453 {
454 	struct sinfonia_fwinfo_cmd  cmd;
455 	struct sinfonia_fwinfo_resp resp;
456 	int num = 0;
457 	int i;
458 
459 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_FWINFO);
460 	cmd.hdr.len = cpu_to_le16(1);
461 
462 	resp.hdr.payload_len = 0;
463 
464 	INFO("FW Information:\n");
465 
466 	for (i = FWINFO_TARGET_MAIN_BOOT ; i <= FWINFO_TARGET_PRINT_TABLES2 ; i++) {
467 		int ret;
468 		cmd.target = i;
469 
470 		if ((ret = sinfonia_docmd(usbh,
471 					  (uint8_t*)&cmd, sizeof(cmd),
472 					  (uint8_t*)&resp, sizeof(resp),
473 					  &num)) < 0) {
474 			continue;
475 		}
476 
477 		if (resp.major == 0)
478 			continue;
479 
480 		if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_fwinfo_resp) - sizeof(struct sinfonia_status_hdr)))
481 			continue;
482 
483 		INFO(" %s\t ver %02x.%02x\n", sinfonia_fwinfo_targets(i),
484 		     resp.major, resp.minor);
485 #if 0
486 		INFO("  name:    '%s'\n", resp.name);
487 		INFO("  type:    '%s'\n", resp.type);
488 		INFO("  date:    '%s'\n", resp.date);
489 		INFO("  version: %02x.%02x (CRC %04x)\n", resp.major, resp.minor,
490 		     le16_to_cpu(resp.checksum));
491 #endif
492 	}
493 	return 0;
494 }
495 
sinfonia_geterrorlog(struct sinfonia_usbdev * usbh)496 int sinfonia_geterrorlog(struct sinfonia_usbdev *usbh)
497 {
498 	struct sinfonia_cmd_hdr cmd;
499 	struct sinfonia_errorlog_resp resp;
500 	int ret, num = 0;
501 	int i;
502 
503 	cmd.cmd = cpu_to_le16(SINFONIA_CMD_ERRORLOG);
504 	cmd.len = cpu_to_le16(0);
505 
506 	resp.hdr.payload_len = 0;
507 
508 	if ((ret = sinfonia_docmd(usbh,
509 				  (uint8_t*)&cmd, sizeof(cmd),
510 				  (uint8_t*)&resp, sizeof(resp),
511 				  &num)) < 0) {
512 		return ret;
513 	}
514 
515 	if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_errorlog_resp) - sizeof(struct sinfonia_status_hdr)))
516 		return -2;
517 
518 	INFO("Stored Error Events: %u entries:\n", resp.count);
519 	for (i = 0 ; i < resp.count ; i++) {
520 		INFO(" %02d: @ %08u prints : 0x%02x/0x%02x (%s)\n", i,
521 		     le32_to_cpu(resp.items[i].print_counter),
522 		     resp.items[i].major, resp.items[i].minor,
523 		     usbh->error_codes(resp.items[i].major, resp.items[i].minor));
524 	}
525 	return 0;
526 }
527 
sinfonia_resetcurve(struct sinfonia_usbdev * usbh,int target,int id)528 int sinfonia_resetcurve(struct sinfonia_usbdev *usbh, int target, int id)
529 {
530 	struct sinfonia_reset_cmd cmd;
531 	struct sinfonia_status_hdr resp;
532 	int ret, num = 0;
533 
534 	cmd.target = target;
535 	cmd.curveid = id;
536 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_RESET);
537 	cmd.hdr.len = cpu_to_le16(2);
538 
539 	if ((ret = sinfonia_docmd(usbh,
540 				  (uint8_t*)&cmd, sizeof(cmd),
541 				  (uint8_t*)&resp, sizeof(resp),
542 				  &num)) < 0) {
543 		return ret;
544 	}
545 
546 	return 0;
547 }
548 
sinfonia_gettonecurve(struct sinfonia_usbdev * usbh,int type,char * fname)549 int sinfonia_gettonecurve(struct sinfonia_usbdev *usbh, int type, char *fname)
550 {
551 	struct sinfonia_readtone_cmd cmd;
552 	struct sinfonia_readtone_resp resp;
553 	int ret, num = 0;
554 
555 	uint8_t *data;
556 	uint16_t curves[TONE_CURVE_SIZE] = { 0 };
557 
558 	int i,j;
559 
560 	cmd.target = type;
561 	cmd.curveid = TONE_CURVE_ID;
562 
563 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_READTONE);
564 	cmd.hdr.len = cpu_to_le16(1);
565 
566 	resp.hdr.payload_len = 0;
567 
568 	INFO("Dump %s Tone Curve to '%s'\n", sinfonia_tonecurve_statuses(type), fname);
569 
570 	if ((ret = sinfonia_docmd(usbh,
571 				  (uint8_t*)&cmd, sizeof(cmd),
572 				  (uint8_t*)&resp, sizeof(resp),
573 				  &num)) < 0) {
574 		return ret;
575 	}
576 
577 	if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_readtone_resp) - sizeof(struct sinfonia_status_hdr)))
578 		return -2;
579 
580 	resp.total_size = le16_to_cpu(resp.total_size);
581 
582 	data = malloc(resp.total_size * 2);
583 	if (!data) {
584 		ERROR("Memory Allocation Failure!\n");
585 		return -1;
586 	}
587 
588 	i = 0;
589 	while (i < resp.total_size) {
590 		ret = read_data(usbh->dev, usbh->endp_up,
591 				data + i,
592 				resp.total_size * 2 - i,
593 				&num);
594 		if (ret < 0)
595 			goto done;
596 		i += num;
597 	}
598 
599 	i = j = 0;
600 	while (i < resp.total_size) {
601 		memcpy(curves + j, data + i+2, data[i+1]);
602 		j += data[i+1] / 2;
603 		i += data[i+1] + 2;
604 	}
605 
606 	/* Open file and write it out */
607 	{
608 		int tc_fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
609 		if (tc_fd < 0) {
610 			ret = -1;
611 			goto done;
612 		}
613 
614 		for (i = 0 ; i < TONE_CURVE_SIZE; i++) {
615 			/* Byteswap appropriately */
616 			curves[i] = cpu_to_be16(le16_to_cpu(curves[i]));
617 		}
618 		ret = write(tc_fd, curves, TONE_CURVE_SIZE * sizeof(uint16_t));
619 		close(tc_fd);
620 	}
621 
622 done:
623 	free(data);
624 	return ret;
625 }
626 
sinfonia_settonecurve(struct sinfonia_usbdev * usbh,int target,char * fname)627 int sinfonia_settonecurve(struct sinfonia_usbdev *usbh, int target, char *fname)
628 {
629 	struct sinfonia_update_cmd cmd;
630 	struct sinfonia_status_hdr resp;
631 	int ret, num = 0;
632 
633 	INFO("Set %s Tone Curve from '%s'\n", sinfonia_update_targets(target), fname);
634 
635 	uint16_t *data = malloc(TONE_CURVE_SIZE * sizeof(uint16_t));
636 	if (!data) {
637 		ERROR("Memory Allocation Failure!\n");
638 		return -1;
639 	}
640 
641 	/* Read in file */
642 	if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE * sizeof(uint16_t), NULL))) {
643 		ERROR("Failed to read Tone Curve file\n");
644 		goto done;
645 	}
646 
647 	/* Byteswap data to local CPU.. */
648 	for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) {
649 		data[ret] = be16_to_cpu(data[ret]);
650 	}
651 
652 	/* Set up command */
653 	cmd.target = target;
654 	cmd.curve_id = TONE_CURVE_ID;
655 	cmd.reserved[0] = cmd.reserved[1] = cmd.reserved[2] = 0;
656 	cmd.reset = 0;
657 	cmd.size = cpu_to_le32(TONE_CURVE_SIZE * sizeof(uint16_t));
658 
659 	cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_UPDATE);
660 	cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_update_cmd)-sizeof(cmd.hdr));
661 
662 	/* Byteswap data to format printer is expecting.. */
663 	for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) {
664 		data[ret] = cpu_to_le16(data[ret]);
665 	}
666 
667 	if ((ret = sinfonia_docmd(usbh,
668 				  (uint8_t*)&cmd, sizeof(cmd),
669 				  (uint8_t*)&resp, sizeof(resp),
670 				  &num)) < 0) {
671 		return ret;
672 	}
673 
674 	/* Sent transfer */
675 	if ((ret = send_data(usbh->dev, usbh->endp_down,
676 			     (uint8_t *) data, TONE_CURVE_SIZE * sizeof(uint16_t)))) {
677 		goto done;
678 	}
679 
680 done:
681 	free(data);
682 
683 	return ret;
684 }
685 
sinfonia_update_targets(uint8_t v)686 const char *sinfonia_update_targets (uint8_t v) {
687 	switch (v) {
688 	case UPDATE_TARGET_USER:
689 		return "User";
690 	case UPDATE_TARGET_CURRENT:
691 		return "Current";
692 	default:
693 		return "Unknown";
694 	}
695 }
696 
sinfonia_tonecurve_statuses(uint8_t v)697 const char *sinfonia_tonecurve_statuses (uint8_t v)
698 {
699 	switch(v) {
700 	case 0:
701 		return "Initial";
702 	case 1:
703 		return "UserSet";
704 	case 2:
705 		return "Current";
706 	default:
707 		return "Unknown";
708 	}
709 }
710 
sinfonia_bank_statuses(uint8_t v)711 const char *sinfonia_bank_statuses(uint8_t v)
712 {
713 	switch (v) {
714 	case BANK_STATUS_FREE:
715 		return "Free";
716 	case BANK_STATUS_XFER:
717 		return "Xfer";
718 	case BANK_STATUS_FULL:
719 		return "Full";
720 	case BANK_STATUS_PRINTING:
721 		return "Printing";
722 	default:
723 		return "Unknown";
724 	}
725 }
726 
sinfonia_error_str(uint8_t v)727 const char *sinfonia_error_str(uint8_t v) {
728 	switch (v) {
729 	case ERROR_NONE:
730 		return "None";
731 	case ERROR_INVALID_PARAM:
732 		return "Invalid Command Parameter";
733 	case ERROR_MAIN_APP_INACTIVE:
734 		return "Main App Inactive";
735 	case ERROR_COMMS_TIMEOUT:
736 		return "Main Communication Timeout";
737 	case ERROR_MAINT_NEEDED:
738 		return "Maintenance Needed";
739 	case ERROR_BAD_COMMAND:
740 		return "Inappropriate Command";
741 	case ERROR_PRINTER:
742 		return "Printer Error";
743 	case ERROR_BUFFER_FULL:
744 		return "Buffer Full";
745 	default:
746 		return "Unknown";
747 	}
748 }
749 
sinfonia_media_types(uint8_t v)750 const char *sinfonia_media_types(uint8_t v) {
751 	switch (v) {
752 	case MEDIA_TYPE_UNKNOWN:
753 		return "Unknown";
754 	case MEDIA_TYPE_PAPER:
755 		return "Paper";
756 	default:
757 		return "Unknown";
758 	}
759 }
760 
sinfonia_print_methods(uint8_t v)761 const char *sinfonia_print_methods (uint8_t v) {
762 	switch (v & 0xf) {
763 	case PRINT_METHOD_STD:
764 		return "Standard";
765 	case PRINT_METHOD_COMBO_2:
766 		return "2up";
767 	case PRINT_METHOD_COMBO_3:
768 		return "3up";
769 	case PRINT_METHOD_SPLIT:
770 		return "Split";
771 	case PRINT_METHOD_DOUBLE:
772 		return "Double";
773 	default:
774 		return "Unknown";
775 	}
776 }
777 
sinfonia_print_modes(uint8_t v)778 const char *sinfonia_print_modes(uint8_t v) {
779 	switch (v) {
780 	case PRINT_MODE_NO_OC:
781 		return "No Overcoat";
782 	case PRINT_MODE_GLOSSY:
783 		return "Glossy";
784 	case PRINT_MODE_MATTE:
785 		return "Matte";
786 	default:
787 		return "Unknown";
788 	}
789 }
790 
sinfonia_fwinfo_targets(uint8_t v)791 const char *sinfonia_fwinfo_targets (uint8_t v) {
792 	switch (v) {
793 	case FWINFO_TARGET_MAIN_BOOT:
794 		return "Main Boot   ";
795 	case FWINFO_TARGET_MAIN_APP:
796 		return "Main App    ";
797 	case FWINFO_TARGET_PRINT_TABLES:
798 	case FWINFO_TARGET_PRINT_TABLES2:  // Seen on EK70xx
799 		return "Print Tables";
800 	case FWINFO_TARGET_DSP:
801 		return "DSP         ";
802 	case FWINFO_TARGET_USB:
803 		return "USB         ";
804 	default:
805 		return "Unknown     ";
806 	}
807 }
808 
sinfonia_print_codes(uint8_t v,int eightinch)809 const char *sinfonia_print_codes (uint8_t v, int eightinch) {
810 	if (eightinch) {
811 		switch (v) {
812 		case CODE_8x10:
813 			return "8x10";
814 		case CODE_8x12:
815 		case CODE_8x12K:
816 			return "8x12";
817 		case CODE_8x4:
818 			return "8x4";
819 		case CODE_8x5:
820 			return "8x5";
821 		case CODE_8x6:
822 			return "8x6";
823 		case CODE_8x8:
824 			return "8x8";
825 		case CODE_8x4_2:
826 			return "8x4*2";
827 		case CODE_8x5_2:
828 			return "8x5*2";
829 		case CODE_8x6_2:
830 			return "8x6*2";
831 		case CODE_8x4_3:
832 			return "8x4*3";
833 		default:
834 			return "Unknown";
835 		}
836 	}
837 
838 	switch (v) {
839 	case CODE_4x6:
840 		return "4x6";
841 	case CODE_3_5x5:
842 		return "3.5x5";
843 	case CODE_5x7:
844 		return "5x7";
845 	case CODE_6x9:
846 		return "6x9";
847 	case CODE_6x8:
848 		return "6x8";
849 	case CODE_2x6:
850 		return "2x6";
851 	case CODE_6x6:
852 		return "6x6";
853 	case CODE_89x60mm:
854 		return "89x60mm";
855 	case CODE_89x59mm:
856 		return "89x59mm";
857 	case CODE_89x58mm:
858 		return "89x58mm";
859 	case CODE_89x57mm:
860 		return "89x57mm";
861 	case CODE_89x56mm:
862 		return "89x56mm";
863 	case CODE_89x55mm:
864 		return "89x55mm";
865 	default:
866 		return "Unknown";
867 	}
868 }
869 
sinfonia_status_str(uint8_t v)870 const char *sinfonia_status_str(uint8_t v) {
871 	switch (v) {
872 	case STATUS_READY:
873 		return "Ready";
874 	case STATUS_INIT_CPU:
875 		return "Initializing CPU";
876 	case STATUS_INIT_RIBBON:
877 		return "Initializing Ribbon";
878 	case STATUS_INIT_PAPER:
879 		return "Loading Paper";
880 	case STATUS_THERMAL_PROTECT:
881 		return "Thermal Protection";
882 	case STATUS_USING_PANEL:
883 		return "Using Operation Panel";
884 	case STATUS_SELF_DIAG:
885 		return "Processing Self Diagnosis";
886 	case STATUS_DOWNLOADING:
887 		return "Processing Download";
888 	case STATUS_FEEDING_PAPER:
889 		return "Feeding Paper";
890 	case STATUS_PRE_HEAT:
891 		return "Pre-Heating";
892 	case STATUS_PRINT_Y:
893 		return "Printing Yellow";
894 	case STATUS_BACK_FEED_Y:
895 		return "Back-Feeding - Yellow Complete";
896 	case STATUS_PRINT_M:
897 		return "Printing Magenta";
898 	case STATUS_BACK_FEED_M:
899 		return "Back-Feeding - Magenta Complete";
900 	case STATUS_PRINT_C:
901 		return "Printing Cyan";
902 	case STATUS_BACK_FEED_C:
903 		return "Back-Feeding - Cyan Complete";
904 	case STATUS_PRINT_OP:
905 		return "Laminating";
906 	case STATUS_PAPER_CUT:
907 		return "Cutting Paper";
908 	case STATUS_PAPER_EJECT:
909 		return "Ejecting Paper";
910 	case STATUS_BACK_FEED_E:
911 		return "Back-Feeding - Ejected";
912 	case STATUS_FINISHED:
913 		return "Print Finished";
914 	case ERROR_PRINTER:
915 		return "Printer Error";
916 	default:
917 		return "Unknown";
918 	}
919 }
920 
sinfonia_cmd_names(uint16_t v)921 const char *sinfonia_cmd_names(uint16_t v) {
922 	switch (le16_to_cpu(v)) {
923 	case SINFONIA_CMD_GETSTATUS:
924 		return "Get Status";
925 	case SINFONIA_CMD_MEDIAINFO:
926 		return "Get Media Info";
927 	case SINFONIA_CMD_MODELNAME:
928 		return "Get Model Name";
929 	case SINFONIA_CMD_ERRORLOG:
930 		return "Get Error Log";
931 	case SINFONIA_CMD_GETPARAM:
932 		return "Get Parameter";
933 	case SINFONIA_CMD_GETSERIAL:
934 		return "Get Serial Number";
935 	case SINFONIA_CMD_PRINTSTAT:
936 		return "Get Print ID Status";
937 	case SINFONIA_CMD_EXTCOUNTER:
938 		return "Get Extended Counters";
939 	case SINFONIA_CMD_PRINTJOB:
940 		return "Print";
941 	case SINFONIA_CMD_CANCELJOB:
942 		return "Cancel Print";
943 	case SINFONIA_CMD_FLASHLED:
944 		return "Flash LEDs";
945 	case SINFONIA_CMD_RESET:
946 		return "Reset";
947 	case SINFONIA_CMD_READTONE:
948 		return "Read Tone Curve";
949 	case SINFONIA_CMD_BUTTON:
950 		return "Button Enable";
951 	case SINFONIA_CMD_SETPARAM:
952 		return "Set Parameter";
953 	case SINFONIA_CMD_GETUNIQUE:
954 		return "Get Unique String";
955 	case SINFONIA_CMD_GETCORR:
956 		return "Get Image Correction Parameter";
957 	case SINFONIA_CMD_GETEEPROM:
958 		return "Get EEPROM Backup Parameter";
959 	case SINFONIA_CMD_SETEEPROM:
960 		return "Set EEPROM Backup Parameter";
961 	case SINFONIA_CMD_SETTIME:
962 		return "Time Setting";
963 	case SINFONIA_CMD_DIAGNOSTIC:
964 		return "Diagnostic";
965 	case SINFONIA_CMD_FWINFO:
966 		return "Get Firmware Info";
967 	case SINFONIA_CMD_UPDATE:
968 		return "Update";
969 	case SINFONIA_CMD_SETUNIQUE:
970 		return "Set Unique String";
971 	default:
972 		return "Unknown Command";
973 	}
974 }
975 
kodak6_mediatypes(int type)976 const char *kodak6_mediatypes(int type)
977 {
978 	switch(type) {
979 	case KODAK6_MEDIA_NONE:
980 		return "No media";
981 	case KODAK6_MEDIA_6R:
982 	case KODAK6_MEDIA_6TR2:
983 	case KODAK7_MEDIA_6R:
984 		return "Kodak 6R";
985 
986 	default:
987 		return "Unknown";
988 	}
989 	return "Unknown";
990 }
991 
kodak6_dumpmediacommon(int type)992 void kodak6_dumpmediacommon(int type)
993 {
994 	switch (type) {
995 	case KODAK6_MEDIA_6R:
996 		INFO("Media type: 6R (Kodak 197-4096 or equivalent)\n");
997 		break;
998 	case KODAK6_MEDIA_6TR2:
999 		INFO("Media type: 6R (Kodak 396-2941 or equivalent)\n");
1000 		break;
1001 	case KODAK7_MEDIA_6R:
1002 		INFO("Media type: 6R (Kodak 659-9047 or equivalent)\n");
1003 		break;
1004 	default:
1005 		INFO("Media type %02x (unknown, please report!)\n", type);
1006 		break;
1007 	}
1008 }
1009 
1010 /* Below are for S1145 (EK68xx) and S1245 only! */
sinfonia_1x45_status_str(uint8_t status1,uint32_t status2,uint8_t error)1011 const char *sinfonia_1x45_status_str(uint8_t status1, uint32_t status2, uint8_t error)
1012 {
1013 	switch(status1) {
1014 	case STATE_STATUS1_STANDBY:
1015 		return "Standby (Ready)";
1016 	case STATE_STATUS1_WAIT:
1017 		switch (status2) {
1018 		case WAIT_STATUS2_INIT:
1019 			return "Wait (Initializing)";
1020 		case WAIT_STATUS2_RIBBON:
1021 			return "Wait (Ribbon Winding)";
1022 		case WAIT_STATUS2_THERMAL:
1023 			return "Wait (Thermal Protection)";
1024 		case WAIT_STATUS2_OPERATING:
1025 			return "Wait (Operating)";
1026 		case WAIT_STATUS2_BUSY:
1027 			return "Wait (Busy)";
1028 		default:
1029 			return "Wait (Unknown)";
1030 		}
1031 	case STATE_STATUS1_ERROR:
1032 		switch (status2) {
1033 		case ERROR_STATUS2_CTRL_CIRCUIT:
1034 			switch (error) {
1035 			case CTRL_CIR_ERROR_EEPROM1:
1036 				return "Error (EEPROM1)";
1037 			case CTRL_CIR_ERROR_EEPROM2:
1038 				return "Error (EEPROM2)";
1039 			case CTRL_CIR_ERROR_DSP:
1040 				return "Error (DSP)";
1041 			case CTRL_CIR_ERROR_CRC_MAIN:
1042 				return "Error (Main CRC)";
1043 			case CTRL_CIR_ERROR_DL_MAIN:
1044 				return "Error (Main Download)";
1045 			case CTRL_CIR_ERROR_CRC_DSP:
1046 				return "Error (DSP CRC)";
1047 			case CTRL_CIR_ERROR_DL_DSP:
1048 				return "Error (DSP Download)";
1049 			case CTRL_CIR_ERROR_ASIC:
1050 				return "Error (ASIC)";
1051 			case CTRL_CIR_ERROR_DRAM:
1052 				return "Error (DRAM)";
1053 			case CTRL_CIR_ERROR_DSPCOMM:
1054 				return "Error (DSP Communincation)";
1055 			default:
1056 				return "Error (Unknown Circuit)";
1057 			}
1058 		case ERROR_STATUS2_MECHANISM_CTRL:
1059 			switch (error) {
1060 			case MECH_ERROR_HEAD_UP:
1061 				return "Error (Head Up Mechanism)";
1062 			case MECH_ERROR_HEAD_DOWN:
1063 				return "Error (Head Down Mechanism)";
1064 			case MECH_ERROR_MAIN_PINCH_UP:
1065 				return "Error (Main Pinch Up Mechanism)";
1066 			case MECH_ERROR_MAIN_PINCH_DOWN:
1067 				return "Error (Main Pinch Down Mechanism)";
1068 			case MECH_ERROR_SUB_PINCH_UP:
1069 				return "Error (Sub Pinch Up Mechanism)";
1070 			case MECH_ERROR_SUB_PINCH_DOWN:
1071 				return "Error (Sub Pinch Down Mechanism)";
1072 			case MECH_ERROR_FEEDIN_PINCH_UP:
1073 				return "Error (Feed-in Pinch Up Mechanism)";
1074 			case MECH_ERROR_FEEDIN_PINCH_DOWN:
1075 				return "Error (Feed-in Pinch Down Mechanism)";
1076 			case MECH_ERROR_FEEDOUT_PINCH_UP:
1077 				return "Error (Feed-out Pinch Up Mechanism)";
1078 			case MECH_ERROR_FEEDOUT_PINCH_DOWN:
1079 				return "Error (Feed-out Pinch Down Mechanism)";
1080 			case MECH_ERROR_CUTTER_LR:
1081 				return "Error (Left->Right Cutter)";
1082 			case MECH_ERROR_CUTTER_RL:
1083 				return "Error (Right->Left Cutter)";
1084 			default:
1085 				return "Error (Unknown Mechanism)";
1086 			}
1087 		case ERROR_STATUS2_SENSOR:
1088 			switch (error) {
1089 			case SENSOR_ERROR_CUTTER:
1090 				return "Error (Cutter Sensor)";
1091 			case SENSOR_ERROR_HEAD_DOWN:
1092 				return "Error (Head Down Sensor)";
1093 			case SENSOR_ERROR_HEAD_UP:
1094 				return "Error (Head Up Sensor)";
1095 			case SENSOR_ERROR_MAIN_PINCH_DOWN:
1096 				return "Error (Main Pinch Down Sensor)";
1097 			case SENSOR_ERROR_MAIN_PINCH_UP:
1098 				return "Error (Main Pinch Up Sensor)";
1099 			case SENSOR_ERROR_FEED_PINCH_DOWN:
1100 				return "Error (Feed Pinch Down Sensor)";
1101 			case SENSOR_ERROR_FEED_PINCH_UP:
1102 				return "Error (Feed Pinch Up Sensor)";
1103 			case SENSOR_ERROR_EXIT_PINCH_DOWN:
1104 				return "Error (Exit Pinch Up Sensor)";
1105 			case SENSOR_ERROR_EXIT_PINCH_UP:
1106 				return "Error (Exit Pinch Up Sensor)";
1107 			case SENSOR_ERROR_LEFT_CUTTER:
1108 				return "Error (Left Cutter Sensor)";
1109 			case SENSOR_ERROR_RIGHT_CUTTER:
1110 				return "Error (Right Cutter Sensor)";
1111 			case SENSOR_ERROR_CENTER_CUTTER:
1112 				return "Error (Center Cutter Sensor)";
1113 			case SENSOR_ERROR_UPPER_CUTTER:
1114 				return "Error (Upper Cutter Sensor)";
1115 			case SENSOR_ERROR_PAPER_FEED_COVER:
1116 				return "Error (Paper Feed Cover)";
1117 			default:
1118 				return "Error (Unknown Sensor)";
1119 			}
1120 		case ERROR_STATUS2_COVER_OPEN:
1121 			switch (error) {
1122 			case COVER_OPEN_ERROR_UPPER:
1123 				return "Error (Upper Cover Open)";
1124 			case COVER_OPEN_ERROR_LOWER:
1125 				return "Error (Lower Cover Open)";
1126 			default:
1127 				return "Error (Unknown Cover Open)";
1128 			}
1129 		case ERROR_STATUS2_TEMP_SENSOR:
1130 			switch (error) {
1131 			case TEMP_SENSOR_ERROR_HEAD_HIGH:
1132 				return "Error (Head Temperature High)";
1133 			case TEMP_SENSOR_ERROR_HEAD_LOW:
1134 				return "Error (Head Temperature Low)";
1135 			case TEMP_SENSOR_ERROR_ENV_HIGH:
1136 				return "Error (Environmental Temperature High)";
1137 			case TEMP_SENSOR_ERROR_ENV_LOW:
1138 				return "Error (Environmental Temperature Low)";
1139 			default:
1140 				return "Error (Unknown Temperature)";
1141 			}
1142 		case ERROR_STATUS2_PAPER_JAM:
1143 			return "Error (Paper Jam)";
1144 		case ERROR_STATUS2_PAPER_EMPTY:
1145 			return "Error (Paper Empty)";
1146 		case ERROR_STATUS2_RIBBON_ERR:
1147 			return "Error (Ribbon)";
1148 		default:
1149 			return "Error (Unknown)";
1150 		}
1151 	default:
1152 		return "Unknown!";
1153 	}
1154 }
1155