all: add new marker query support to backends and rejigger as needed.

This commit is contained in:
Solomon Peachy 2018-04-27 15:40:09 -04:00
parent 06dbf0fa91
commit 5669fb3552
13 changed files with 912 additions and 723 deletions

8
README
View File

@ -299,6 +299,8 @@
Notes:
This backend does not support reporting marker levels.
[1] Format of curvedata file:
256 entries each of Yellow, Magenta, Cyan mappings:
@ -598,6 +600,8 @@
This backend does not support additional commands.
This backend does not support reporting marker levels.
***************************************************************************
BACKEND=mitsu70x
@ -725,6 +729,8 @@
-s Query printer status
This backend does not support reporting marker levels.
***************************************************************************
BACKEND=dnpds40
@ -807,4 +813,6 @@ Notes:
-E Eject card in printer
-R Reset printer
This backend does not support reporting marker levels.
***************************************************************************

View File

@ -78,8 +78,6 @@
#define READBACK_LEN 12
struct printer_data; /* Forward declaration */
struct printer_data {
int type; /* P_??? */
char *model; /* eg "SELPHY ES1" */
@ -122,19 +120,16 @@ static char *generic_pgcode_names(uint8_t *rdbuf, struct printer_data *printer)
static uint8_t es1_error_detect(uint8_t *rdbuf)
{
if (rdbuf[1] == 0x01) {
if (rdbuf[9] == 0x00) {
if (rdbuf[9] == 0x00)
ERROR("Cover open!\n");
} else {
else
ERROR("Unknown error %02x\n", rdbuf[9]);
}
return 1;
} else if (rdbuf[4] == 0x01 && rdbuf[5] == 0xff &&
rdbuf[6] == 0xff && rdbuf[7] == 0xff) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
return 1;
} else if (rdbuf[0] == 0x0f) {
ATTR("marker-levels=%d\n", 0);
ERROR("Out of media!\n");
return 1;
}
@ -154,13 +149,11 @@ static uint8_t es2_error_detect(uint8_t *rdbuf)
rdbuf[4] == 0x05 &&
rdbuf[5] == 0x05 &&
rdbuf[6] == 0x02) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
return 1;
}
if (rdbuf[0] == 0x14) {
ATTR("marker-levels=%d\n", 0);
ERROR("Out of media!\n");
return 1;
}
@ -171,19 +164,16 @@ static uint8_t es2_error_detect(uint8_t *rdbuf)
static uint8_t es3_error_detect(uint8_t *rdbuf)
{
if (rdbuf[8] == 0x01) {
if (rdbuf[10] == 0x0f) {
if (rdbuf[10] == 0x0f)
ERROR("Communications Error\n");
} else if (rdbuf[10] == 0x01) {
ATTR("marker-levels=%d\n", 0);
else if (rdbuf[10] == 0x01)
ERROR("No media loaded!\n");
} else {
else
ERROR("Unknown error - %02x + %02x\n",
rdbuf[8], rdbuf[10]);
}
return 1;
} else if (rdbuf[8] == 0x03 &&
rdbuf[10] == 0x02) {
ATTR("marker-levels=%d\n", 0);
ERROR("No media loaded!\n");
return 1;
} else if (rdbuf[8] == 0x08 &&
@ -213,13 +203,11 @@ static uint8_t es40_error_detect(uint8_t *rdbuf)
if (rdbuf[3] == 0x01)
ERROR("Generic communication error\n");
else if (rdbuf[3] == 0x32) {
ATTR("marker-levels=%d\n", 0);
else if (rdbuf[3] == 0x32)
ERROR("Cover open or media empty!\n");
} else
else
ERROR("Unknown error - %02x\n", rdbuf[3]);
return 1;
}
@ -233,18 +221,15 @@ static uint8_t cp790_error_detect(uint8_t *rdbuf)
ERROR("No paper tray loaded!\n");
return 1;
} else if (rdbuf[3]) {
if ((rdbuf[3] & 0xf) == 0x02) { // 0x12 0x22
ATTR("marker-levels=%d\n", 0);
if ((rdbuf[3] & 0xf) == 0x02) // 0x12 0x22
ERROR("No paper tray loaded!\n");
} else if ((rdbuf[3] & 0xf) == 0x03) { // 0x13 0x23
ATTR("marker-levels=%d\n", 0);
else if ((rdbuf[3] & 0xf) == 0x03) // 0x13 0x23
ERROR("Empty paper tray or feed error!\n");
} else if (rdbuf[3] == 0x11)
else if (rdbuf[3] == 0x11)
ERROR("Paper feed error!\n");
else if (rdbuf[3] == 0x21) {
ATTR("marker-levels=%d\n", 0);
else if (rdbuf[3] == 0x21)
ERROR("Ribbon depleted!\n");
} else
else
ERROR("Unknown error - %02x\n", rdbuf[3]);
return 1;
}
@ -265,16 +250,13 @@ static uint8_t cp10_error_detect(uint8_t *rdbuf)
if (!rdbuf[2])
return 0;
if (rdbuf[2] == 0x80) {
ATTR("marker-levels=%d\n", 0);
if (rdbuf[2] == 0x80)
ERROR("No ribbon loaded\n");
} else if (rdbuf[2] == 0x08) {
ATTR("marker-levels=%d\n", 0);
else if (rdbuf[2] == 0x08)
ERROR("Ribbon depleted!\n");
} else if (rdbuf[2] == 0x01) {
ATTR("marker-levels=%d\n", 0);
else if (rdbuf[2] == 0x01)
ERROR("No paper loaded!\n");
} else
else
ERROR("Unknown error - %02x\n", rdbuf[2]);
return 1;
}
@ -284,15 +266,13 @@ static uint8_t cpxxx_error_detect(uint8_t *rdbuf)
if (!rdbuf[2])
return 0;
if (rdbuf[2] == 0x01) {
ATTR("marker-levels=%d\n", 0);
if (rdbuf[2] == 0x01)
ERROR("Paper feed problem!\n");
} else if (rdbuf[2] == 0x04)
else if (rdbuf[2] == 0x04)
ERROR("Ribbon problem!\n");
else if (rdbuf[2] == 0x08) {
ATTR("marker-levels=%d\n", 0);
else if (rdbuf[2] == 0x08)
ERROR("Ribbon depleted!\n");
} else
else
ERROR("Unknown error - %02x\n", rdbuf[2]);
return 1;
}
@ -563,6 +543,7 @@ struct canonselphy_ctx {
int type;
struct printer_data *printer;
struct marker marker;
uint8_t bw_mode;
@ -648,7 +629,8 @@ static int canonselphy_attach(void *vctx, struct libusb_device_handle *dev,
struct canonselphy_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
int i;
int i, num;
uint8_t rdbuf[READBACK_LEN];
UNUSED(jobid);
@ -675,7 +657,27 @@ static int canonselphy_attach(void *vctx, struct libusb_device_handle *dev,
return CUPS_BACKEND_FAILED;
}
/* TODO: Query & Update Marker */
/* Read printer status. Twice. */
i = read_data(ctx->dev, ctx->endp_up,
rdbuf, READBACK_LEN, &num);
if (i < 0)
return CUPS_BACKEND_FAILED;
i = read_data(ctx->dev, ctx->endp_up,
rdbuf, READBACK_LEN, &num);
if (i < 0)
return CUPS_BACKEND_FAILED;
/* Fill out marker structure */
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = ctx->printer->pgcode_names? ctx->printer->pgcode_names(rdbuf, ctx->printer) : "Unknown";
ctx->marker.levelmax = -1; /* Unknown */
if (ctx->printer->error_detect(rdbuf))
ctx->marker.levelnow = 0; /* Out of media */
else
ctx->marker.levelnow = -3; /* Unknown but OK */
return CUPS_BACKEND_OK;
}
@ -866,14 +868,6 @@ static int canonselphy_main_loop(void *vctx, int copies) {
if (ret < 0)
return CUPS_BACKEND_FAILED;
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", ctx->printer->pgcode_names? ctx->printer->pgcode_names(rdbuf, ctx->printer) : "Unknown");
ATTR("marker-types=ribbonWax\n");
ATTR("marker-levels=%d\n", -3); /* ie Unknown but OK */
top:
if (state != last_state) {
@ -894,6 +888,7 @@ top:
/* Error detection */
if (ctx->printer->error_detect(rdbuf)) {
dump_markers(&ctx->marker, 1, 0);
if (ctx->printer->clear_error_len)
/* Try to clear error state */
if ((ret = send_data(ctx->dev, ctx->endp_down, ctx->printer->clear_error, ctx->printer->clear_error_len)))
@ -1104,6 +1099,35 @@ static void canonselphy_cmdline(void)
DEBUG("\t\t[ -s ] # Query printer status\n");
}
static int canonselphy_query_markers(void *vctx, struct marker **markers, int *count)
{
struct canonselphy_ctx *ctx = vctx;
uint8_t rdbuf[READBACK_LEN];
int ret, num;
/* Read in the printer status, twice. */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) rdbuf, READBACK_LEN, &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) rdbuf, READBACK_LEN, &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
if (ctx->printer->error_detect(rdbuf))
ctx->marker.levelnow = 0;
else
ctx->marker.levelnow = -3;
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
static const char *canonselphy_prefixes[] = {
"canonselphy",
"selphycp10", "selphycp100", "selphycp200", "selphycp220",
@ -1119,7 +1143,7 @@ static const char *canonselphy_prefixes[] = {
struct dyesub_backend canonselphy_backend = {
.name = "Canon SELPHY CP/ES (legacy)",
.version = "0.99",
.version = "0.100",
.uri_prefixes = canonselphy_prefixes,
.cmdline_usage = canonselphy_cmdline,
.cmdline_arg = canonselphy_cmdline_arg,
@ -1128,6 +1152,7 @@ struct dyesub_backend canonselphy_backend = {
.teardown = canonselphy_teardown,
.read_parse = canonselphy_read_parse,
.main_loop = canonselphy_main_loop,
.query_markers = canonselphy_query_markers,
.devices = {
{ USB_VID_CANON, USB_PID_CANON_CP10, P_CP10, NULL, "selphycp10"},
{ USB_VID_CANON, USB_PID_CANON_CP100, P_CP_XXX, NULL, "selphycp100"},

View File

@ -69,6 +69,8 @@ struct selphyneo_ctx {
uint8_t *databuf;
uint32_t datalen;
struct marker marker;
};
static char *selphyneo_statuses(uint8_t sts)
@ -195,6 +197,8 @@ static int selphyneo_attach(void *vctx, struct libusb_device_handle *dev,
struct selphyneo_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
struct selphyneo_readback rdback;
int ret, num;
UNUSED(jobid);
@ -205,7 +209,24 @@ static int selphyneo_attach(void *vctx, struct libusb_device_handle *dev,
device = libusb_get_device(dev);
libusb_get_device_descriptor(device, &desc);
// TODO: Query & Update Marker
/* Read in the printer status to clear last state */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) &rdback, sizeof(rdback), &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
/* And again, for the markers */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) &rdback, sizeof(rdback), &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = selphynew_pgcodes(rdback.data[6]);
ctx->marker.levelmax = -1;
ctx->marker.levelnow = -3;
return CUPS_BACKEND_OK;
}
@ -292,20 +313,6 @@ static int selphyneo_main_loop(void *vctx, int copies) {
if (ret < 0)
return CUPS_BACKEND_FAILED;
/* And again, for the markers */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) &rdback, sizeof(rdback), &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", selphynew_pgcodes(rdback.data[6]));
ATTR("marker-types=ribbonWax\n");
top:
INFO("Waiting for printer idle\n");
@ -326,18 +333,20 @@ top:
break;
case 0x0A:
ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
ATTR("marker-levels=%d\n", 0);
ctx->marker.levelnow = 0;
dump_markers(&ctx->marker, 1, 0);
return CUPS_BACKEND_CANCEL;
default:
ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
ATTR("marker-levels=%d\n", 0);
ctx->marker.levelnow = 0;
dump_markers(&ctx->marker, 1, 0);
return CUPS_BACKEND_STOP;
}
sleep(1);
} while(1);
ATTR("marker-levels=%d\n", -3); /* ie Unknown but OK */
dump_markers(&ctx->marker, 1, 0);
INFO("Sending spool data\n");
/* Send the data over in 256K chunks */
@ -380,11 +389,13 @@ top:
break;
case 0x0A:
ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
ATTR("marker-levels=%d\n", 0);
ctx->marker.levelnow = 0;
dump_markers(&ctx->marker, 1, 0);
return CUPS_BACKEND_CANCEL;
default:
ERROR("Printer error: %s (%02x)\n", selphyneo_errors(rdback.data[2]), rdback.data[2]);
ATTR("marker-levels=%d\n", 0);
ctx->marker.levelnow = 0;
dump_markers(&ctx->marker, 1, 0);
return CUPS_BACKEND_STOP;
}
@ -440,6 +451,37 @@ static void selphyneo_cmdline(void)
DEBUG("\t\t[ -s ] # Query printer status\n");
}
static int selphyneo_query_markers(void *vctx, struct marker **markers, int *count)
{
struct selphyneo_ctx *ctx = vctx;
struct selphyneo_readback rdback;
int ret, num;
/* Read in the printer status to clear last state */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) &rdback, sizeof(rdback), &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
/* And again, for the markers */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) &rdback, sizeof(rdback), &num);
if (ret < 0)
return CUPS_BACKEND_FAILED;
if (rdback.data[2])
ctx->marker.levelnow = 0;
else
ctx->marker.levelnow = -3;
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
static const char *canonselphyneo_prefixes[] = {
"canonselphyneo",
"selphycp820", "selphycp910", "selphycp1000", "selphycp1200", "selphycp1300",
@ -448,7 +490,7 @@ static const char *canonselphyneo_prefixes[] = {
struct dyesub_backend canonselphyneo_backend = {
.name = "Canon SELPHY CP (new)",
.version = "0.15",
.version = "0.16",
.uri_prefixes = canonselphyneo_prefixes,
.cmdline_usage = selphyneo_cmdline,
.cmdline_arg = selphyneo_cmdline_arg,
@ -457,6 +499,7 @@ struct dyesub_backend canonselphyneo_backend = {
.teardown = selphyneo_teardown,
.read_parse = selphyneo_read_parse,
.main_loop = selphyneo_main_loop,
.query_markers = selphyneo_query_markers,
.devices = {
{ USB_VID_CANON, USB_PID_CANON_CP820, P_CP910, NULL, "selphycp820"},
{ USB_VID_CANON, USB_PID_CANON_CP910, P_CP910, NULL, "selphycp910"},

View File

@ -91,6 +91,8 @@ struct dnpds40_ctx {
int correct_count;
int needs_mlot;
struct marker marker;
uint32_t native_width;
int supports_6x9;
int supports_2x6;
@ -548,6 +550,35 @@ static void *dnpds40_init(void)
((ctx->ver_major > (__major)) || \
(ctx->ver_major == (__major) && ctx->ver_minor >= (__minor)))
static int dnpds40_query_mqty(struct dnpds40_ctx *ctx)
{
struct dnpds40_cmd cmd;
uint8_t *resp;
int len = 0, count;
/* Get Media remaining */
dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0);
resp = dnpds40_resp_cmd(ctx, &cmd, &len);
if (!resp)
return -1;
dnpds40_cleanup_string((char*)resp, len);
count = atoi((char*)resp+4);
free(resp);
if (count) {
/* Old-sk00l models report one less than they should */
if (!ctx->correct_count)
count++;
count -= ctx->mediaoffset;
}
return count;
}
static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
@ -588,6 +619,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ptr = strtok(NULL, ".");
ctx->ver_minor = atoi(ptr);
free(resp);
} else {
return CUPS_BACKEND_FAILED;
}
/* Get Serial Number */
@ -598,6 +631,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
dnpds40_cleanup_string((char*)resp, len);
ctx->serno = (char*) resp;
/* Do NOT free resp! */
} else {
return CUPS_BACKEND_FAILED;
}
/* Query Media Info */
@ -619,6 +654,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media--;
free(resp);
} else {
return CUPS_BACKEND_FAILED;
}
}
@ -667,6 +704,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->duplex_media -= (ctx->duplex_media & 3);
free(resp);
} else {
return CUPS_BACKEND_FAILED;
}
}
@ -809,6 +848,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
if (resp) {
ctx->mediaoffset = atoi((char*)resp+4);
free(resp);
} else {
return CUPS_BACKEND_FAILED;
}
} else if (!ctx->correct_count) {
ctx->mediaoffset = 50;
@ -827,6 +868,8 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media_count_new = atoi((char*)resp+4);
free(resp);
ctx->media_count_new -= ctx->mediaoffset;
} else {
return CUPS_BACKEND_FAILED;
}
} else {
/* Look it up for legacy models & FW */
@ -849,7 +892,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media_count_new = 180;
break;
default:
ctx->media_count_new = 999; // non-zero
ctx->media_count_new = 0;
break;
}
break;
@ -865,7 +908,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media_count_new = 350;
break;
default:
ctx->media_count_new = 999; // non-zero
ctx->media_count_new = 0;
break;
}
break;
@ -884,7 +927,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media_count_new = 280;
break;
default:
ctx->media_count_new = 999; // non-zero
ctx->media_count_new = 0;
break;
}
break;
@ -900,7 +943,7 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media_count_new = 280;
break;
default:
ctx->media_count_new = 999; // non-zero
ctx->media_count_new = 0;
break;
}
break;
@ -914,18 +957,25 @@ static int dnpds40_attach(void *vctx, struct libusb_device_handle *dev,
ctx->media_count_new = 110;
break;
default:
ctx->media_count_new = 999; // non-zero
ctx->media_count_new = 0;
break;
}
break;
default:
ctx->media_count_new = 999; // non-zero
ctx->media_count_new = 0;
break;
}
}
// TODO: fail out on other errors
// TODO: Update Marker
/* Fill out marker structure */
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = dnpds40_media_types(ctx->media);
ctx->marker.levelmax = ctx->media_count_new;
ctx->marker.levelnow = dnpds40_query_mqty(ctx);
if (ctx->marker.levelnow < 0)
return CUPS_BACKEND_FAILED;
return CUPS_BACKEND_OK;
}
@ -1484,14 +1534,6 @@ static int dnpds40_main_loop(void *vctx, int copies) {
if (!!ctx->matte != ctx->last_matte)
buf_needed = 2;
if (ctx->media_count_new) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", dnpds40_media_types(ctx->media));
ATTR("marker-types=ribbonWax\n");
}
/* RX1HS requires HS media, but the only way to tell is that the
HS media reports a lot code, while the non-HS media does not. */
if (ctx->needs_mlot) {
@ -1579,29 +1621,12 @@ top:
{
/* Figure out remaining native prints */
dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0);
resp = dnpds40_resp_cmd(ctx, &cmd, &len);
if (!resp)
ctx->marker.levelnow = dnpds40_query_mqty(ctx);
if (ctx->marker.levelnow < 0)
return CUPS_BACKEND_FAILED;
dump_markers(&ctx->marker, 1, 0);
dnpds40_cleanup_string((char*)resp, len);
count = atoi((char*)resp+4);
free(resp);
if (count) {
/* Old-sk00l models report one less than they should */
if (!ctx->correct_count)
count++;
count -= ctx->mediaoffset;
}
if (ctx->media_count_new) {
ATTR("marker-levels=%d\n", count * 100 / ctx->media_count_new);
ATTR("marker-message=\"%d native prints remaining on '%s' ribbon\"\n", count, dnpds40_media_types(ctx->media));
}
count = ctx->marker.levelnow; // For logic below.
/* See if we can rewind to save media */
if (ctx->can_rewind && ctx->supports_rewind) {
@ -1648,7 +1673,6 @@ top:
return CUPS_BACKEND_STOP;
}
#endif
if (count < copies) {
WARNING("Printer does not have sufficient remaining media (%d) to complete job (%d)\n", copies, count);
}
@ -1771,11 +1795,8 @@ top:
count -= ctx->mediaoffset;
}
if (ctx->media_count_new) {
ATTR("marker-levels=%d\n", count * 100 / ctx->media_count_new);
ATTR("marker-message=\"%d native prints remaining on '%s' ribbon\"\n", count, dnpds40_media_types(ctx->media));
}
ctx->marker.levelnow = count;
dump_markers(&ctx->marker, 1, 0);
}
/* Clean up */
@ -2306,24 +2327,10 @@ static int dnpds40_get_status(struct dnpds40_ctx *ctx)
INFO("Native Prints Available on New Media: %u\n", ctx->media_count_new);
/* Get Media remaining */
dnpds40_build_cmd(&cmd, "INFO", "MQTY", 0);
resp = dnpds40_resp_cmd(ctx, &cmd, &len);
if (!resp)
count = dnpds40_query_mqty(ctx);
if (count < 0)
return CUPS_BACKEND_FAILED;
dnpds40_cleanup_string((char*)resp, len);
count = atoi((char*)resp+4);
free(resp);
if (count) {
/* Old-sk00l models report one less than they should */
if (!ctx->correct_count)
count++;
count -= ctx->mediaoffset;
}
INFO("Native Prints Remaining on Media: %d\n", count);
if (ctx->supports_rewind) {
@ -2699,6 +2706,20 @@ static int dnpds40_cmdline_arg(void *vctx, int argc, char **argv)
return 0;
}
static int dnpds40_query_markers(void *vctx, struct marker **markers, int *count)
{
struct dnpds40_ctx *ctx = vctx;
*markers = &ctx->marker;
*count = 1;
ctx->marker.levelnow = dnpds40_query_mqty(ctx);
if (ctx->marker.levelnow < 0)
return CUPS_BACKEND_FAILED;
return CUPS_BACKEND_OK;
}
static const char *dnpds40_prefixes[] = {
"dnp_citizen",
"dnpds40", "dnpds80", "dnpds80dx", "dnpds620", "dnpds820", "dnprx1",
@ -2724,7 +2745,7 @@ static const char *dnpds40_prefixes[] = {
/* Exported */
struct dyesub_backend dnpds40_backend = {
.name = "DNP DS-series / Citizen C-series",
.version = "0.100",
.version = "0.101",
.uri_prefixes = dnpds40_prefixes,
.cmdline_usage = dnpds40_cmdline,
.cmdline_arg = dnpds40_cmdline_arg,
@ -2734,6 +2755,7 @@ struct dyesub_backend dnpds40_backend = {
.read_parse = dnpds40_read_parse,
.main_loop = dnpds40_main_loop,
.query_serno = dnpds40_query_serno,
.query_markers = dnpds40_query_markers,
.devices = {
{ USB_VID_CITIZEN, USB_PID_DNP_DS40, P_DNP_DS40, NULL, "dnpds40"}, // Also Citizen CX
{ USB_VID_CITIZEN, USB_PID_DNP_DS80, P_DNP_DS80, NULL, "dnpds80"}, // Also Citizen CX-W and Mitsubishi CP-3800DW

View File

@ -178,10 +178,10 @@ struct kodak605_ctx {
struct kodak605_media_list *media;
struct marker marker;
uint8_t *databuf;
int datalen;
uint8_t last_donor;
};
static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_list *media)
@ -218,6 +218,40 @@ static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_li
return 0;
}
static int kodak605_get_status(struct kodak605_ctx *ctx, struct kodak605_status *sts)
{
uint8_t cmdbuf[4];
int ret, num = 0;
/* Send Status Query */
cmdbuf[0] = 0x01;
cmdbuf[1] = 0x00;
cmdbuf[2] = 0x00;
cmdbuf[3] = 0x00;
if ((ret = send_data(ctx->dev, ctx->endp_down,
cmdbuf, sizeof(cmdbuf))))
return ret;
/* Read in the printer status */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) sts, sizeof(*sts), &num);
if (ret < 0)
return ret;
if (num < (int)sizeof(*sts)) {
ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*sts));
return CUPS_BACKEND_FAILED;
}
if (sts->hdr.result != RESULT_SUCCESS) {
ERROR("Unexpected response from status query (%x)!\n", sts->hdr.result);
return CUPS_BACKEND_FAILED;
}
return 0;
}
static void *kodak605_init(void)
{
struct kodak605_ctx *ctx = malloc(sizeof(struct kodak605_ctx));
@ -240,6 +274,7 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev,
struct kodak605_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
struct kodak605_status sts;
ctx->dev = dev;
ctx->endp_up = endp_up;
@ -256,16 +291,23 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev,
if (!ctx->jobid)
ctx->jobid++;
/* Init */
ctx->last_donor = 255;
/* Query media info */
if (kodak605_get_media(ctx, ctx->media)) {
ERROR("Can't query media\n");
return CUPS_BACKEND_FAILED;
}
// TODO: Update Marker
/* Update status */
if (kodak605_get_status(ctx, &sts)) {
ERROR("Can't query status\n");
return CUPS_BACKEND_FAILED;
}
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = kodak68xx_mediatypes(ctx->media->type);
ctx->marker.levelmax = 100; /* Ie percentage */
ctx->marker.levelnow = sts.donor;
return CUPS_BACKEND_OK;
}
@ -337,40 +379,6 @@ static int kodak605_read_parse(void *vctx, int data_fd) {
return CUPS_BACKEND_OK;
}
static int kodak605_get_status(struct kodak605_ctx *ctx, struct kodak605_status *sts)
{
uint8_t cmdbuf[4];
int ret, num = 0;
/* Send Status Query */
cmdbuf[0] = 0x01;
cmdbuf[1] = 0x00;
cmdbuf[2] = 0x00;
cmdbuf[3] = 0x00;
if ((ret = send_data(ctx->dev, ctx->endp_down,
cmdbuf, sizeof(cmdbuf))))
return ret;
/* Read in the printer status */
ret = read_data(ctx->dev, ctx->endp_up,
(uint8_t*) sts, sizeof(*sts), &num);
if (ret < 0)
return ret;
if (num < (int)sizeof(*sts)) {
ERROR("Short Read! (%d/%d)\n", num, (int)sizeof(*sts));
return CUPS_BACKEND_FAILED;
}
if (sts->hdr.result != RESULT_SUCCESS) {
ERROR("Unexpected response from status query (%x)!\n", sts->hdr.result);
return CUPS_BACKEND_FAILED;
}
return 0;
}
static int kodak605_main_loop(void *vctx, int copies) {
struct kodak605_ctx *ctx = vctx;
@ -396,22 +404,15 @@ static int kodak605_main_loop(void *vctx, int copies) {
return CUPS_BACKEND_HOLD;
}
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", kodak68xx_mediatypes(ctx->media->type));
ATTR("marker-types=ribbonWax\n");
INFO("Waiting for printer idle\n");
while(1) {
if ((ret = kodak605_get_status(ctx, &sts)))
return CUPS_BACKEND_FAILED;
if (ctx->last_donor != sts.donor) {
ctx->last_donor = sts.donor;
ATTR("marker-levels=%u\n", sts.donor);
if (ctx->marker.levelnow != sts.donor) {
ctx->marker.levelnow = sts.donor;
dump_markers(&ctx->marker, 1, 0);
}
// XXX check for errors
@ -470,13 +471,12 @@ static int kodak605_main_loop(void *vctx, int copies) {
if ((kodak605_get_status(ctx, &sts)) != 0)
return CUPS_BACKEND_FAILED;
if (ctx->marker.levelnow != sts.donor) {
ctx->marker.levelnow = sts.donor;
dump_markers(&ctx->marker, 1, 0);
}
// XXX check for errors
if (ctx->last_donor != sts.donor) {
ctx->last_donor = sts.donor;
ATTR("marker-levels=%u\n", sts.donor);
} // XXX check for errors ?
/* Wait for completion */
if (sts.b1_id == ctx->jobid && sts.b1_complete == sts.b1_total)
break;
@ -677,6 +677,23 @@ static int kodak605_cmdline_arg(void *vctx, int argc, char **argv)
return 0;
}
static int kodak605_query_markers(void *vctx, struct marker **markers, int *count)
{
struct kodak605_ctx *ctx = vctx;
struct kodak605_status sts;
/* Query printer status */
if (kodak605_get_status(ctx, &sts))
return CUPS_BACKEND_FAILED;
ctx->marker.levelnow = sts.donor;
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
static const char *kodak605_prefixes[] = {
"kodak605",
NULL,
@ -685,7 +702,7 @@ static const char *kodak605_prefixes[] = {
/* Exported */
struct dyesub_backend kodak605_backend = {
.name = "Kodak 605",
.version = "0.28",
.version = "0.29",
.uri_prefixes = kodak605_prefixes,
.cmdline_usage = kodak605_cmdline,
.cmdline_arg = kodak605_cmdline_arg,
@ -694,6 +711,7 @@ struct dyesub_backend kodak605_backend = {
.teardown = kodak605_teardown,
.read_parse = kodak605_read_parse,
.main_loop = kodak605_main_loop,
.query_markers = kodak605_query_markers,
.devices = {
{ USB_VID_KODAK, USB_PID_KODAK_605, P_KODAK_605, "Kodak", "kodaka605"},
{ 0, 0, 0, NULL, NULL}

View File

@ -239,7 +239,7 @@ struct kodak6800_ctx {
uint8_t *databuf;
int datalen;
uint8_t last_donor;
struct marker marker;
};
static const char *kodak68xx_mediatypes(int type)
@ -278,8 +278,6 @@ static int kodak6800_do_cmd(struct kodak6800_ctx *ctx,
return 0;
}
static void kodak68x0_dump_mediainfo(struct kodak68x0_media_readback *media)
{
int i;
@ -1018,6 +1016,7 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev,
struct kodak6800_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
struct kodak68x0_status_readback status;
ctx->dev = dev;
ctx->endp_up = endp_up;
@ -1034,16 +1033,21 @@ static int kodak6800_attach(void *vctx, struct libusb_device_handle *dev,
if (!ctx->jobid)
ctx->jobid++;
/* Init */
ctx->last_donor = 255;
/* Query media info */
if (kodak6800_get_mediainfo(ctx, ctx->media)) {
ERROR("Can't query media\n");
return CUPS_BACKEND_FAILED;
}
// TODO: Update Marker
/* Query printer status */
if (kodak6800_get_status(ctx, &status))
return CUPS_BACKEND_FAILED;
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = kodak68xx_mediatypes(ctx->media->type);
ctx->marker.levelmax = 100; /* Ie percentage */
ctx->marker.levelnow = status.donor;
return CUPS_BACKEND_OK;
}
@ -1143,22 +1147,15 @@ static int kodak6800_main_loop(void *vctx, int copies) {
return CUPS_BACKEND_HOLD;
}
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", kodak68xx_mediatypes(ctx->media->type));
ATTR("marker-types=ribbonWax\n");
INFO("Waiting for printer idle\n");
while(1) {
if (kodak6800_get_status(ctx, &status))
return CUPS_BACKEND_FAILED;
if (ctx->last_donor != status.donor) {
ctx->last_donor = status.donor;
ATTR("marker-levels=%u\n", status.donor);
if (ctx->marker.levelnow != status.donor) {
ctx->marker.levelnow = status.donor;
dump_markers(&ctx->marker, 1, 0);
}
if (status.status1 == STATE_STATUS1_ERROR) {
@ -1231,9 +1228,9 @@ static int kodak6800_main_loop(void *vctx, int copies) {
if (kodak6800_get_status(ctx, &status))
return CUPS_BACKEND_FAILED;
if (ctx->last_donor != status.donor) {
ctx->last_donor = status.donor;
ATTR("marker-levels=%u\n", status.donor);
if (ctx->marker.levelnow != status.donor) {
ctx->marker.levelnow = status.donor;
dump_markers(&ctx->marker, 1, 0);
}
if (status.status1 == STATE_STATUS1_ERROR) {
@ -1261,6 +1258,23 @@ static int kodak6800_main_loop(void *vctx, int copies) {
return CUPS_BACKEND_OK;
}
static int kodak6800_query_markers(void *vctx, struct marker **markers, int *count)
{
struct kodak6800_ctx *ctx = vctx;
struct kodak68x0_status_readback status;
/* Query printer status */
if (kodak6800_get_status(ctx, &status))
return CUPS_BACKEND_FAILED;
ctx->marker.levelnow = status.donor;
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
static const char *kodak6800_prefixes[] = {
"kodak68x0",
"kodak6800", "kodak6850",
@ -1270,7 +1284,7 @@ static const char *kodak6800_prefixes[] = {
/* Exported */
struct dyesub_backend kodak6800_backend = {
.name = "Kodak 6800/6850",
.version = "0.60",
.version = "0.61",
.uri_prefixes = kodak6800_prefixes,
.cmdline_usage = kodak6800_cmdline,
.cmdline_arg = kodak6800_cmdline_arg,
@ -1280,6 +1294,7 @@ struct dyesub_backend kodak6800_backend = {
.read_parse = kodak6800_read_parse,
.main_loop = kodak6800_main_loop,
.query_serno = kodak6800_query_serno,
.query_markers = kodak6800_query_markers,
.devices = {
{ USB_VID_KODAK, USB_PID_KODAK_6800, P_KODAK_6800, "Kodak", "kodak6800"},
{ USB_VID_KODAK, USB_PID_KODAK_6850, P_KODAK_6850, "Kodak", "kodak6850"},

View File

@ -909,7 +909,7 @@ struct dyesub_backend magicard_backend = {
.main_loop = magicard_main_loop,
.devices = {
{ USB_VID_MAGICARD, USB_PID_MAGICARD_TANGO2E, P_MAGICARD, NULL, "tango2e"},
{ USB_VID_MAGICARD, USB_PID_MAGICARD_ENDURO, P_MAGICARD, NULL, "enduro"},
{ USB_VID_MAGICARD, USB_PID_MAGICARD_ENDURO, P_MAGICARD, NULL, "enduro"},
{ USB_VID_MAGICARD, USB_PID_MAGICARD_ENDUROPLUS, P_MAGICARD, NULL, "enduroplus"},
{ USB_VID_MAGICARD, 0xFFFF, P_MAGICARD, NULL, "magicard"},
{ 0, 0, 0, NULL, "magicard"}

View File

@ -136,14 +136,16 @@ struct mitsu70x_ctx {
uint8_t *databuf;
int datalen;
struct marker marker[2];
uint32_t matte;
uint16_t jobid;
uint16_t rows;
uint16_t cols;
uint16_t last_donor_l;
uint16_t last_donor_u;
uint16_t last_l;
uint16_t last_u;
int num_decks;
char *laminatefname;
@ -709,7 +711,7 @@ static int mitsu70x_attach(void *vctx, struct libusb_device_handle *dev,
ctx->type = lookup_printer_type(&mitsu70x_backend,
desc.idVendor, desc.idProduct);
ctx->last_donor_l = ctx->last_donor_u = 65535;
ctx->last_l = ctx->last_u = 65535;
/* Attempt to open the library */
#if defined(WITH_DYNAMIC)
@ -788,7 +790,19 @@ static int mitsu70x_attach(void *vctx, struct libusb_device_handle *dev,
else
ctx->num_decks = 1;
// TODO: Update Marker
/* Set up markers */
ctx->marker[0].color = "#00FFFF#FF00FF#FFFF00";
ctx->marker[0].name = mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type);
ctx->marker[0].levelmax = be16_to_cpu(resp.lower.capacity);
ctx->marker[0].levelnow = be16_to_cpu(resp.lower.remain);
if (ctx->num_decks == 2) {
ctx->marker[1].color = "#00FFFF#FF00FF#FFFF00";
ctx->marker[1].name = mitsu70x_media_types(resp.upper.media_brand, resp.upper.media_type);
ctx->marker[1].levelmax = be16_to_cpu(resp.upper.capacity);
ctx->marker[1].levelnow = be16_to_cpu(resp.upper.remain);
}
return CUPS_BACKEND_OK;
}
@ -1528,23 +1542,6 @@ top:
if (ret)
return CUPS_BACKEND_FAILED;
if (ctx->num_decks == 2) {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00,#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100,100\n");
ATTR("marker-low-levels=10,10\n");
ATTR("marker-names='\"%s\"','\"%s\"'\n",
mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type),
mitsu70x_media_types(resp.upper.media_brand, resp.upper.media_type));
ATTR("marker-types=ribbonWax,ribbonWax\n");
} else {
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n",
mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type));
ATTR("marker-types=ribbonWax\n");
}
/* FW sanity checking */
if (ctx->type == P_KODAK_305) {
/* Known versions:
@ -1685,37 +1682,23 @@ skip_status:
INFO("Waiting for printer to acknowledge completion\n");
do {
uint16_t donor_u, donor_l;
sleep(1);
ret = mitsu70x_get_printerstatus(ctx, &resp);
if (ret)
return CUPS_BACKEND_FAILED;
donor_l = be16_to_cpu(resp.lower.remain) * 100 / be16_to_cpu(resp.lower.capacity);
ctx->marker[0].levelmax = be16_to_cpu(resp.lower.capacity);
ctx->marker[0].levelnow = be16_to_cpu(resp.lower.remain);
if (ctx->num_decks == 2) {
donor_u = be16_to_cpu(resp.upper.remain) * 100 / be16_to_cpu(resp.upper.capacity);
if (donor_l != ctx->last_donor_l ||
donor_u != ctx->last_donor_u) {
ctx->last_donor_l = donor_l;
ctx->last_donor_u = donor_u;
ATTR("marker-levels=%d,%d\n", donor_l, donor_u);
ATTR("marker-message='\"%d native prints remaining on %s media\"','\"%d native prints remaining on %s media\"'\n",
be16_to_cpu(resp.lower.remain),
mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type),
be16_to_cpu(resp.upper.remain),
mitsu70x_media_types(resp.upper.media_brand, resp.upper.media_type));
}
} else {
if (donor_l != ctx->last_donor_l) {
ctx->last_donor_l = donor_l;
ATTR("marker-levels=%d\n", donor_l);
ATTR("marker-message=\"%d native prints remaining on %s media\"\n",
be16_to_cpu(resp.lower.remain),
mitsu70x_media_types(resp.lower.media_brand, resp.lower.media_type));
}
ctx->marker[1].levelmax = be16_to_cpu(resp.upper.capacity);
ctx->marker[1].levelnow = be16_to_cpu(resp.upper.remain);
}
if (ctx->marker[0].levelnow != ctx->last_l ||
ctx->marker[1].levelnow != ctx->last_u) {
dump_markers(ctx->marker, ctx->num_decks, 0);
ctx->last_l = ctx->marker[0].levelnow;
ctx->last_u = ctx->marker[1].levelnow;
}
/* Query job status for our used jobid */
@ -1916,7 +1899,7 @@ static int mitsu70x_query_status(struct mitsu70x_ctx *ctx)
ret = mitsu70x_get_printerstatus(ctx, &resp);
if (!ret)
mitsu70x_dump_printerstatus(ctx, &resp);
return ret;
}
@ -1998,6 +1981,40 @@ static int mitsu70x_cmdline_arg(void *vctx, int argc, char **argv)
return 0;
}
static int mitsu70x_query_markers(void *vctx, struct marker **markers, int *count)
{
struct mitsu70x_ctx *ctx = vctx;
struct mitsu70x_printerstatus_resp resp;
int ret;
*markers = ctx->marker;
*count = ctx->num_decks;
/* Tell CUPS about the consumables we report */
ret = mitsu70x_get_printerstatus(ctx, &resp);
if (ret)
return CUPS_BACKEND_FAILED;
if (resp.power) {
ret = mitsu70x_wakeup(ctx, 1);
if (ret)
return CUPS_BACKEND_FAILED;
ret = mitsu70x_get_printerstatus(ctx, &resp);
if (ret)
return CUPS_BACKEND_FAILED;
}
ctx->marker[0].levelmax = be16_to_cpu(resp.lower.capacity);
ctx->marker[0].levelnow = be16_to_cpu(resp.lower.remain);
if (ctx->num_decks == 2) {
ctx->marker[1].levelmax = be16_to_cpu(resp.upper.capacity);
ctx->marker[1].levelnow = be16_to_cpu(resp.upper.remain);
}
return CUPS_BACKEND_OK;
}
static const char *mitsu70x_prefixes[] = {
"mitsu70x",
"mitsud80", "mitsuk60", "kodak305", "fujiask300",
@ -2007,7 +2024,7 @@ static const char *mitsu70x_prefixes[] = {
/* Exported */
struct dyesub_backend mitsu70x_backend = {
.name = "Mitsubishi CP-D70 family",
.version = "0.77",
.version = "0.78",
.uri_prefixes = mitsu70x_prefixes,
.cmdline_usage = mitsu70x_cmdline,
.cmdline_arg = mitsu70x_cmdline_arg,
@ -2017,6 +2034,7 @@ struct dyesub_backend mitsu70x_backend = {
.read_parse = mitsu70x_read_parse,
.main_loop = mitsu70x_main_loop,
.query_serno = mitsu70x_query_serno,
.query_markers = mitsu70x_query_markers,
.devices = {
{ USB_VID_MITSU, USB_PID_MITSU_D70X, P_MITSU_D70X, NULL, "mitsu70x"},
{ USB_VID_MITSU, USB_PID_MITSU_K60, P_MITSU_K60, NULL, "mitsuk60"},

View File

@ -173,9 +173,7 @@ struct mitsu9550_ctx {
uint16_t cols;
uint32_t plane_len;
uint16_t last_donor;
uint16_t last_remain;
int marker_reported;
struct marker marker;
/* Parse headers separately */
struct mitsu9550_hdr1 hdr1;
@ -235,39 +233,22 @@ struct mitsu9550_status2 {
struct mitsu9550_status *sts = (struct mitsu9550_status*) rdbuf;\
/* struct mitsu9550_status2 *sts2 = (struct mitsu9550_status2*) rdbuf; */ \
struct mitsu9550_media *media = (struct mitsu9550_media *) rdbuf; \
uint16_t donor, remain; \
uint16_t donor; \
/* media */ \
ret = mitsu9550_get_status(ctx, rdbuf, 0, 0, 1); \
if (ret < 0) \
return CUPS_BACKEND_FAILED; \
\
/* Tell CUPS about the consumables we report */ \
if (!ctx->marker_reported) { \
ctx->marker_reported = 1; \
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n"); \
ATTR("marker-high-levels=100\n"); \
ATTR("marker-low-levels=10\n"); \
ATTR("marker-names='%s'\n", mitsu9550_media_types(media->type, ctx->is_s)); \
ATTR("marker-types=ribbonWax\n"); \
donor = be16_to_cpu(media->remain); \
if (donor != ctx->marker.levelnow) { \
ctx->marker.levelnow = donor; \
dump_markers(&ctx->marker, 1, 0); \
} \
\
/* Sanity-check media response */ \
if (media->remain == 0 || media->max == 0) { \
ERROR("Printer out of media!\n"); \
ATTR("marker-levels=%d\n", 0); \
return CUPS_BACKEND_HOLD; \
} \
remain = be16_to_cpu(media->remain); \
donor = be16_to_cpu(media->max); \
donor = remain/donor; \
if (donor != ctx->last_donor) { \
ctx->last_donor = donor; \
ATTR("marker-levels=%u\n", donor); \
} \
if (remain != ctx->last_remain) { \
ctx->last_remain = remain; \
ATTR("marker-message=\"%u prints remaining on '%s' ribbon\"\n", remain, mitsu9550_media_types(media->type, ctx->is_s)); \
} \
if (validate_media(ctx->type, media->type, ctx->cols, ctx->rows)) { \
ERROR("Incorrect media (%u) type for printjob (%ux%u)!\n", media->type, ctx->cols, ctx->rows); \
return CUPS_BACKEND_HOLD; \
@ -527,6 +508,8 @@ void CColorConv3D_DoColorConv(struct CColorConv3D *this, uint8_t *data, uint16_t
}
}
/* ---- end 3D LUT ---- */
static int mitsu9550_get_status(struct mitsu9550_ctx *ctx, uint8_t *resp, int status, int status2, int media);
static char *mitsu9550_media_types(uint8_t type, uint8_t is_s);
static void *mitsu9550_init(void)
{
@ -546,6 +529,7 @@ static int mitsu9550_attach(void *vctx, struct libusb_device_handle *dev,
struct mitsu9550_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
struct mitsu9550_media media;
UNUSED(jobid);
@ -568,9 +552,14 @@ static int mitsu9550_attach(void *vctx, struct libusb_device_handle *dev,
ctx->type == P_MITSU_9810)
ctx->is_98xx = 1;
ctx->last_donor = ctx->last_remain = 65535;
if (mitsu9550_get_status(ctx, (uint8_t*) &media, 0, 0, 1))
return CUPS_BACKEND_FAILED;
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = mitsu9550_media_types(media.type, ctx->is_s);
ctx->marker.levelmax = be16_to_cpu(media.max);
ctx->marker.levelnow = be16_to_cpu(media.remain);
// TODO: Query & Update Marker
return CUPS_BACKEND_OK;
}
@ -836,7 +825,7 @@ hdr_done:
}
CColorConv3D_DoColorConv(lut, ctx->databuf + sizeof(struct mitsu9550_plane),
ctx->cols, ctx->rows, ctx->cols * 3, COLORCONV_BGR);
CColorConv3D_Destroy3DColorTable(lut);
CColorConv3D_Destroy3DColorTable(lut);
ctx->hdr2.unkc[9] = 0;
}
@ -1313,29 +1302,22 @@ top:
struct mitsu9550_status *sts = (struct mitsu9550_status*) rdbuf;
// struct mitsu9550_status2 *sts2 = (struct mitsu9550_status2*) rdbuf;
struct mitsu9550_media *media = (struct mitsu9550_media *) rdbuf;
uint16_t donor, remain;
uint16_t donor;
ret = mitsu9550_get_status(ctx, rdbuf, 0, 0, 1); // media
if (ret < 0)
return CUPS_BACKEND_FAILED;
donor = be16_to_cpu(media->remain);
if (donor != ctx->marker.levelnow) {
ctx->marker.levelnow = donor;
dump_markers(&ctx->marker, 1, 0);
}
/* Sanity-check media response */
if (media->remain == 0 || media->max == 0) {
ERROR("Printer out of media!\n");
ATTR("marker-levels=%d\n", 0);
return CUPS_BACKEND_HOLD;
}
remain = be16_to_cpu(media->remain);
donor = be16_to_cpu(media->max);
donor = remain/donor;
if (donor != ctx->last_donor) {
ctx->last_donor = donor;
ATTR("marker-levels=%u\n", donor);
}
if (remain != ctx->last_remain) {
ctx->last_remain = remain;
ATTR("marker-message=\"%u prints remaining on '%s' ribbon\"\n", remain, mitsu9550_media_types(media->type, ctx->is_s));
}
ret = mitsu9550_get_status(ctx, rdbuf, 0, 1, 0); // status2
if (ret < 0)
return CUPS_BACKEND_FAILED;
@ -1417,29 +1399,22 @@ top:
struct mitsu9550_status *sts = (struct mitsu9550_status*) rdbuf;
// struct mitsu9550_status2 *sts2 = (struct mitsu9550_status2*) rdbuf;
struct mitsu9550_media *media = (struct mitsu9550_media *) rdbuf;
uint16_t donor, remain;
uint16_t donor;
ret = mitsu9550_get_status(ctx, rdbuf, 0, 0, 1); // media
if (ret < 0)
return CUPS_BACKEND_FAILED;
donor = be16_to_cpu(media->remain);
if (donor != ctx->marker.levelnow) {
ctx->marker.levelnow = donor;
dump_markers(&ctx->marker, 1, 0);
}
/* Sanity-check media response */
if (media->remain == 0 || media->max == 0) {
ERROR("Printer out of media!\n");
ATTR("marker-levels=%d\n", 0);
return CUPS_BACKEND_HOLD;
}
remain = be16_to_cpu(media->remain);
donor = be16_to_cpu(media->max);
donor = remain/donor;
if (donor != ctx->last_donor) {
ctx->last_donor = donor;
ATTR("marker-levels=%u\n", donor);
}
if (remain != ctx->last_remain) {
ctx->last_remain = remain;
ATTR("marker-message=\"%u prints remaining on '%s' ribbon\"\n", remain, mitsu9550_media_types(media->type, ctx->is_s));
}
ret = mitsu9550_get_status(ctx, rdbuf, 0, 1, 0); // status2
if (ret < 0)
return CUPS_BACKEND_FAILED;
@ -1641,6 +1616,23 @@ static int mitsu9550_cmdline_arg(void *vctx, int argc, char **argv)
return 0;
}
static int mitsu9550_query_markers(void *vctx, struct marker **markers, int *count)
{
struct mitsu9550_ctx *ctx = vctx;
struct mitsu9550_media media;
/* Query printer status */
if (mitsu9550_get_status(ctx, (uint8_t*) &media, 0, 0, 1))
return CUPS_BACKEND_FAILED;
ctx->marker.levelnow = be16_to_cpu(media.remain);
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
static const char *mitsu9550_prefixes[] = {
"mitsu9xxx",
"mitsu9000", "mitsu9500", "mitsu9550", "mitsi9600", "mitsu9800", "mitsu9810",
@ -1650,7 +1642,7 @@ static const char *mitsu9550_prefixes[] = {
/* Exported */
struct dyesub_backend mitsu9550_backend = {
.name = "Mitsubishi CP9xxx family",
.version = "0.33",
.version = "0.34",
.uri_prefixes = mitsu9550_prefixes,
.cmdline_usage = mitsu9550_cmdline,
.cmdline_arg = mitsu9550_cmdline_arg,
@ -1660,6 +1652,7 @@ struct dyesub_backend mitsu9550_backend = {
.read_parse = mitsu9550_read_parse,
.main_loop = mitsu9550_main_loop,
.query_serno = mitsu9550_query_serno,
.query_markers = mitsu9550_query_markers,
.devices = {
{ USB_VID_MITSU, USB_PID_MITSU_9000AM, P_MITSU_9550, NULL, "mitsu9000"},
{ USB_VID_MITSU, USB_PID_MITSU_9000D, P_MITSU_9550, NULL, "mitsu9000"},

View File

@ -417,6 +417,8 @@ struct shinkos1245_ctx {
int num_medias;
int media_8x12;
struct marker marker;
uint8_t *databuf;
int datalen;
int tonecurve;
@ -1280,6 +1282,7 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev,
struct shinkos1245_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
struct shinkos1245_resp_status status;
ctx->dev = dev;
ctx->endp_up = endp_up;
@ -1296,7 +1299,23 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev,
if (!ctx->jobid)
ctx->jobid++;
/* TODO: Query & Update Marker */
/* Query Media */
if (shinkos1245_get_media(ctx))
return CUPS_BACKEND_FAILED;
if (!ctx->num_medias) {
ERROR("Media Query Error\n");
return CUPS_BACKEND_FAILED;
}
/* Query status */
if (shinkos1245_get_status(ctx, &status))
return CUPS_BACKEND_FAILED;
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = ctx->media_8x12 ? "8x12" : "8x10";
ctx->marker.levelmax = ctx->media_8x12 ? 230 : 280;
ctx->marker.levelnow = ctx->marker.levelmax - be32_to_cpu(status.counters.media);
return CUPS_BACKEND_OK;
}
@ -1405,13 +1424,6 @@ static int shinkos1245_main_loop(void *vctx, int copies) {
int i, num, last_state = -1, state = S_IDLE;
struct shinkos1245_resp_status status1, status2;
/* Query Media information if necessary */
if (!ctx->num_medias)
shinkos1245_get_media(ctx);
if (!ctx->num_medias) {
ERROR("Media Query Error\n");
return CUPS_BACKEND_FAILED;
}
/* Make sure print size is supported */
for (i = 0 ; i < ctx->num_medias ; i++) {
if (ctx->hdr.media == ctx->medias[i].code &&
@ -1429,13 +1441,6 @@ static int shinkos1245_main_loop(void *vctx, int copies) {
if (copies > 9999) // XXX test against remaining media?
copies = 9999;
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", ctx->media_8x12? "8x12" : "8x10");
ATTR("marker-types=ribbonWax\n");
top:
if (state != last_state) {
if (dyesub_debug)
@ -1459,15 +1464,6 @@ top:
if (status1.state.status1 == STATE_STATUS1_ERROR)
goto printer_error;
/* Work out the remaining media percentage */
{
int total = ctx->media_8x12 ? 230 : 280;
int remain = total - be32_to_cpu(status1.counters.media);
ATTR("marker-levels=%d\n", remain * 100 / total);
ATTR("marker-message=\"%d prints remaining on ribbon\"\n", remain);
}
last_state = state;
fflush(stderr);
@ -1642,6 +1638,23 @@ static int shinkos1245_query_serno(struct libusb_device_handle *dev, uint8_t end
return CUPS_BACKEND_OK;
}
static int shinkos1245_query_markers(void *vctx, struct marker **markers, int *count)
{
struct shinkos1245_ctx *ctx = vctx;
struct shinkos1245_resp_status status;
/* Query status */
if (shinkos1245_get_status(ctx, &status))
return CUPS_BACKEND_FAILED;
ctx->marker.levelnow = ctx->marker.levelmax - be32_to_cpu(status.counters.media);
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
/* Exported */
#define USB_VID_SHINKO 0x10CE
#define USB_PID_SHINKO_S1245 0x0007
@ -1653,7 +1666,7 @@ static const char *shinkos1245_prefixes[] = {
struct dyesub_backend shinkos1245_backend = {
.name = "Shinko/Sinfonia CHC-S1245/E1",
.version = "0.20",
.version = "0.21",
.uri_prefixes = shinkos1245_prefixes,
.cmdline_usage = shinkos1245_cmdline,
.cmdline_arg = shinkos1245_cmdline_arg,
@ -1663,6 +1676,7 @@ struct dyesub_backend shinkos1245_backend = {
.read_parse = shinkos1245_read_parse,
.main_loop = shinkos1245_main_loop,
.query_serno = shinkos1245_query_serno,
.query_markers = shinkos1245_query_markers,
.devices = {
{ USB_VID_SHINKO, USB_PID_SHINKO_S1245, P_SHINKO_S1245, NULL, "shinkos1245"},
{ 0, 0, 0, NULL, NULL}

View File

@ -92,24 +92,6 @@ struct s2145_printjob_hdr {
uint32_t unk21;
} __attribute__((packed));
/* Private data structure */
struct shinkos2145_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
uint8_t jobid;
struct s2145_printjob_hdr hdr;
uint8_t *databuf;
int datalen;
uint16_t last_donor;
uint16_t last_remain;
uint16_t media_prints;
};
/* Structs for printer */
struct s2145_cmd_hdr {
uint16_t cmd;
@ -803,6 +785,24 @@ struct s2145_getunique_resp {
uint8_t data[24]; /* Not necessarily all used. */
} __attribute__((packed));
/* Private data structure */
struct shinkos2145_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
uint8_t jobid;
struct s2145_printjob_hdr hdr;
uint8_t *databuf;
int datalen;
struct s2145_mediainfo_resp media;
struct marker marker;
int media_code;
};
#define READBACK_LEN 128 /* Needs to be larger than largest response hdr */
#define CMDBUF_LEN sizeof(struct s2145_print_cmd)
@ -973,27 +973,10 @@ static int get_errorlog(struct shinkos2145_ctx *ctx)
return 0;
}
static int get_mediainfo(struct shinkos2145_ctx *ctx)
static void dump_mediainfo(struct s2145_mediainfo_resp *resp)
{
struct s2145_cmd_hdr cmd;
struct s2145_mediainfo_resp *resp = (struct s2145_mediainfo_resp *) rdbuf;
int ret, num = 0;
int i;
cmd.cmd = cpu_to_le16(S2145_CMD_MEDIAINFO);
cmd.len = cpu_to_le16(0);
if ((ret = s2145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s2145_mediainfo_resp) - sizeof(struct s2145_status_hdr)))
return -2;
INFO("Supported Media Information: %u entries:\n", resp->count);
for (i = 0 ; i < resp->count ; i++) {
INFO(" %02d: C 0x%02x (%s), %04ux%04u, M 0x%02x (%s), P 0x%02x (%s)\n", i,
@ -1003,7 +986,6 @@ static int get_mediainfo(struct shinkos2145_ctx *ctx)
resp->items[i].media_type, media_types(resp->items[i].media_type),
resp->items[i].print_type, print_methods(resp->items[i].print_type));
}
return 0;
}
static int get_user_string(struct shinkos2145_ctx *ctx)
@ -1357,7 +1339,7 @@ int shinkos2145_cmdline_arg(void *vctx, int argc, char **argv)
j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg);
break;
case 'm':
j = get_mediainfo(ctx);
dump_mediainfo(&ctx->media);
break;
case 'r':
j = reset_curve(ctx, RESET_USER_CURVE);
@ -1405,6 +1387,7 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev,
uint8_t endp_up, uint8_t endp_down, uint8_t jobid)
{
struct shinkos2145_ctx *ctx = vctx;
int i;
ctx->dev = dev;
ctx->endp_up = endp_up;
@ -1415,10 +1398,49 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev,
if (!ctx->jobid)
ctx->jobid++;
/* Initialize donor */
ctx->last_donor = ctx->last_remain = ctx->media_prints = 65535;
/* Query Media */
struct s2145_cmd_hdr cmd;
struct s2145_mediainfo_resp *resp = (struct s2145_mediainfo_resp *) rdbuf;
int num = 0;
cmd.cmd = cpu_to_le16(S2145_CMD_MEDIAINFO);
cmd.len = cpu_to_le16(0);
if (s2145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
memcpy(&ctx->media, resp, sizeof(ctx->media));
/* Figure out the media type... */
int media_prints = 65536;
for (i = 0 ; i < ctx->media.count ; i++) {
if (print_counts(ctx->media.items[i].code) < media_prints) {
media_prints = print_counts(ctx->media.items[i].code);
ctx->media_code = ctx->media.items[i].code;
}
}
/* Query Status */
struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf;
cmd.cmd = cpu_to_le16(S2145_CMD_STATUS);
cmd.len = cpu_to_le16(0);
if (s2145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*sts),
&num)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = print_sizes(ctx->media_code);
ctx->marker.levelmax = media_prints;
ctx->marker.levelnow = le32_to_cpu(sts->count_ribbon_left);
// TODO: Query & Update Marker
return CUPS_BACKEND_OK;
}
@ -1525,49 +1547,20 @@ static int shinkos2145_main_loop(void *vctx, int copies) {
struct s2145_cmd_hdr *cmd = (struct s2145_cmd_hdr *) cmdbuf;;
struct s2145_print_cmd *print = (struct s2145_print_cmd *) cmdbuf;
struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf;
struct s2145_mediainfo_resp *media = (struct s2145_mediainfo_resp *) rdbuf;
/* Send Media Query */
memset(cmdbuf, 0, CMDBUF_LEN);
cmd->cmd = cpu_to_le16(S2145_CMD_MEDIAINFO);
cmd->len = cpu_to_le16(0);
if ((ret = s2145_do_cmd(ctx,
cmdbuf, sizeof(*cmd),
sizeof(*media),
&num)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd));
return CUPS_BACKEND_FAILED;
}
if (le16_to_cpu(media->hdr.payload_len) != (sizeof(struct s2145_mediainfo_resp) - sizeof(struct s2145_status_hdr)))
return CUPS_BACKEND_FAILED;
/* Validate print sizes */
for (i = 0; i < media->count ; i++) {
/* Figure out the media type... */
int media_prints = print_counts(media->items[i].code);
if (media_prints < ctx->media_prints)
ctx->media_prints = media_prints;
for (i = 0; i < ctx->media.count ; i++) {
/* Look for matching media */
if (le16_to_cpu(media->items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) &&
le16_to_cpu(media->items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)) &&
media->items[i].print_type == le32_to_cpu(ctx->hdr.method))
if (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) &&
le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)) &&
ctx->media.items[i].print_type == le32_to_cpu(ctx->hdr.method))
break;
}
if (i == media->count) {
if (i == ctx->media.count) {
ERROR("Incorrect media loaded for print!\n");
return CUPS_BACKEND_HOLD;
}
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='Color'\n");
ATTR("marker-types=ribbonWax\n");
// XXX check copies against remaining media!
top:
@ -1590,23 +1583,14 @@ top:
}
if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
uint16_t donor, remain;
memcpy(rdbuf2, rdbuf, READBACK_LEN);
INFO("Printer Status: 0x%02x (%s)\n",
sts->hdr.status, status_str(sts->hdr.status));
/* Guessimate a percentage for the remaining media */
donor = le32_to_cpu(sts->count_ribbon_left) * 100 / ctx->media_prints;
if (donor != ctx->last_donor) {
ctx->last_donor = donor;
ATTR("marker-levels=%d\n", donor);
}
remain = le32_to_cpu(sts->count_ribbon_left);
if (remain != ctx->last_remain) {
ctx->last_remain = remain;
ATTR("marker-message=\"%d prints remaining on ribbon\"\n", remain);
if (ctx->marker.levelnow != (int)sts->count_ribbon_left) {
ctx->marker.levelnow = sts->count_ribbon_left;
dump_markers(&ctx->marker, 1, 0);
}
if (sts->hdr.result != RESULT_SUCCESS)
@ -1689,7 +1673,8 @@ top:
INFO("Fast return mode enabled.\n");
state = S_FINISHED;
} else if (sts->hdr.status == STATUS_READY ||
sts->hdr.status == STATUS_FINISHED) {
sts->hdr.status == STATUS_FINISHED ||
sts->hdr.status == ERROR_PRINTER) {
state = S_FINISHED;
}
break;
@ -1700,6 +1685,16 @@ top:
if (state != S_FINISHED)
goto top;
if (sts->hdr.status == ERROR_PRINTER) {
if(sts->hdr.error == ERROR_NONE)
sts->hdr.error = sts->hdr.status;
INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n",
sts->hdr.error,
error_str(sts->hdr.error),
sts->hdr.printer_major,
sts->hdr.printer_minor, error_codes(sts->hdr.printer_major, sts->hdr.printer_minor));
}
INFO("Print complete\n");
return CUPS_BACKEND_OK;
@ -1749,6 +1744,33 @@ static int shinkos2145_query_serno(struct libusb_device_handle *dev, uint8_t end
return CUPS_BACKEND_OK;
}
static int shinkos2145_query_markers(void *vctx, struct marker **markers, int *count)
{
struct shinkos2145_ctx *ctx = vctx;
struct s2145_cmd_hdr cmd;
struct s2145_status_resp *sts = (struct s2145_status_resp *) rdbuf;
int num;
/* Query Status */
cmd.cmd = cpu_to_le16(S2145_CMD_STATUS);
cmd.len = cpu_to_le16(0);
if (s2145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*sts),
&num)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(sts->count_ribbon_left);
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
/* Exported */
#define USB_VID_SHINKO 0x10CE
#define USB_PID_SHINKO_S2145 0x000E
@ -1760,7 +1782,7 @@ static const char *shinkos2145_prefixes[] = {
struct dyesub_backend shinkos2145_backend = {
.name = "Shinko/Sinfonia CHC-S2145/S2",
.version = "0.50",
.version = "0.51",
.uri_prefixes = shinkos2145_prefixes,
.cmdline_usage = shinkos2145_cmdline,
.cmdline_arg = shinkos2145_cmdline_arg,
@ -1770,6 +1792,7 @@ struct dyesub_backend shinkos2145_backend = {
.read_parse = shinkos2145_read_parse,
.main_loop = shinkos2145_main_loop,
.query_serno = shinkos2145_query_serno,
.query_markers = shinkos2145_query_markers,
.devices = {
{ USB_VID_SHINKO, USB_PID_SHINKO_S2145, P_SHINKO_S2145, NULL, "shinkos2145"},
{ 0, 0, 0, NULL, NULL}

View File

@ -261,43 +261,6 @@ struct shinkos6145_correctionparam {
uint8_t pad[3948]; // @12436, null.
} __attribute__((packed)); /* 16384 bytes */
/* Private data structure */
struct shinkos6145_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
uint8_t jobid;
struct s6145_printjob_hdr hdr;
uint8_t image_avg[3]; /* CMY */
uint8_t *databuf;
size_t datalen;
uint8_t ribbon_type;
uint8_t input_ymc;
uint16_t last_donor;
uint16_t last_remain;
uint16_t last_ribbon;
uint8_t *eeprom;
size_t eepromlen;
void *dl_handle;
ImageProcessingFN ImageProcessing;
ImageAvrCalcFN ImageAvrCalc;
struct shinkos6145_correctionparam *corrdata;
size_t corrdatalen;
};
static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx);
static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx);
/* Structs for printer */
struct s6145_cmd_hdr {
uint16_t cmd;
@ -1117,6 +1080,41 @@ struct s6145_imagecorr_data {
uint8_t data[16];
} __attribute__((packed));
/* Private data structure */
struct shinkos6145_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
uint8_t jobid;
struct s6145_printjob_hdr hdr;
uint8_t image_avg[3]; /* CMY */
uint8_t *databuf;
size_t datalen;
uint8_t input_ymc;
struct marker marker;
struct s6145_mediainfo_resp media;
uint8_t *eeprom;
size_t eepromlen;
void *dl_handle;
ImageProcessingFN ImageProcessing;
ImageAvrCalcFN ImageAvrCalc;
struct shinkos6145_correctionparam *corrdata;
size_t corrdatalen;
};
static int shinkos6145_get_imagecorr(struct shinkos6145_ctx *ctx);
static int shinkos6145_get_eeprom(struct shinkos6145_ctx *ctx);
static int get_param(struct shinkos6145_ctx *ctx, int target, uint32_t *param);
#define READBACK_LEN 512 /* Needs to be larger than largest response hdr */
@ -1357,27 +1355,10 @@ static int get_errorlog(struct shinkos6145_ctx *ctx)
return 0;
}
static int get_mediainfo(struct shinkos6145_ctx *ctx)
static void dump_mediainfo(struct s6145_mediainfo_resp *resp)
{
struct s6145_cmd_hdr cmd;
struct s6145_mediainfo_resp *resp = (struct s6145_mediainfo_resp *) rdbuf;
int ret, num = 0;
int i;
cmd.cmd = cpu_to_le16(S6145_CMD_MEDIAINFO);
cmd.len = cpu_to_le16(0);
if ((ret = s6145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6145_mediainfo_resp) - sizeof(struct s6145_status_hdr)))
return -2;
INFO("Loaded Media Type: %s\n", print_ribbons(resp->ribbon));
INFO("Supported Print Sizes: %u entries:\n", resp->count);
for (i = 0 ; i < resp->count ; i++) {
@ -1387,7 +1368,6 @@ static int get_mediainfo(struct shinkos6145_ctx *ctx)
le16_to_cpu(resp->items[i].rows),
resp->items[i].print_method, print_methods(resp->items[i].print_method));
}
return 0;
}
static int cancel_job(struct shinkos6145_ctx *ctx, char *str)
@ -1867,7 +1847,7 @@ int shinkos6145_cmdline_arg(void *vctx, int argc, char **argv)
j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg);
break;
case 'm':
j = get_mediainfo(ctx);
dump_mediainfo(&ctx->media);
break;
case 'q':
j = shinkos6145_dump_eeprom(ctx, optarg);
@ -1954,10 +1934,38 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev,
/* Ensure jobid is sane */
ctx->jobid = (jobid & 0x7f) + 1;
/* Initialize donor */
ctx->last_donor = ctx->last_remain = 65535;
/* Query Media */
struct s6145_mediainfo_resp *resp = (struct s6145_mediainfo_resp *) rdbuf;
struct s6145_cmd_hdr cmd;
int num;
if (s6145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
memcpy(&ctx->media, resp, sizeof(*resp));
/* Query Status */
struct s6145_status_resp *sts = (struct s6145_status_resp *) rdbuf;
cmd.cmd = cpu_to_le16(S6145_CMD_GETSTATUS);
cmd.len = cpu_to_le16(0);
if (s6145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*sts),
&num)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = print_ribbons(ctx->media.ribbon);
ctx->marker.levelmax = ribbon_sizes(ctx->media.ribbon);
ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(sts->count_ribbon_left);
// TODO: Query & Update Marker
return CUPS_BACKEND_OK;
}
@ -2207,16 +2215,6 @@ static int shinkos6145_main_loop(void *vctx, int copies) {
return CUPS_BACKEND_HOLD;
}
ctx->last_ribbon = media->ribbon;
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", print_ribbons(media->ribbon));
ATTR("marker-types=ribbonWax\n");
ctx->ribbon_type = media->ribbon;
// XXX check copies against remaining media?
/* Query printer mode */
@ -2246,23 +2244,14 @@ top:
}
if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
uint16_t donor, remain;
memcpy(rdbuf2, rdbuf, READBACK_LEN);
INFO("Printer Status: 0x%02x (%s)\n",
sts->hdr.status, status_str(sts->hdr.status));
/* Guessimate a percentage for the remaining media */
donor = le32_to_cpu(sts->count_ribbon_left) * 100 / ribbon_sizes(ctx->ribbon_type);
if (donor != ctx->last_donor) {
ctx->last_donor = donor;
ATTR("marker-levels=%d\n", donor);
}
remain = le32_to_cpu(sts->count_ribbon_left);
if (remain != ctx->last_remain) {
ctx->last_remain = remain;
ATTR("marker-message=\"%d prints remaining on '%s' ribbon\"\n", remain, print_ribbons(media->ribbon));
if (ctx->marker.levelnow != (int)sts->count_ribbon_left) {
ctx->marker.levelnow = sts->count_ribbon_left;
dump_markers(&ctx->marker, 1, 0);
}
if (sts->hdr.result != RESULT_SUCCESS)
@ -2492,6 +2481,33 @@ static int shinkos6145_query_serno(struct libusb_device_handle *dev, uint8_t end
return CUPS_BACKEND_OK;
}
static int shinkos6145_query_markers(void *vctx, struct marker **markers, int *count)
{
struct shinkos6145_ctx *ctx = vctx;
struct s6145_cmd_hdr cmd;
struct s6145_status_resp *sts = (struct s6145_status_resp *) rdbuf;
int num;
/* Query Status */
cmd.cmd = cpu_to_le16(S6145_CMD_GETSTATUS);
cmd.len = cpu_to_le16(0);
if (s6145_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*sts),
&num)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
ctx->marker.levelnow = le32_to_cpu(sts->count_ribbon_left);
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
/* Exported */
#define USB_VID_SHINKO 0x10CE
#define USB_PID_SHINKO_S6145 0x0019
@ -2504,7 +2520,7 @@ static const char *shinkos6145_prefixes[] = {
struct dyesub_backend shinkos6145_backend = {
.name = "Shinko/Sinfonia CHC-S6145/CS2",
.version = "0.24",
.version = "0.25",
.uri_prefixes = shinkos6145_prefixes,
.cmdline_usage = shinkos6145_cmdline,
.cmdline_arg = shinkos6145_cmdline_arg,
@ -2514,6 +2530,7 @@ struct dyesub_backend shinkos6145_backend = {
.read_parse = shinkos6145_read_parse,
.main_loop = shinkos6145_main_loop,
.query_serno = shinkos6145_query_serno,
.query_markers = shinkos6145_query_markers,
.devices = {
{ USB_VID_SHINKO, USB_PID_SHINKO_S6145, P_SHINKO_S6145, NULL, "shinkos6145"},
{ USB_VID_SHINKO, USB_PID_SHINKO_S6145D, P_SHINKO_S6145D, NULL, "brava21"},

View File

@ -92,25 +92,6 @@ struct s6245_printjob_hdr {
uint32_t unk21;
} __attribute__((packed));
/* Private data structure */
struct shinkos6245_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
uint8_t jobid;
struct s6245_printjob_hdr hdr;
uint8_t *databuf;
int datalen;
uint16_t last_donor;
uint16_t last_remain;
uint8_t ribbon_code;
};
/* Structs for printer */
struct s6245_cmd_hdr {
uint16_t cmd;
@ -926,37 +907,47 @@ struct s6245_fwinfo_resp {
uint16_t checksum;
} __attribute__((packed));
/* Private data structure */
struct shinkos6245_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
int type;
uint8_t jobid;
struct s6245_printjob_hdr hdr;
struct marker marker;
uint8_t *databuf;
int datalen;
struct s6245_mediainfo_resp media;
};
#define READBACK_LEN 512 /* Needs to be larger than largest response hdr */
#define CMDBUF_LEN sizeof(struct s6245_print_cmd)
static uint8_t rdbuf[READBACK_LEN];
static int s6245_do_cmd(struct shinkos6245_ctx *ctx,
uint8_t *cmd, int cmdlen,
int minlen, int *num)
int buflen,
int *num, struct s6245_status_hdr *resp)
{
int ret;
struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf;
libusb_device_handle *dev = ctx->dev;
uint8_t endp_up = ctx->endp_up;
uint8_t endp_down = ctx->endp_down;
int ret;
if ((ret = send_data(dev, endp_down,
cmd, cmdlen)))
return (ret < 0) ? ret : -99;
ret = read_data(dev, endp_up,
rdbuf, READBACK_LEN, num);
(uint8_t *)resp, buflen, num);
if (ret < 0)
return ret;
if (*num < minlen) {
ERROR("Short read! (%d/%d))\n", *num, minlen);
return -99;
}
if (resp->result != RESULT_SUCCESS) {
INFO("Printer Status: %02x (%s)\n", resp->status,
@ -973,8 +964,8 @@ static int s6245_do_cmd(struct shinkos6245_ctx *ctx,
static int get_status(struct shinkos6245_ctx *ctx)
{
struct s6245_cmd_hdr cmd;
struct s6245_status_resp *resp = (struct s6245_status_resp *) rdbuf;
struct s6245_getextcounter_resp *resp2 = (struct s6245_getextcounter_resp *) rdbuf;
struct s6245_status_resp resp;
struct s6245_getextcounter_resp resp2;
int ret, num = 0;
cmd.cmd = cpu_to_le16(S6245_CMD_GETSTATUS);
@ -982,48 +973,48 @@ static int get_status(struct shinkos6245_ctx *ctx)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
INFO("Printer Status: 0x%02x (%s)\n", resp->hdr.status,
status_str(resp->hdr.status));
if (resp->hdr.status == ERROR_PRINTER) {
if(resp->hdr.error == ERROR_NONE)
resp->hdr.error = resp->hdr.status;
INFO("Printer Status: 0x%02x (%s)\n", resp.hdr.status,
status_str(resp.hdr.status));
if (resp.hdr.status == ERROR_PRINTER) {
if(resp.hdr.error == ERROR_NONE)
resp.hdr.error = resp.hdr.status;
INFO(" Error 0x%02x (%s) 0x%02x/0x%02x (%s)\n",
resp->hdr.error,
error_str(resp->hdr.error),
resp->hdr.printer_major,
resp->hdr.printer_minor, error_codes(resp->hdr.printer_major, resp->hdr.printer_minor));
resp.hdr.error,
error_str(resp.hdr.error),
resp.hdr.printer_major,
resp.hdr.printer_minor, error_codes(resp.hdr.printer_major, resp.hdr.printer_minor));
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_status_resp) - sizeof(struct s6245_status_hdr)))
if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_status_resp) - sizeof(struct s6245_status_hdr)))
return 0;
INFO(" Print Counts:\n");
INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp->count_paper));
INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp->count_lifetime));
INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp->count_maint));
INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp->count_head));
INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp->count_cutter));
INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp->count_ribbon_left));
INFO("\tSince Paper Changed:\t%08u\n", le32_to_cpu(resp.count_paper));
INFO("\tLifetime:\t\t%08u\n", le32_to_cpu(resp.count_lifetime));
INFO("\tMaintenance:\t\t%08u\n", le32_to_cpu(resp.count_maint));
INFO("\tPrint Head:\t\t%08u\n", le32_to_cpu(resp.count_head));
INFO(" Cutter Actuations:\t%08u\n", le32_to_cpu(resp.count_cutter));
INFO(" Ribbon Remaining:\t%08u\n", le32_to_cpu(resp.count_ribbon_left));
INFO("Bank 1: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n",
resp->bank1_status, bank_statuses(resp->bank1_status),
resp->bank1_printid,
le16_to_cpu(resp->bank1_finished),
le16_to_cpu(resp->bank1_specified),
le16_to_cpu(resp->bank1_remaining));
resp.bank1_status, bank_statuses(resp.bank1_status),
resp.bank1_printid,
le16_to_cpu(resp.bank1_finished),
le16_to_cpu(resp.bank1_specified),
le16_to_cpu(resp.bank1_remaining));
INFO("Bank 2: 0x%02x (%s) Job %03u @ %03u/%03u (%03u remaining)\n",
resp->bank2_status, bank_statuses(resp->bank1_status),
resp->bank2_printid,
le16_to_cpu(resp->bank2_finished),
le16_to_cpu(resp->bank2_specified),
le16_to_cpu(resp->bank2_remaining));
resp.bank2_status, bank_statuses(resp.bank1_status),
resp.bank2_printid,
le16_to_cpu(resp.bank2_finished),
le16_to_cpu(resp.bank2_specified),
le16_to_cpu(resp.bank2_remaining));
INFO("Tonecurve Status: 0x%02x (%s)\n", resp->tonecurve_status, tonecurve_statuses(resp->tonecurve_status));
INFO("Tonecurve Status: 0x%02x (%s)\n", resp.tonecurve_status, tonecurve_statuses(resp.tonecurve_status));
/* Query Extended counters */
cmd.cmd = cpu_to_le16(S6245_CMD_EXTCOUNTER);
@ -1031,17 +1022,17 @@ static int get_status(struct shinkos6245_ctx *ctx)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp2),
&num)) < 0) {
sizeof(resp2),
&num, (void*)&resp2)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp2->hdr.payload_len) != (sizeof(struct s6245_getextcounter_resp) - sizeof(struct s6245_status_hdr)))
if (le16_to_cpu(resp2.hdr.payload_len) != (sizeof(struct s6245_getextcounter_resp) - sizeof(struct s6245_status_hdr)))
return 0;
INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2->lifetime_distance));
INFO("Maintenance Distance: %08u inches\n", le32_to_cpu(resp2->maint_distance));
INFO("Head Distance: %08u inches\n", le32_to_cpu(resp2->head_distance));
INFO("Lifetime Distance: %08u inches\n", le32_to_cpu(resp2.lifetime_distance));
INFO("Maintenance Distance: %08u inches\n", le32_to_cpu(resp2.maint_distance));
INFO("Head Distance: %08u inches\n", le32_to_cpu(resp2.head_distance));
return 0;
}
@ -1049,7 +1040,7 @@ static int get_status(struct shinkos6245_ctx *ctx)
static int get_fwinfo(struct shinkos6245_ctx *ctx)
{
struct s6245_fwinfo_cmd cmd;
struct s6245_fwinfo_resp *resp = (struct s6245_fwinfo_resp *)rdbuf;
struct s6245_fwinfo_resp resp;
int num = 0;
int i;
@ -1064,23 +1055,23 @@ static int get_fwinfo(struct shinkos6245_ctx *ctx)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret);
continue;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_fwinfo_resp) - sizeof(struct s6245_status_hdr)))
if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_fwinfo_resp) - sizeof(struct s6245_status_hdr)))
continue;
INFO(" %s\t ver %02x.%02x\n", fwinfo_targets(i),
resp->major, resp->minor);
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));
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
}
return 0;
@ -1089,7 +1080,7 @@ static int get_fwinfo(struct shinkos6245_ctx *ctx)
static int get_errorlog(struct shinkos6245_ctx *ctx)
{
struct s6245_errorlog_cmd cmd;
struct s6245_errorlog_resp *resp = (struct s6245_errorlog_resp *) rdbuf;
struct s6245_errorlog_resp resp;
int num = 0;
int i = 0;
@ -1102,50 +1093,33 @@ static int get_errorlog(struct shinkos6245_ctx *ctx)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret);
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_errorlog_resp) - sizeof(struct s6245_status_hdr)))
if (le16_to_cpu(resp.hdr.payload_len) != (sizeof(struct s6245_errorlog_resp) - sizeof(struct s6245_status_hdr)))
return -2;
INFO("Stored Error ID %d:\n", i);
INFO(" %04d-%02u-%02u %02u:%02u:%02u @ %08u prints : 0x%02x/0x%02x (%s)\n",
resp->time_year + 2000, resp->time_month, resp->time_day,
resp->time_hour, resp->time_min, resp->time_sec,
le32_to_cpu(resp->print_counter),
resp->error_major, resp->error_minor,
error_codes(resp->error_major, resp->error_minor));
resp.time_year + 2000, resp.time_month, resp.time_day,
resp.time_hour, resp.time_min, resp.time_sec,
le32_to_cpu(resp.print_counter),
resp.error_major, resp.error_minor,
error_codes(resp.error_major, resp.error_minor));
INFO(" Temp: %02u/%02u Hum: %02u\n",
resp->printer_thermistor, resp->head_thermistor, resp->printer_humidity);
} while (++i < le16_to_cpu(resp->error_count));
resp.printer_thermistor, resp.head_thermistor, resp.printer_humidity);
} while (++i < le16_to_cpu(resp.error_count));
return 0;
}
static int get_mediainfo(struct shinkos6245_ctx *ctx)
static void dump_mediainfo(struct s6245_mediainfo_resp *resp)
{
struct s6245_cmd_hdr cmd;
struct s6245_mediainfo_resp *resp = (struct s6245_mediainfo_resp *) rdbuf;
int ret, num = 0;
int i;
cmd.cmd = cpu_to_le16(S6245_CMD_MEDIAINFO);
cmd.len = cpu_to_le16(0);
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
if (le16_to_cpu(resp->hdr.payload_len) != (sizeof(struct s6245_mediainfo_resp) - sizeof(struct s6245_status_hdr)))
return -2;
INFO("Loaded Media Type: %s\n", ribbon_sizes(resp->ribbon_code));
INFO("Supported Media Information: %u entries:\n", resp->count);
for (i = 0 ; i < resp->count ; i++) {
@ -1155,13 +1129,12 @@ static int get_mediainfo(struct shinkos6245_ctx *ctx)
le16_to_cpu(resp->items[i].rows),
resp->items[i].print_method, print_methods(resp->items[i].print_method));
}
return 0;
}
static int cancel_job(struct shinkos6245_ctx *ctx, char *str)
{
struct s6245_cancel_cmd cmd;
struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf;
struct s6245_status_hdr resp;
int ret, num = 0;
if (!str)
@ -1174,8 +1147,8 @@ static int cancel_job(struct shinkos6245_ctx *ctx, char *str)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd));
return ret;
}
@ -1186,7 +1159,7 @@ static int cancel_job(struct shinkos6245_ctx *ctx, char *str)
static int flash_led(struct shinkos6245_ctx *ctx)
{
struct s6245_cmd_hdr cmd;
struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf;
struct s6245_status_hdr resp;
int ret, num = 0;
cmd.cmd = cpu_to_le16(S6245_CMD_FLASHLED);
@ -1194,8 +1167,8 @@ static int flash_led(struct shinkos6245_ctx *ctx)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
@ -1207,7 +1180,7 @@ static int flash_led(struct shinkos6245_ctx *ctx)
static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param)
{
struct s6245_setparam_cmd cmd;
struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf;
struct s6245_status_hdr resp;
int ret, num = 0;
/* Set up command */
@ -1219,8 +1192,8 @@ static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command (%d)\n", cmd_names(cmd.hdr.cmd), ret);
}
@ -1230,7 +1203,7 @@ static int set_param(struct shinkos6245_ctx *ctx, int target, uint32_t param)
static int reset_curve(struct shinkos6245_ctx *ctx, int target)
{
struct s6245_reset_cmd cmd;
struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf;
struct s6245_status_hdr resp;
int ret, num = 0;
cmd.target = target;
@ -1240,8 +1213,8 @@ static int reset_curve(struct shinkos6245_ctx *ctx, int target)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd));
return ret;
}
@ -1251,8 +1224,8 @@ static int reset_curve(struct shinkos6245_ctx *ctx, int target)
static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname)
{
struct s6245_readtone_cmd cmd;
struct s6245_readtone_resp *resp = (struct s6245_readtone_resp *) rdbuf;
struct s6245_readtone_cmd cmd;
struct s6245_readtone_resp resp;
int ret, num = 0;
uint8_t *data;
@ -1270,25 +1243,25 @@ static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd));
return ret;
}
resp->total_size = le16_to_cpu(resp->total_size);
resp.total_size = le16_to_cpu(resp.total_size);
data = malloc(resp->total_size * 2);
data = malloc(resp.total_size * 2);
if (!data) {
ERROR("Memory Allocation Failure!\n");
return -1;
}
i = 0;
while (i < resp->total_size) {
while (i < resp.total_size) {
ret = read_data(ctx->dev, ctx->endp_up,
data + i,
resp->total_size * 2 - i,
resp.total_size * 2 - i,
&num);
if (ret < 0)
goto done;
@ -1296,7 +1269,7 @@ static int get_tonecurve(struct shinkos6245_ctx *ctx, int type, char *fname)
}
i = j = 0;
while (i < resp->total_size) {
while (i < resp.total_size) {
memcpy(curves + j, data + i+2, data[i+1]);
j += data[i+1] / 2;
i += data[i+1] + 2;
@ -1326,7 +1299,7 @@ done:
static int set_tonecurve(struct shinkos6245_ctx *ctx, int target, char *fname)
{
struct s6245_update_cmd cmd;
struct s6245_status_hdr *resp = (struct s6245_status_hdr *) rdbuf;
struct s6245_status_hdr resp;
int ret, num = 0;
INFO("Set %s Tone Curve from '%s'\n", update_targets(target), fname);
@ -1369,8 +1342,8 @@ static int set_tonecurve(struct shinkos6245_ctx *ctx, int target, char *fname)
if ((ret = s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.hdr.cmd));
goto done;
}
@ -1457,7 +1430,7 @@ int shinkos6245_cmdline_arg(void *vctx, int argc, char **argv)
j = set_tonecurve(ctx, TONECURVE_CURRENT, optarg);
break;
case 'm':
j = get_mediainfo(ctx);
dump_mediainfo(&ctx->media);
break;
case 'r':
j = reset_curve(ctx, RESET_TONE_CURVE);
@ -1499,6 +1472,10 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev,
struct shinkos6245_ctx *ctx = vctx;
struct libusb_device *device;
struct libusb_device_descriptor desc;
struct s6245_cmd_hdr cmd;
struct s6245_status_resp status;
int num;
ctx->dev = dev;
ctx->endp_up = endp_up;
@ -1515,10 +1492,32 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev,
if (!ctx->jobid)
ctx->jobid++;
/* Initialize donor */
ctx->last_donor = ctx->last_remain = 65535;
/* Query Media */
cmd.cmd = cpu_to_le16(S6245_CMD_MEDIAINFO);
cmd.len = cpu_to_le16(0);
if (s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(ctx->media),
&num, (void*)&ctx->media)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
/* Query Status */
if (s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(status),
&num, (void*)&status)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
ctx->marker.color = "#00FFFF#FF00FF#FFFF00";
ctx->marker.name = ribbon_sizes(ctx->media.ribbon_code);
ctx->marker.levelmax = ribbon_counts(ctx->media.ribbon_code);
ctx->marker.levelnow = ctx->marker.levelmax - le32_to_cpu(status.count_ribbon_left);
// TODO: Query & Update Marker
return CUPS_BACKEND_OK;
}
@ -1618,15 +1617,14 @@ static int shinkos6245_main_loop(void *vctx, int copies) {
int ret, num;
uint8_t cmdbuf[CMDBUF_LEN];
uint8_t rdbuf2[READBACK_LEN];
int i, last_state = -1, state = S_IDLE;
uint8_t mcut;
struct s6245_cmd_hdr *cmd = (struct s6245_cmd_hdr *) cmdbuf;;
struct s6245_print_cmd *print = (struct s6245_print_cmd *) cmdbuf;
struct s6245_status_resp *sts = (struct s6245_status_resp *) rdbuf;
struct s6245_mediainfo_resp *media = (struct s6245_mediainfo_resp *) rdbuf;
struct s6245_status_resp sts, sts2;
struct s6245_status_hdr resp;
/* Cap copies */
// XXX 120 for 8x10 media, 100 for 8x12 media (S6245)
@ -1649,34 +1647,17 @@ static int shinkos6245_main_loop(void *vctx, int copies) {
}
// XXX what about mcut |= PRINT_METHOD_DISABLE_ERR;
/* Send Media Query */
memset(cmdbuf, 0, CMDBUF_LEN);
cmd->cmd = cpu_to_le16(S6245_CMD_MEDIAINFO);
cmd->len = cpu_to_le16(0);
if ((ret = s6245_do_cmd(ctx,
cmdbuf, sizeof(*cmd),
sizeof(*media),
&num)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd));
return CUPS_BACKEND_FAILED;
}
if (le16_to_cpu(media->hdr.payload_len) != (sizeof(struct s6245_mediainfo_resp) - sizeof(struct s6245_status_hdr)))
return CUPS_BACKEND_FAILED;
/* Validate print sizes */
for (i = 0; i < media->count ; i++) {
for (i = 0; i < ctx->media.count ; i++) {
/* Look for matching media */
if (le16_to_cpu(media->items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) &&
le16_to_cpu(media->items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)))
if (le16_to_cpu(ctx->media.items[i].columns) == cpu_to_le16(le32_to_cpu(ctx->hdr.columns)) &&
le16_to_cpu(ctx->media.items[i].rows) == cpu_to_le16(le32_to_cpu(ctx->hdr.rows)))
break;
}
if (i == media->count) {
if (i == ctx->media.count) {
ERROR("Incorrect media loaded for print!\n");
return CUPS_BACKEND_HOLD;
}
ctx->ribbon_code = media->ribbon_code;
/* Send Set Time */
{
@ -1698,21 +1679,14 @@ static int shinkos6245_main_loop(void *vctx, int copies) {
if ((ret = s6245_do_cmd(ctx,
cmdbuf, sizeof(*stime),
sizeof(struct s6245_status_hdr),
&num)) < 0) {
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(stime->hdr.cmd));
return CUPS_BACKEND_FAILED;
}
if (sts->hdr.result != RESULT_SUCCESS)
if (resp.result != RESULT_SUCCESS)
goto printer_error;
}
/* Tell CUPS about the consumables we report */
ATTR("marker-colors=#00FFFF#FF00FF#FFFF00\n");
ATTR("marker-high-levels=100\n");
ATTR("marker-low-levels=10\n");
ATTR("marker-names='%s'\n", ribbon_sizes(ctx->ribbon_code));
ATTR("marker-types=ribbonWax\n");
// XXX check copies against remaining media!
top:
@ -1728,35 +1702,26 @@ top:
if ((ret = s6245_do_cmd(ctx,
cmdbuf, sizeof(*cmd),
sizeof(struct s6245_status_hdr),
&num)) < 0) {
sizeof(sts),
&num, (void*)&sts)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd->cmd));
return CUPS_BACKEND_FAILED;
}
if (memcmp(rdbuf, rdbuf2, READBACK_LEN)) {
uint16_t donor, remain;
memcpy(rdbuf2, rdbuf, READBACK_LEN);
if (memcmp(&sts2, &sts, sizeof(sts))) {
memcpy(&sts2, &sts, sizeof(sts));
INFO("Printer Status: 0x%02x (%s)\n",
sts->hdr.status, status_str(sts->hdr.status));
sts.hdr.status, status_str(sts.hdr.status));
/* Guessimate a percentage for the remaining media */
donor = le32_to_cpu(sts->count_ribbon_left) * 100 / ribbon_counts(ctx->ribbon_code);
if (donor != ctx->last_donor) {
ctx->last_donor = donor;
ATTR("marker-levels=%d\n", donor);
}
remain = le32_to_cpu(sts->count_ribbon_left);
if (remain != ctx->last_remain) {
ctx->last_remain = remain;
ATTR("marker-message=\"%d prints remaining on '%s' ribbon\"\n", remain, ribbon_sizes(ctx->ribbon_code));
if (ctx->marker.levelnow != (int)sts.count_ribbon_left) {
ctx->marker.levelnow = sts.count_ribbon_left;
dump_markers(&ctx->marker, 1, 0);
}
if (sts->hdr.result != RESULT_SUCCESS)
if (sts.hdr.result != RESULT_SUCCESS)
goto printer_error;
if (sts->hdr.error == ERROR_PRINTER)
if (sts.hdr.error == ERROR_PRINTER)
goto printer_error;
} else if (state == last_state) {
sleep(1);
@ -1772,8 +1737,8 @@ top:
/* make sure we're not colliding with an existing
jobid */
while (ctx->jobid == sts->bank1_printid ||
ctx->jobid == sts->bank2_printid) {
while (ctx->jobid == sts.bank1_printid ||
ctx->jobid == sts.bank2_printid) {
ctx->jobid++;
ctx->jobid &= 0x7f;
if (!ctx->jobid)
@ -1781,8 +1746,8 @@ top:
}
/* If either bank is free, continue */
if (sts->bank1_status == BANK_STATUS_FREE ||
sts->bank2_status == BANK_STATUS_FREE)
if (sts.bank1_status == BANK_STATUS_FREE ||
sts.bank2_status == BANK_STATUS_FREE)
state = S_PRINTER_READY_CMD;
break;
@ -1804,20 +1769,20 @@ top:
if ((ret = s6245_do_cmd(ctx,
cmdbuf, sizeof(*print),
sizeof(struct s6245_status_hdr),
&num)) < 0) {
sizeof(resp),
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(print->hdr.cmd));
return ret;
}
if (sts->hdr.result != RESULT_SUCCESS) {
if (sts->hdr.error == ERROR_BUFFER_FULL) {
if (resp.result != RESULT_SUCCESS) {
if (resp.error == ERROR_BUFFER_FULL) {
INFO("Printer Buffers full, retrying\n");
break;
} else if ((sts->hdr.status & 0xf0) == 0x30 || sts->hdr.status == 0x21) {
INFO("Printer busy (%s), retrying\n", status_str(sts->hdr.status));
} else if ((resp.status & 0xf0) == 0x30 || sts.hdr.status == 0x21) {
INFO("Printer busy (%s), retrying\n", status_str(sts.hdr.status));
break;
} else if (sts->hdr.status != ERROR_NONE)
} else if (resp.status != ERROR_NONE)
goto printer_error;
}
@ -1834,7 +1799,7 @@ top:
if (fast_return) {
INFO("Fast return mode enabled.\n");
state = S_FINISHED;
} else if (sts->hdr.status == STATUS_READY) {
} else if (sts.hdr.status == STATUS_READY) {
state = S_FINISHED;
}
break;
@ -1851,19 +1816,19 @@ top:
printer_error:
ERROR("Printer reported error: %#x (%s) status: %#x (%s) -> %#x.%#x (%s)\n",
sts->hdr.error,
error_str(sts->hdr.error),
sts->hdr.status,
status_str(sts->hdr.status),
sts->hdr.printer_major, sts->hdr.printer_minor,
error_codes(sts->hdr.printer_major, sts->hdr.printer_minor));
sts.hdr.error,
error_str(sts.hdr.error),
sts.hdr.status,
status_str(sts.hdr.status),
sts.hdr.printer_major, sts.hdr.printer_minor,
error_codes(sts.hdr.printer_major, sts.hdr.printer_minor));
return CUPS_BACKEND_FAILED;
}
static int shinkos6245_query_serno(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, char *buf, int buf_len)
{
struct s6245_cmd_hdr cmd;
struct s6245_getserial_resp *resp = (struct s6245_getserial_resp*) rdbuf;
struct s6245_getserial_resp resp;
int ret, num = 0;
struct shinkos6245_ctx ctx = {
@ -1877,23 +1842,50 @@ static int shinkos6245_query_serno(struct libusb_device_handle *dev, uint8_t end
if ((ret = s6245_do_cmd(&ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(*resp) - 1,
&num)) < 0) {
sizeof(resp) - 1,
&num, (void*)&resp)) < 0) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return ret;
}
/* Null-terminate */
resp->hdr.payload_len = le16_to_cpu(resp->hdr.payload_len);
if (resp->hdr.payload_len > 23)
resp->hdr.payload_len = 23;
resp->data[resp->hdr.payload_len] = 0;
strncpy(buf, (char*)resp->data, buf_len);
resp.hdr.payload_len = le16_to_cpu(resp.hdr.payload_len);
if (resp.hdr.payload_len > 23)
resp.hdr.payload_len = 23;
resp.data[resp.hdr.payload_len] = 0;
strncpy(buf, (char*)resp.data, buf_len);
buf[buf_len-1] = 0; /* ensure it's null terminated */
return CUPS_BACKEND_OK;
}
static int shinkos6245_query_markers(void *vctx, struct marker **markers, int *count)
{
struct shinkos6245_ctx *ctx = vctx;
struct s6245_cmd_hdr cmd;
struct s6245_status_resp status;
int num;
/* Query Status */
cmd.cmd = cpu_to_le16(S6245_CMD_GETSTATUS);
cmd.len = cpu_to_le16(0);
if (s6245_do_cmd(ctx,
(uint8_t*)&cmd, sizeof(cmd),
sizeof(status),
&num, (void*)&status)) {
ERROR("Failed to execute %s command\n", cmd_names(cmd.cmd));
return CUPS_BACKEND_FAILED;
}
ctx->marker.levelnow = le32_to_cpu(status.count_ribbon_left);
*markers = &ctx->marker;
*count = 1;
return CUPS_BACKEND_OK;
}
/* Exported */
#define USB_VID_SHINKO 0x10CE
#define USB_PID_SHINKO_S6245 0x001D
@ -1907,7 +1899,7 @@ static const char *shinkos6245_prefixes[] = {
struct dyesub_backend shinkos6245_backend = {
.name = "Shinko/Sinfonia CHC-S6245",
.version = "0.09WIP",
.version = "0.10WIP",
.uri_prefixes = shinkos6245_prefixes,
.cmdline_usage = shinkos6245_cmdline,
.cmdline_arg = shinkos6245_cmdline_arg,
@ -1917,6 +1909,7 @@ struct dyesub_backend shinkos6245_backend = {
.read_parse = shinkos6245_read_parse,
.main_loop = shinkos6245_main_loop,
.query_serno = shinkos6245_query_serno,
.query_markers = shinkos6245_query_markers,
.devices = {
{ USB_VID_SHINKO, USB_PID_SHINKO_S6245, P_SHINKO_S6245, NULL, "shinkos6245"},
{ USB_VID_HITI, USB_PID_HITI_P910L, P_SHINKO_S6245, NULL, "hitip910"},