s1245: Add media query support, and start fleshing out the main loop.

This commit is contained in:
Solomon Peachy 2015-02-08 19:48:17 -05:00
parent f7d2f6e764
commit 5661725a3b
2 changed files with 192 additions and 25 deletions

1
README
View File

@ -322,6 +322,7 @@
Valid commands:
-s Query printer status
-m Query media information
***************************************************************************
BACKEND=sonyupdr150

View File

@ -41,14 +41,6 @@
#include "backend_common.h"
enum {
S_IDLE = 0,
S_PRINTER_READY_CMD,
S_PRINTER_SENT_DATA,
S_FINISHED,
};
/* Structure of printjob header. All fields are LITTLE ENDIAN */
struct s1245_printjob_hdr {
uint32_t len1; /* Fixed at 0x10 */
@ -89,20 +81,6 @@ struct s1245_printjob_hdr {
uint32_t unk21; /* Null */
} __attribute__((packed));
/* Private data stucture */
struct shinkos1245_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
uint8_t jobid;
uint8_t fast_return;
struct s1245_printjob_hdr hdr;
uint8_t *databuf;
int datalen;
};
/* Printer data structures */
struct shinkos1245_cmd_hdr {
uint8_t prefix; /* 0x03 */
@ -418,6 +396,31 @@ struct shinkos1245_resp_matte {
#define MATTE_MODE_MATTE 0x00
/* Private data stucture */
struct shinkos1245_ctx {
struct libusb_device_handle *dev;
uint8_t endp_up;
uint8_t endp_down;
uint8_t jobid;
uint8_t fast_return;
struct s1245_printjob_hdr hdr;
struct shinkos1245_mediadesc medias[15];
int num_medias;
uint8_t *databuf;
int datalen;
};
enum {
S_IDLE = 0,
S_PRINTER_READY_CMD,
S_PRINTER_SENT_DATA,
S_FINISHED,
};
/* Basic printer I/O stuffs */
static void shinkos1245_fill_hdr(struct shinkos1245_cmd_hdr *hdr)
{
@ -479,6 +482,46 @@ static int shinkos1245_get_status(struct shinkos1245_ctx *ctx,
return 0;
}
static int shinkos1245_get_media(struct shinkos1245_ctx *ctx)
{
struct shinkos1245_cmd_getmedia cmd;
struct shinkos1245_resp_media resp;
int i, j;
int ret, num;
shinkos1245_fill_hdr(&cmd.hdr);
memset(cmd.pad, 0, sizeof(cmd.pad));
for (i = 1 ; i <= 3 ; i++) {
cmd.cmd[0] = 0x0a || (i << 4);
ret = shinkos1245_do_cmd(ctx, &cmd, sizeof(cmd),
&resp, sizeof(resp), &num);
if (ret < 0) {
ERROR("Failed to execute GET_STATUS command\n");
return ret;
}
if (resp.code != CMD_CODE_OK) {
ERROR("Bad return code on GET_STATUS (%02x)\n",
resp.code);
return -99;
}
/* Store media info */
for (j = 0; j < resp.count ; j++) {
ctx->medias[ctx->num_medias].code = resp.data[j].code;
ctx->medias[ctx->num_medias].columns = be16_to_cpu(resp.data[j].columns);
ctx->medias[ctx->num_medias].rows = be16_to_cpu(resp.data[j].rows);
ctx->medias[ctx->num_medias].type = resp.data[j].type;
ctx->medias[ctx->num_medias].print_type = resp.data[j].print_type;
ctx->num_medias++;
}
if (resp.count < 5)
break;
}
return 0;
}
static void shinkos1245_dump_status(struct shinkos1245_resp_status *sts)
{
char *detail;
@ -600,10 +643,27 @@ static void shinkos1245_dump_status(struct shinkos1245_resp_status *sts)
INFO("Tone Curve Status: %s\n", detail);
}
static void shinkos1245_dump_media(struct shinkos1245_mediadesc *medias,
int count)
{
int i;
INFO("Supported print sizes: %d\n", count);
for (i = 0 ; i < count ; i++) {
INFO("\t %02x: %04d*%04d (%02x/%02d)\n",
medias[i].print_type,
medias[i].columns,
medias[i].rows,
medias[i].code, medias[i].type);
}
}
/* Driver API */
static void shinkos1245_cmdline(void)
{
DEBUG("\t\t[ -m ] # Query media\n");
DEBUG("\t\t[ -s ] # Query status\n");
}
@ -615,8 +675,16 @@ int shinkos1245_cmdline_arg(void *vctx, int argc, char **argv)
/* Reset arg parsing */
optind = 1;
opterr = 0;
while ((i = getopt(argc, argv, "s")) >= 0) {
while ((i = getopt(argc, argv, "ms")) >= 0) {
switch(i) {
case 'm':
if (ctx) {
j = shinkos1245_get_media(ctx);
if (!j)
shinkos1245_dump_media(ctx->medias, ctx->num_medias);
break;
}
return 1;
case 's':
if (ctx) {
struct shinkos1245_resp_status sts;
@ -705,13 +773,23 @@ static int shinkos1245_read_parse(void *vctx, int data_fd) {
return CUPS_BACKEND_CANCEL;
}
/* Finish byteswapping */
ctx->hdr.media = le32_to_cpu(ctx->hdr.media);
ctx->hdr.method = le32_to_cpu(ctx->hdr.method);
ctx->hdr.mode = le32_to_cpu(ctx->hdr.mode);
ctx->hdr.mattedepth = le32_to_cpu(ctx->hdr.mattedepth);
ctx->hdr.dust = le32_to_cpu(ctx->hdr.dust);
ctx->hdr.columns = le32_to_cpu(ctx->hdr.columns);
ctx->hdr.rows = le32_to_cpu(ctx->hdr.rows);
ctx->hdr.copies = le32_to_cpu(ctx->hdr.copies);
/* Allocate space */
if (ctx->databuf) {
free(ctx->databuf);
ctx->databuf = NULL;
}
ctx->datalen = le32_to_cpu(ctx->hdr.rows) * le32_to_cpu(ctx->hdr.columns) * 3;
ctx->datalen = ctx->hdr.rows * ctx->hdr.columns * 3;
ctx->databuf = malloc(ctx->datalen);
if (!ctx->databuf) {
ERROR("Memory allocation failure!\n");
@ -755,7 +833,95 @@ static int shinkos1245_read_parse(void *vctx, int data_fd) {
static int shinkos1245_main_loop(void *vctx, int copies) {
struct shinkos1245_ctx *ctx = vctx;
int i, last_state = -1, state = S_IDLE;
struct shinkos1245_resp_status status1, status2;
// XXX query printer info
/* 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)
break;
if (ctx->hdr.method != ctx->medias[i].print_type)
break;
if (ctx->hdr.rows != ctx->medias[i].rows)
break;
if (ctx->hdr.columns != ctx->medias[i].columns)
break;
}
if (i == ctx->num_medias) {
ERROR("Unsupported print type\n");
return CUPS_BACKEND_HOLD;
}
top:
if (state != last_state) {
if (dyesub_debug)
DEBUG("last_state %d new %d\n", last_state, state);
}
/* Send status query */
i = shinkos1245_get_status(ctx, &status1);
if (i < 0)
return CUPS_BACKEND_FAILED;
if (memcmp(&status1, &status2, sizeof(status1))) {
memcpy(&status2, &status1, sizeof(status1));
// status changed, check for errors and whatnot
} else if (state == last_state) {
sleep(1);
goto top;
}
last_state = state;
fflush(stderr);
switch (state) {
case S_IDLE:
// check to see if printer has free bank, if so, continue
break;
case S_PRINTER_READY_CMD:
// issue a print command, send over data.
break;
case S_PRINTER_SENT_DATA:
if (ctx->fast_return) {
INFO("Fast return mode enabled.\n");
state = S_FINISHED;
}
// check for completion
break;
default:
break;
}
if (state != S_FINISHED)
goto top;
/* This printer handles copies internally */
copies = 1;
/* Clean up */
if (terminate)
copies = 1;
INFO("Print complete (%d copies remaining)\n", copies - 1);
if (copies && --copies) {
state = S_IDLE;
goto top;
}
return CUPS_BACKEND_OK;
printer_error:
return CUPS_BACKEND_FAILED;
}