2019-05-06 16:28:07 -04:00
|
|
|
/*
|
|
|
|
* Shinko/Sinfonia Common Code
|
|
|
|
*
|
2020-06-30 23:42:54 -04:00
|
|
|
* (c) 2019-2020 Solomon Peachy <pizza@shaftnet.org>
|
2019-05-06 16:28:07 -04:00
|
|
|
*
|
|
|
|
* The latest version of this program can be found at:
|
|
|
|
*
|
2021-01-23 10:47:01 -05:00
|
|
|
* https://git.shaftnet.org/cgit/selphy_print.git
|
2019-05-06 16:28:07 -04:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
|
|
* Software Foundation; either version 3 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2020-01-17 16:50:56 -05:00
|
|
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
2019-05-06 16:28:07 -04:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-3.0+
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "backend_common.h"
|
2019-05-13 10:29:00 -04:00
|
|
|
#include "backend_sinfonia.h"
|
2019-05-06 16:28:07 -04:00
|
|
|
|
|
|
|
int sinfonia_read_parse(int data_fd, uint32_t model,
|
2019-05-13 10:41:28 -04:00
|
|
|
struct sinfonia_printjob *job)
|
2019-05-06 16:28:07 -04:00
|
|
|
{
|
2019-05-06 21:10:43 -04:00
|
|
|
uint32_t hdr[29];
|
2019-05-06 16:28:07 -04:00
|
|
|
int ret, i;
|
|
|
|
uint8_t tmpbuf[4];
|
|
|
|
|
|
|
|
/* Read in header */
|
|
|
|
ret = read(data_fd, hdr, SINFONIA_HDR_LEN);
|
|
|
|
if (ret < 0 || ret != SINFONIA_HDR_LEN) {
|
|
|
|
if (ret == 0)
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
ERROR("Read failed (%d/%d)\n",
|
|
|
|
ret, SINFONIA_HDR_LEN);
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Byteswap everything */
|
|
|
|
for (i = 0 ; i < (SINFONIA_HDR_LEN / 4) ; i++) {
|
|
|
|
hdr[i] = le32_to_cpu(hdr[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanity-check headers */
|
|
|
|
if (hdr[0] != SINFONIA_HDR1_LEN ||
|
|
|
|
hdr[4] != SINFONIA_HDR2_LEN ||
|
|
|
|
hdr[22] != SINFONIA_DPI) {
|
|
|
|
ERROR("Unrecognized header data format!\n");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
if (hdr[1] != model) {
|
|
|
|
ERROR("job/printer mismatch (%u/%u)!\n", hdr[1], model);
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hdr[13] || !hdr[14]) {
|
|
|
|
ERROR("Bad job cols/rows!\n");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Work out data length */
|
2019-05-13 10:41:28 -04:00
|
|
|
job->datalen = hdr[13] * hdr[14] * 3;
|
|
|
|
job->databuf = malloc(job->datalen);
|
|
|
|
if (!job->databuf) {
|
2019-05-06 16:28:07 -04:00
|
|
|
ERROR("Memory allocation failure!\n");
|
|
|
|
return CUPS_BACKEND_RETRY_CURRENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read in payload data */
|
|
|
|
{
|
2019-05-13 10:41:28 -04:00
|
|
|
uint32_t remain = job->datalen;
|
|
|
|
uint8_t *ptr = job->databuf;
|
2019-05-06 16:28:07 -04:00
|
|
|
do {
|
|
|
|
ret = read(data_fd, ptr, remain);
|
|
|
|
if (ret < 0) {
|
2019-05-14 23:06:39 -04:00
|
|
|
ERROR("Read failed (%d/%u/%d)\n",
|
2019-05-13 10:41:28 -04:00
|
|
|
ret, remain, job->datalen);
|
2019-05-06 16:28:07 -04:00
|
|
|
perror("ERROR: Read failed");
|
2019-05-13 10:41:28 -04:00
|
|
|
free(job->databuf);
|
|
|
|
job->databuf = NULL;
|
2019-05-06 16:28:07 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
ptr += ret;
|
|
|
|
remain -= ret;
|
|
|
|
} while (remain);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure footer is sane too */
|
|
|
|
ret = read(data_fd, tmpbuf, 4);
|
|
|
|
if (ret != 4) {
|
|
|
|
ERROR("Read failed (%d/%d)\n", ret, 4);
|
|
|
|
perror("ERROR: Read failed");
|
2019-05-13 10:41:28 -04:00
|
|
|
free(job->databuf);
|
|
|
|
job->databuf = NULL;
|
2019-05-06 16:28:07 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (tmpbuf[0] != 0x04 ||
|
|
|
|
tmpbuf[1] != 0x03 ||
|
|
|
|
tmpbuf[2] != 0x02 ||
|
|
|
|
tmpbuf[3] != 0x01) {
|
|
|
|
ERROR("Unrecognized footer data format!\n");
|
2019-05-13 10:41:28 -04:00
|
|
|
free (job->databuf);
|
|
|
|
job->databuf = NULL;
|
2019-05-06 16:28:07 -04:00
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill out job params */
|
2019-05-13 10:41:28 -04:00
|
|
|
job->jp.media = hdr[6];
|
|
|
|
if (hdr[1] != 6245)
|
|
|
|
job->jp.method = hdr[8];
|
|
|
|
if (hdr[1] == 2245 || hdr[1] == 6245)
|
|
|
|
job->jp.quality = hdr[9];
|
|
|
|
if (hdr[1] == 1245 || hdr[1] == 2145)
|
|
|
|
job->jp.oc_mode = hdr[9];
|
|
|
|
else
|
|
|
|
job->jp.oc_mode = hdr[10];
|
2020-03-03 00:16:05 -05:00
|
|
|
if (hdr[1] == 1245) {
|
2019-05-13 10:41:28 -04:00
|
|
|
job->jp.mattedepth = hdr[11];
|
|
|
|
job->jp.dust = hdr[12];
|
2020-03-03 00:16:05 -05:00
|
|
|
}
|
2019-05-13 10:41:28 -04:00
|
|
|
job->jp.columns = hdr[13];
|
|
|
|
job->jp.rows = hdr[14];
|
|
|
|
job->jp.copies = hdr[15];
|
|
|
|
|
|
|
|
if (hdr[1] == 2245 || hdr[1] == 6145)
|
|
|
|
job->jp.ext_flags = hdr[28];
|
2019-05-06 16:28:07 -04:00
|
|
|
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
2019-05-21 11:07:49 -04:00
|
|
|
int sinfonia_raw10_read_parse(int data_fd, struct sinfonia_printjob *job)
|
|
|
|
{
|
|
|
|
struct sinfonia_printcmd10_hdr hdr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Read in header */
|
|
|
|
ret = read(data_fd, &hdr, sizeof(hdr));
|
|
|
|
if (ret < 0 || ret != sizeof(hdr)) {
|
|
|
|
if (ret == 0)
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
ERROR("Read failed (%d/%d/%d)\n",
|
|
|
|
ret, 0, (int)sizeof(hdr));
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
/* Validate header */
|
2019-09-08 21:33:30 -04:00
|
|
|
if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB ||
|
2019-05-21 11:07:49 -04:00
|
|
|
le16_to_cpu(hdr.hdr.len) != 10) {
|
|
|
|
ERROR("Unrecognized data format!\n");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
job->jp.copies = le16_to_cpu(hdr.copies);
|
|
|
|
job->jp.rows = le16_to_cpu(hdr.rows);
|
|
|
|
job->jp.columns = le16_to_cpu(hdr.columns);
|
|
|
|
job->jp.media = hdr.media;
|
|
|
|
job->jp.oc_mode = hdr.oc_mode;
|
|
|
|
job->jp.method = hdr.method;
|
|
|
|
|
|
|
|
/* Allocate buffer */
|
|
|
|
job->datalen = job->jp.rows * job->jp.columns * 3;
|
2019-09-18 21:02:06 -04:00
|
|
|
|
|
|
|
/* Hack in backprinting */
|
|
|
|
if (job->jp.copies & 0x8000) {
|
|
|
|
job->jp.copies &= ~0x8000;
|
|
|
|
job->datalen += (44 * 2);
|
|
|
|
job->jp.ext_flags = EXT_FLAG_BACKPRINT;
|
|
|
|
}
|
|
|
|
|
2019-05-21 11:07:49 -04:00
|
|
|
job->databuf = malloc(job->datalen);
|
|
|
|
if (!job->databuf) {
|
|
|
|
ERROR("Memory allocation failure!\n");
|
|
|
|
return CUPS_BACKEND_RETRY_CURRENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int remain = job->datalen;
|
|
|
|
uint8_t *ptr = job->databuf;
|
|
|
|
do {
|
|
|
|
ret = read(data_fd, ptr, remain);
|
|
|
|
if (ret < 0) {
|
|
|
|
ERROR("Read failed (%d/%d/%d)\n",
|
|
|
|
ret, remain, job->datalen);
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
ptr += ret;
|
|
|
|
remain -= ret;
|
|
|
|
} while (remain);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_raw18_read_parse(int data_fd, struct sinfonia_printjob *job)
|
|
|
|
{
|
|
|
|
struct sinfonia_printcmd18_hdr hdr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Read in header */
|
|
|
|
ret = read(data_fd, &hdr, sizeof(hdr));
|
|
|
|
if (ret < 0 || ret != sizeof(hdr)) {
|
|
|
|
if (ret == 0)
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
ERROR("Read failed (%d/%d/%d)\n",
|
|
|
|
ret, 0, (int)sizeof(hdr));
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
/* Validate header */
|
|
|
|
if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB ||
|
|
|
|
le16_to_cpu(hdr.hdr.len) != 18) {
|
|
|
|
ERROR("Unrecognized data format!\n");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
job->jp.copies = le16_to_cpu(hdr.copies);
|
|
|
|
job->jp.rows = le16_to_cpu(hdr.rows);
|
|
|
|
job->jp.columns = le16_to_cpu(hdr.columns);
|
|
|
|
job->jp.media = hdr.media;
|
|
|
|
job->jp.oc_mode = hdr.oc_mode;
|
|
|
|
job->jp.method = hdr.method;
|
|
|
|
|
|
|
|
/* Allocate buffer */
|
|
|
|
job->datalen = job->jp.rows * job->jp.columns * 3;
|
|
|
|
job->databuf = malloc(job->datalen);
|
|
|
|
if (!job->databuf) {
|
|
|
|
ERROR("Memory allocation failure!\n");
|
|
|
|
return CUPS_BACKEND_RETRY_CURRENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int remain = job->datalen;
|
|
|
|
uint8_t *ptr = job->databuf;
|
|
|
|
do {
|
|
|
|
ret = read(data_fd, ptr, remain);
|
|
|
|
if (ret < 0) {
|
|
|
|
ERROR("Read failed (%d/%d/%d)\n",
|
|
|
|
ret, remain, job->datalen);
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
ptr += ret;
|
|
|
|
remain -= ret;
|
|
|
|
} while (remain);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
2019-06-03 20:38:09 -04:00
|
|
|
int sinfonia_raw28_read_parse(int data_fd, struct sinfonia_printjob *job)
|
|
|
|
{
|
|
|
|
struct sinfonia_printcmd28_hdr hdr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Read in header */
|
|
|
|
ret = read(data_fd, &hdr, sizeof(hdr));
|
|
|
|
if (ret < 0 || ret != sizeof(hdr)) {
|
|
|
|
if (ret == 0)
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
ERROR("Read failed (%d/%d/%d)\n",
|
|
|
|
ret, 0, (int)sizeof(hdr));
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
/* Validate header */
|
|
|
|
if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB ||
|
|
|
|
le16_to_cpu(hdr.hdr.len) != 28) {
|
|
|
|
ERROR("Unrecognized data format!\n");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
job->jp.copies = le16_to_cpu(hdr.copies);
|
|
|
|
job->jp.rows = le16_to_cpu(hdr.rows);
|
|
|
|
job->jp.columns = le16_to_cpu(hdr.columns);
|
|
|
|
job->jp.media = hdr.media;
|
2020-07-29 19:36:10 -04:00
|
|
|
job->jp.oc_mode = hdr.options & SINFONIA_PRINT28_OC_MASK;
|
|
|
|
job->jp.quality = hdr.options & SINFONIA_PRINT28_OPTIONS_HQ;
|
2019-06-03 20:38:09 -04:00
|
|
|
job->jp.method = hdr.method;
|
|
|
|
|
|
|
|
/* Allocate buffer */
|
|
|
|
job->datalen = job->jp.rows * job->jp.columns * 3;
|
|
|
|
job->databuf = malloc(job->datalen);
|
|
|
|
if (!job->databuf) {
|
|
|
|
ERROR("Memory allocation failure!\n");
|
|
|
|
return CUPS_BACKEND_RETRY_CURRENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int remain = job->datalen;
|
|
|
|
uint8_t *ptr = job->databuf;
|
|
|
|
do {
|
|
|
|
ret = read(data_fd, ptr, remain);
|
|
|
|
if (ret < 0) {
|
|
|
|
ERROR("Read failed (%d/%d/%d)\n",
|
|
|
|
ret, remain, job->datalen);
|
|
|
|
perror("ERROR: Read failed");
|
|
|
|
return CUPS_BACKEND_CANCEL;
|
|
|
|
}
|
|
|
|
ptr += ret;
|
|
|
|
remain -= ret;
|
|
|
|
} while (remain);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
2019-05-21 11:07:49 -04:00
|
|
|
void sinfonia_cleanup_job(const void *vjob)
|
|
|
|
{
|
|
|
|
const struct sinfonia_printjob *job = vjob;
|
|
|
|
|
|
|
|
if (job->databuf)
|
|
|
|
free(job->databuf);
|
|
|
|
|
|
|
|
free((void*)job);
|
|
|
|
}
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
int sinfonia_docmd(struct sinfonia_usbdev *usbh,
|
|
|
|
uint8_t *cmd, int cmdlen,
|
|
|
|
uint8_t *resp, int resplen,
|
|
|
|
int *num)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
struct sinfonia_cmd_hdr *cmdhdr = (struct sinfonia_cmd_hdr *) cmd;
|
|
|
|
struct sinfonia_status_hdr *resphdr = (struct sinfonia_status_hdr *)resp;
|
|
|
|
|
2020-08-11 20:27:26 -04:00
|
|
|
if ((ret = send_data(usbh->conn,
|
|
|
|
cmd, cmdlen))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:27:26 -04:00
|
|
|
ret = read_data(usbh->conn,
|
|
|
|
(uint8_t *)resp, resplen, num);
|
2019-05-24 23:49:51 -04:00
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (resphdr->result != RESULT_SUCCESS) {
|
|
|
|
INFO("Printer Status: %02x (%s)\n", resphdr->status,
|
|
|
|
sinfonia_status_str(resphdr->status));
|
|
|
|
INFO(" Result: 0x%02x Error: 0x%02x (0x%02x/0x%02x = %s)\n",
|
|
|
|
resphdr->result, resphdr->error, resphdr->printer_major,
|
|
|
|
resphdr->printer_minor, usbh->error_codes(resphdr->printer_major, resphdr->printer_minor));
|
2019-09-19 18:09:36 -04:00
|
|
|
ret = CUPS_BACKEND_FAILED;
|
2019-05-24 23:49:51 -04:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
fail:
|
|
|
|
ERROR("Failed to execute %s command\n", sinfonia_cmd_names(cmdhdr->cmd));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_flashled(struct sinfonia_usbdev *usbh)
|
|
|
|
{
|
|
|
|
struct sinfonia_cmd_hdr cmd;
|
|
|
|
struct sinfonia_status_hdr resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
cmd.cmd = cpu_to_le16(SINFONIA_CMD_FLASHLED);
|
|
|
|
cmd.len = cpu_to_le16(0);
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_canceljob(struct sinfonia_usbdev *usbh, int id)
|
|
|
|
{
|
|
|
|
struct sinfonia_cancel_cmd cmd;
|
|
|
|
struct sinfonia_status_hdr resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
cmd.id = id;
|
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_CANCELJOB);
|
|
|
|
cmd.hdr.len = cpu_to_le16(1);
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_getparam(struct sinfonia_usbdev *usbh, int target, uint32_t *param)
|
|
|
|
{
|
|
|
|
struct sinfonia_getparam_cmd cmd;
|
|
|
|
struct sinfonia_getparam_resp resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
/* Set up command */
|
|
|
|
cmd.target = target;
|
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_GETPARAM);
|
|
|
|
cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_getparam_cmd)-sizeof(cmd.hdr));
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
|
|
|
// ERROR("Unable to query param id %02x: %s\n",
|
|
|
|
// target, sinfonia_paramname(usbh, target));
|
|
|
|
return ret;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
*param = le32_to_cpu(resp.param);
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *sinfonia_paramname(struct sinfonia_usbdev *usbh,
|
|
|
|
int id)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0 ; i < usbh->params_count ; i++) {
|
|
|
|
if (usbh->params[i].id == id)
|
|
|
|
return usbh->params[i].descr;
|
|
|
|
|
|
|
|
}
|
|
|
|
return "Unknown/Not Found!";
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
2019-09-22 00:14:12 -04:00
|
|
|
int sinfonia_dumpallparams(struct sinfonia_usbdev *usbh, int known)
|
2019-09-19 15:49:00 -04:00
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
uint32_t param = 0;
|
|
|
|
|
2019-09-22 00:14:12 -04:00
|
|
|
if (known) {
|
|
|
|
for (i = 0 ; i < usbh->params_count ; i++) {
|
|
|
|
ret = sinfonia_getparam(usbh, usbh->params[i].id, ¶m);
|
|
|
|
if (ret)
|
|
|
|
continue;
|
|
|
|
DEBUG("%02x (%s): %08x\n", usbh->params[i].id,
|
|
|
|
usbh->params[i].descr, param);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0 ; i < 256 ; i++) {
|
|
|
|
ret = sinfonia_getparam(usbh, i, ¶m);
|
|
|
|
if (ret)
|
|
|
|
continue;
|
|
|
|
DEBUG("%02x (%s): %08x\n", i, sinfonia_paramname(usbh, i), param);
|
|
|
|
}
|
2019-09-19 15:49:00 -04:00
|
|
|
}
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
int sinfonia_setparam(struct sinfonia_usbdev *usbh, int target, uint32_t param)
|
|
|
|
{
|
|
|
|
struct sinfonia_setparam_cmd cmd;
|
|
|
|
struct sinfonia_status_hdr resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
/* Set up command */
|
|
|
|
cmd.target = target;
|
|
|
|
cmd.param = cpu_to_le32(param);
|
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_SETPARAM);
|
|
|
|
cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_setparam_cmd)-sizeof(cmd.hdr));
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
|
|
|
// ERROR("Unable to query param id %02x: %s\n",
|
|
|
|
// target, sinfonia_paramname(usbh, target));
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_getfwinfo(struct sinfonia_usbdev *usbh)
|
|
|
|
{
|
|
|
|
struct sinfonia_fwinfo_cmd cmd;
|
|
|
|
struct sinfonia_fwinfo_resp resp;
|
|
|
|
int num = 0;
|
|
|
|
int i;
|
2020-07-28 20:40:43 -04:00
|
|
|
int last = FWINFO_TARGET_PRINT_TABLES2;
|
2019-05-24 23:49:51 -04:00
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_FWINFO);
|
|
|
|
cmd.hdr.len = cpu_to_le16(1);
|
|
|
|
|
2019-05-26 13:05:41 -04:00
|
|
|
resp.hdr.payload_len = 0;
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
INFO("FW Information:\n");
|
|
|
|
|
2020-08-11 20:27:26 -04:00
|
|
|
if (usbh->conn->type == P_SHINKO_S6145) last = FWINFO_TARGET_PRINT_TABLES;
|
|
|
|
if (usbh->conn->type == P_SHINKO_S2245) last = FWINFO_TARGET_DSP;
|
2020-07-28 20:40:43 -04:00
|
|
|
|
|
|
|
for (i = FWINFO_TARGET_MAIN_BOOT ; i <= last ; i++) {
|
2019-05-24 23:49:51 -04:00
|
|
|
int ret;
|
|
|
|
cmd.target = i;
|
2019-09-10 14:32:07 -04:00
|
|
|
resp.major = 0;
|
2019-05-24 23:49:51 -04:00
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-08-12 21:23:30 -04:00
|
|
|
if (resp.major == 0)
|
|
|
|
continue;
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_fwinfo_resp) - sizeof(struct sinfonia_status_hdr)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
INFO(" %s\t ver %02x.%02x\n", sinfonia_fwinfo_targets(i),
|
|
|
|
resp.major, resp.minor);
|
|
|
|
#if 0
|
|
|
|
INFO(" name: '%s'\n", resp.name);
|
|
|
|
INFO(" type: '%s'\n", resp.type);
|
|
|
|
INFO(" date: '%s'\n", resp.date);
|
|
|
|
INFO(" version: %02x.%02x (CRC %04x)\n", resp.major, resp.minor,
|
|
|
|
le16_to_cpu(resp.checksum));
|
|
|
|
#endif
|
|
|
|
}
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_geterrorlog(struct sinfonia_usbdev *usbh)
|
|
|
|
{
|
|
|
|
struct sinfonia_cmd_hdr cmd;
|
|
|
|
struct sinfonia_errorlog_resp resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
cmd.cmd = cpu_to_le16(SINFONIA_CMD_ERRORLOG);
|
|
|
|
cmd.len = cpu_to_le16(0);
|
|
|
|
|
2019-05-26 13:05:41 -04:00
|
|
|
resp.hdr.payload_len = 0;
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_errorlog_resp) - sizeof(struct sinfonia_status_hdr)))
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
INFO("Stored Error Events: %u entries:\n", resp.count);
|
|
|
|
for (i = 0 ; i < resp.count ; i++) {
|
|
|
|
INFO(" %02d: @ %08u prints : 0x%02x/0x%02x (%s)\n", i,
|
|
|
|
le32_to_cpu(resp.items[i].print_counter),
|
|
|
|
resp.items[i].major, resp.items[i].minor,
|
|
|
|
usbh->error_codes(resp.items[i].major, resp.items[i].minor));
|
|
|
|
}
|
2020-07-28 20:40:43 -04:00
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_resetcurve(struct sinfonia_usbdev *usbh, int target, int id)
|
|
|
|
{
|
|
|
|
struct sinfonia_reset_cmd cmd;
|
|
|
|
struct sinfonia_status_hdr resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
cmd.target = target;
|
|
|
|
cmd.curveid = id;
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_RESET);
|
|
|
|
cmd.hdr.len = cpu_to_le16(2);
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-05-24 23:49:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int sinfonia_gettonecurve(struct sinfonia_usbdev *usbh, int type, char *fname)
|
|
|
|
{
|
|
|
|
struct sinfonia_readtone_cmd cmd;
|
|
|
|
struct sinfonia_readtone_resp resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
uint8_t *data;
|
|
|
|
uint16_t curves[TONE_CURVE_SIZE] = { 0 };
|
|
|
|
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
cmd.target = type;
|
|
|
|
cmd.curveid = TONE_CURVE_ID;
|
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_READTONE);
|
2019-09-22 23:26:55 -04:00
|
|
|
cmd.hdr.len = cpu_to_le16(2);
|
2019-05-24 23:49:51 -04:00
|
|
|
|
2019-05-26 13:05:41 -04:00
|
|
|
resp.hdr.payload_len = 0;
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
INFO("Dump %s Tone Curve to '%s'\n", sinfonia_tonecurve_statuses(type), fname);
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-05-26 13:05:41 -04:00
|
|
|
if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct sinfonia_readtone_resp) - sizeof(struct sinfonia_status_hdr)))
|
|
|
|
return -2;
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
resp.total_size = le16_to_cpu(resp.total_size);
|
|
|
|
|
|
|
|
data = malloc(resp.total_size * 2);
|
|
|
|
if (!data) {
|
|
|
|
ERROR("Memory Allocation Failure!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (i < resp.total_size) {
|
2020-08-11 20:27:26 -04:00
|
|
|
ret = read_data(usbh->conn,
|
2019-05-24 23:49:51 -04:00
|
|
|
data + i,
|
|
|
|
resp.total_size * 2 - i,
|
|
|
|
&num);
|
|
|
|
if (ret < 0)
|
|
|
|
goto done;
|
|
|
|
i += num;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = j = 0;
|
|
|
|
while (i < resp.total_size) {
|
|
|
|
memcpy(curves + j, data + i+2, data[i+1]);
|
|
|
|
j += data[i+1] / 2;
|
|
|
|
i += data[i+1] + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Open file and write it out */
|
|
|
|
{
|
|
|
|
int tc_fd = open(fname, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
|
|
|
|
if (tc_fd < 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0 ; i < TONE_CURVE_SIZE; i++) {
|
|
|
|
/* Byteswap appropriately */
|
|
|
|
curves[i] = cpu_to_be16(le16_to_cpu(curves[i]));
|
|
|
|
}
|
2019-07-15 23:35:54 -04:00
|
|
|
ret = write(tc_fd, curves, TONE_CURVE_SIZE * sizeof(uint16_t));
|
2019-05-24 23:49:51 -04:00
|
|
|
close(tc_fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
free(data);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-18 19:54:56 -04:00
|
|
|
int sinfonia_button_set(struct sinfonia_usbdev *dev, int enable)
|
|
|
|
{
|
|
|
|
struct sinfonia_button_cmd cmd;
|
|
|
|
struct sinfonia_status_hdr resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_BUTTON);
|
|
|
|
cmd.hdr.len = cpu_to_le16(1);
|
|
|
|
|
|
|
|
cmd.enabled = enable;
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(dev,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&cmd, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-09-18 19:54:56 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-21 23:03:05 -04:00
|
|
|
return CUPS_BACKEND_OK;
|
2019-09-18 19:54:56 -04:00
|
|
|
}
|
|
|
|
|
2019-05-24 23:49:51 -04:00
|
|
|
int sinfonia_settonecurve(struct sinfonia_usbdev *usbh, int target, char *fname)
|
|
|
|
{
|
|
|
|
struct sinfonia_update_cmd cmd;
|
|
|
|
struct sinfonia_status_hdr resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
2019-09-19 14:56:37 -04:00
|
|
|
INFO("Set %s from '%s'\n", sinfonia_update_targets(target), fname);
|
2019-05-24 23:49:51 -04:00
|
|
|
|
|
|
|
uint16_t *data = malloc(TONE_CURVE_SIZE * sizeof(uint16_t));
|
|
|
|
if (!data) {
|
|
|
|
ERROR("Memory Allocation Failure!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read in file */
|
|
|
|
if ((ret = dyesub_read_file(fname, data, TONE_CURVE_SIZE * sizeof(uint16_t), NULL))) {
|
|
|
|
ERROR("Failed to read Tone Curve file\n");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Byteswap data to local CPU.. */
|
|
|
|
for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) {
|
|
|
|
data[ret] = be16_to_cpu(data[ret]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set up command */
|
|
|
|
cmd.target = target;
|
|
|
|
cmd.curve_id = TONE_CURVE_ID;
|
|
|
|
cmd.reserved[0] = cmd.reserved[1] = cmd.reserved[2] = 0;
|
|
|
|
cmd.reset = 0;
|
|
|
|
cmd.size = cpu_to_le32(TONE_CURVE_SIZE * sizeof(uint16_t));
|
|
|
|
|
|
|
|
cmd.hdr.cmd = cpu_to_le16(SINFONIA_CMD_UPDATE);
|
|
|
|
cmd.hdr.len = cpu_to_le16(sizeof(struct sinfonia_update_cmd)-sizeof(cmd.hdr));
|
|
|
|
|
|
|
|
/* Byteswap data to format printer is expecting.. */
|
|
|
|
for (ret = 0; ret < TONE_CURVE_SIZE ; ret++) {
|
|
|
|
data[ret] = cpu_to_le16(data[ret]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(usbh,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-05-24 23:49:51 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sent transfer */
|
2020-08-11 20:27:26 -04:00
|
|
|
if ((ret = send_data(usbh->conn,
|
2019-05-24 23:49:51 -04:00
|
|
|
(uint8_t *) data, TONE_CURVE_SIZE * sizeof(uint16_t)))) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
free(data);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-08 21:33:30 -04:00
|
|
|
int sinfonia_query_media(struct sinfonia_usbdev *dev,
|
|
|
|
void *resp)
|
|
|
|
{
|
|
|
|
struct sinfonia_cmd_hdr cmd;
|
|
|
|
int i, num;
|
|
|
|
|
|
|
|
struct sinfonia_6x45_mediainfo_resp *media = resp;
|
|
|
|
|
|
|
|
cmd.cmd = cpu_to_le16(SINFONIA_CMD_MEDIAINFO);
|
|
|
|
cmd.len = cpu_to_le16(0);
|
|
|
|
|
|
|
|
if (sinfonia_docmd(dev,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)media, sizeof(*media),
|
|
|
|
&num)) {
|
|
|
|
return CUPS_BACKEND_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Byteswap media descriptor.. */
|
|
|
|
for (i = 0 ; i < media->count ; i++) {
|
|
|
|
media->items[i].columns = le16_to_cpu(media->items[i].columns);
|
|
|
|
media->items[i].rows = le16_to_cpu(media->items[i].rows);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
2020-03-24 18:22:39 -04:00
|
|
|
static const char *dummy_error_codes(uint8_t major, uint8_t minor)
|
2019-09-10 14:32:07 -04:00
|
|
|
{
|
|
|
|
UNUSED(major);
|
|
|
|
UNUSED(minor);
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
2020-08-11 20:27:26 -04:00
|
|
|
int sinfonia_query_serno(struct dyesub_connection *conn, char *buf, int buf_len)
|
2019-09-08 21:33:30 -04:00
|
|
|
{
|
|
|
|
struct sinfonia_cmd_hdr cmd;
|
|
|
|
struct sinfonia_getserial_resp resp;
|
|
|
|
int ret, num = 0;
|
|
|
|
|
|
|
|
struct sinfonia_usbdev sdev = {
|
2019-09-10 14:32:07 -04:00
|
|
|
.error_codes = dummy_error_codes,
|
2020-08-11 20:27:26 -04:00
|
|
|
.conn = conn,
|
2019-09-08 21:33:30 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
cmd.cmd = cpu_to_le16(SINFONIA_CMD_GETSERIAL);
|
|
|
|
cmd.len = cpu_to_le16(0);
|
|
|
|
|
|
|
|
if ((ret = sinfonia_docmd(&sdev,
|
|
|
|
(uint8_t*)&cmd, sizeof(cmd),
|
|
|
|
(uint8_t*)&resp, sizeof(resp),
|
2019-09-21 23:03:05 -04:00
|
|
|
&num))) {
|
2019-09-08 21:33:30 -04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy and Null-terminate */
|
|
|
|
num = (buf_len > (int)sizeof(resp.data)) ? (int)sizeof(resp.data) : (buf_len - 1);
|
|
|
|
memcpy(buf, resp.data, num);
|
|
|
|
buf[num] = 0;
|
|
|
|
|
|
|
|
return CUPS_BACKEND_OK;
|
|
|
|
}
|
|
|
|
|
2019-05-12 23:55:09 -04:00
|
|
|
const char *sinfonia_update_targets (uint8_t v) {
|
2019-05-06 16:28:07 -04:00
|
|
|
switch (v) {
|
2019-09-19 14:56:37 -04:00
|
|
|
case UPDATE_TARGET_TONE_USER:
|
|
|
|
return "User Tone Curve";
|
|
|
|
case UPDATE_TARGET_TONE_CURRENT:
|
|
|
|
return "Current Tone Curve";
|
|
|
|
case UPDATE_TARGET_LAM_USER:
|
|
|
|
return "User Lamination Data";
|
|
|
|
case UPDATE_TARGET_LAM_CUR:
|
|
|
|
return "Current Lamination Data";
|
|
|
|
case UPDATE_TARGET_LAM_DEF:
|
|
|
|
return "Default Lamination Data";
|
2019-05-06 16:28:07 -04:00
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-12 23:55:09 -04:00
|
|
|
const char *sinfonia_tonecurve_statuses (uint8_t v)
|
2019-05-06 16:28:07 -04:00
|
|
|
{
|
|
|
|
switch(v) {
|
|
|
|
case 0:
|
|
|
|
return "Initial";
|
|
|
|
case 1:
|
|
|
|
return "UserSet";
|
|
|
|
case 2:
|
|
|
|
return "Current";
|
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-12 23:55:09 -04:00
|
|
|
const char *sinfonia_bank_statuses(uint8_t v)
|
2019-05-06 16:28:07 -04:00
|
|
|
{
|
|
|
|
switch (v) {
|
|
|
|
case BANK_STATUS_FREE:
|
|
|
|
return "Free";
|
|
|
|
case BANK_STATUS_XFER:
|
|
|
|
return "Xfer";
|
|
|
|
case BANK_STATUS_FULL:
|
|
|
|
return "Full";
|
|
|
|
case BANK_STATUS_PRINTING:
|
|
|
|
return "Printing";
|
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
2019-05-09 12:39:18 -04:00
|
|
|
|
2019-05-12 23:55:09 -04:00
|
|
|
const char *sinfonia_error_str(uint8_t v) {
|
2019-05-09 12:39:18 -04:00
|
|
|
switch (v) {
|
|
|
|
case ERROR_NONE:
|
|
|
|
return "None";
|
|
|
|
case ERROR_INVALID_PARAM:
|
|
|
|
return "Invalid Command Parameter";
|
|
|
|
case ERROR_MAIN_APP_INACTIVE:
|
|
|
|
return "Main App Inactive";
|
|
|
|
case ERROR_COMMS_TIMEOUT:
|
|
|
|
return "Main Communication Timeout";
|
|
|
|
case ERROR_MAINT_NEEDED:
|
|
|
|
return "Maintenance Needed";
|
2020-01-25 07:15:02 -05:00
|
|
|
case ERROR_INAPP_COMMAND:
|
2019-05-09 12:39:18 -04:00
|
|
|
return "Inappropriate Command";
|
|
|
|
case ERROR_PRINTER:
|
|
|
|
return "Printer Error";
|
|
|
|
case ERROR_BUFFER_FULL:
|
|
|
|
return "Buffer Full";
|
|
|
|
default:
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 12:55:57 -04:00
|
|
|
|
2019-05-12 23:55:09 -04:00
|
|
|
const char *sinfonia_media_types(uint8_t v) {
|
2019-05-12 12:55:57 -04:00
|
|