kodak: Add preliminary support for Kodak 7000-series, 8810, and 6900
6900 in particular is _very_ preliminary. Also unifies some more common sinfonia code.
This commit is contained in:
parent
4e8665a029
commit
d39238255d
11
README
11
README
|
@ -452,13 +452,14 @@
|
||||||
|
|
||||||
Additional model IDs recognized:
|
Additional model IDs recognized:
|
||||||
|
|
||||||
kodak-605
|
kodak-605, kodak-7000, kodak-7010, kodak-7015,
|
||||||
|
kodak-701x, kodak-7xxx
|
||||||
|
|
||||||
Verified supported printers:
|
Verified supported printers:
|
||||||
|
|
||||||
Kodak 605
|
Kodak 605
|
||||||
|
|
||||||
Unsupported printers (Unknown VID/PID):
|
Work-in-progress printers:
|
||||||
|
|
||||||
Kodak 7000/7010/7015
|
Kodak 7000/7010/7015
|
||||||
|
|
||||||
|
@ -687,6 +688,7 @@
|
||||||
Model IDs recognized:
|
Model IDs recognized:
|
||||||
|
|
||||||
sinfonia-chcs6245 hiti-p910l shinko-chcs6245
|
sinfonia-chcs6245 hiti-p910l shinko-chcs6245
|
||||||
|
kodak-8810
|
||||||
|
|
||||||
Model IDs for backwards compatibility with older releases:
|
Model IDs for backwards compatibility with older releases:
|
||||||
|
|
||||||
|
@ -695,11 +697,8 @@
|
||||||
Work-in-process printers:
|
Work-in-process printers:
|
||||||
|
|
||||||
HiTi P910L
|
HiTi P910L
|
||||||
Shinko CHC-S6245 (aka "Sinfonia CE1")
|
|
||||||
|
|
||||||
Unsupported printers (Unknown VID/PID):
|
|
||||||
|
|
||||||
Kodak 8810
|
Kodak 8810
|
||||||
|
Shinko CHC-S6245 (aka "Sinfonia CE1")
|
||||||
|
|
||||||
Valid commands:
|
Valid commands:
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,10 @@ enum {
|
||||||
P_SONY_UPD898 = 46,
|
P_SONY_UPD898 = 46,
|
||||||
P_SONY_UPCR20L = 47,
|
P_SONY_UPCR20L = 47,
|
||||||
P_SONY_UPDR80 = 48,
|
P_SONY_UPDR80 = 48,
|
||||||
|
P_KODAK_8810 = 49,
|
||||||
|
P_KODAK_7000 = 50,
|
||||||
|
P_KODAK_701X = 51,
|
||||||
|
P_KODAK_6900 = 52,
|
||||||
P_END,
|
P_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@
|
||||||
|
|
||||||
#define USB_VID_KODAK 0x040A
|
#define USB_VID_KODAK 0x040A
|
||||||
#define USB_PID_KODAK_605 0x402E
|
#define USB_PID_KODAK_605 0x402E
|
||||||
|
#define USB_PID_KODAK_7000 0x4035
|
||||||
|
#define USB_PID_KODAK_701X 0x4037
|
||||||
|
|
||||||
/* List of confirmed commands */
|
/* List of confirmed commands */
|
||||||
//#define SINFONIA_CMD_GETSTATUS 0x0001
|
//#define SINFONIA_CMD_GETSTATUS 0x0001
|
||||||
|
@ -87,30 +89,13 @@ struct kodak605_status {
|
||||||
/*@57*/ uint16_t complete; /* in current job */
|
/*@57*/ uint16_t complete; /* in current job */
|
||||||
/*@59*/ uint16_t total; /* in current job */
|
/*@59*/ uint16_t total; /* in current job */
|
||||||
/*@61*/ uint8_t null_2[9]; /* 00 00 00 00 00 00 00 00 00 */
|
/*@61*/ uint8_t null_2[9]; /* 00 00 00 00 00 00 00 00 00 */
|
||||||
/*@70*/ uint8_t unk_12[6]; /* 01 00 00 00 00 00 */
|
/*@70*/ uint8_t unk_12[6]; /* 01 00 00 00 00 00 (605) 01 01 01 01 00 00 (EK7000) */
|
||||||
} __attribute__((packed));
|
/*@76*/ uint8_t unk_13[1]; // EK7000-series only?
|
||||||
|
|
||||||
/* File header */
|
|
||||||
struct kodak605_hdr {
|
|
||||||
uint8_t hdr[4]; /* 01 40 0a 00 */
|
|
||||||
uint8_t jobid;
|
|
||||||
uint16_t copies; /* LE, 0x0001 or more */
|
|
||||||
uint16_t columns; /* LE, always 0x0734 */
|
|
||||||
uint16_t rows; /* LE */
|
|
||||||
uint8_t media; /* 0x03 for 6x8, 0x01 for 6x4 */
|
|
||||||
uint8_t laminate; /* 0x02 to laminate, 0x01 for not */
|
|
||||||
uint8_t mode; /* Print mode -- 0x00, 0x01 seen */
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define CMDBUF_LEN 4
|
#define CMDBUF_LEN 4
|
||||||
|
|
||||||
/* Private data structure */
|
/* Private data structure */
|
||||||
struct kodak605_printjob {
|
|
||||||
struct kodak605_hdr hdr;
|
|
||||||
uint8_t *databuf;
|
|
||||||
int datalen;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct kodak605_ctx {
|
struct kodak605_ctx {
|
||||||
struct libusb_device_handle *dev;
|
struct libusb_device_handle *dev;
|
||||||
uint8_t endp_up;
|
uint8_t endp_up;
|
||||||
|
@ -121,7 +106,6 @@ struct kodak605_ctx {
|
||||||
struct kodak605_media_list *media;
|
struct kodak605_media_list *media;
|
||||||
|
|
||||||
struct marker marker;
|
struct marker marker;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_list *media)
|
static int kodak605_get_media(struct kodak605_ctx *ctx, struct kodak605_media_list *media)
|
||||||
|
@ -243,16 +227,6 @@ static int kodak605_attach(void *vctx, struct libusb_device_handle *dev, int typ
|
||||||
return CUPS_BACKEND_OK;
|
return CUPS_BACKEND_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kodak605_cleanup_job(const void *vjob)
|
|
||||||
{
|
|
||||||
const struct kodak605_printjob *job = vjob;
|
|
||||||
|
|
||||||
if (job->databuf)
|
|
||||||
free(job->databuf);
|
|
||||||
|
|
||||||
free((void*)job);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kodak605_teardown(void *vctx) {
|
static void kodak605_teardown(void *vctx) {
|
||||||
struct kodak605_ctx *ctx = vctx;
|
struct kodak605_ctx *ctx = vctx;
|
||||||
|
|
||||||
|
@ -266,7 +240,7 @@ static int kodak605_read_parse(void *vctx, const void **vjob, int data_fd, int c
|
||||||
struct kodak605_ctx *ctx = vctx;
|
struct kodak605_ctx *ctx = vctx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
struct kodak605_printjob *job = NULL;
|
struct sinfonia_printjob *job = NULL;
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return CUPS_BACKEND_CANCEL;
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
@ -278,51 +252,16 @@ static int kodak605_read_parse(void *vctx, const void **vjob, int data_fd, int c
|
||||||
}
|
}
|
||||||
memset(job, 0, sizeof(*job));
|
memset(job, 0, sizeof(*job));
|
||||||
|
|
||||||
/* Read in then validate header */
|
/* Read in header */
|
||||||
ret = read(data_fd, &job->hdr, sizeof(job->hdr));
|
ret = sinfonia_raw10_read_parse(data_fd, job);
|
||||||
if (ret < 0 || ret != sizeof(job->hdr)) {
|
if (ret) {
|
||||||
if (ret == 0)
|
free(job);
|
||||||
return CUPS_BACKEND_CANCEL;
|
return ret;
|
||||||
ERROR("Read failed (%d/%d/%d)\n",
|
|
||||||
ret, 0, (int)sizeof(job->hdr));
|
|
||||||
perror("ERROR: Read failed");
|
|
||||||
return CUPS_BACKEND_CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (job->hdr.hdr[0] != 0x01 ||
|
|
||||||
job->hdr.hdr[1] != 0x40 ||
|
|
||||||
job->hdr.hdr[2] != 0x0a ||
|
|
||||||
job->hdr.hdr[3] != 0x00) {
|
|
||||||
ERROR("Unrecognized data format!\n");
|
|
||||||
return CUPS_BACKEND_CANCEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
job->datalen = le16_to_cpu(job->hdr.rows) * le16_to_cpu(job->hdr.columns) * 3;
|
|
||||||
job->databuf = malloc(job->datalen);
|
|
||||||
if (!job->databuf) {
|
|
||||||
ERROR("Memory allocation failure!\n");
|
|
||||||
return CUPS_BACKEND_RETRY_CURRENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
int remain = job->datalen;
|
|
||||||
uint8_t *ptr = job->databuf;
|
|
||||||
do {
|
|
||||||
ret = read(data_fd, ptr, remain);
|
|
||||||
if (ret < 0) {
|
|
||||||
ERROR("Read failed (%d/%d/%d)\n",
|
|
||||||
ret, remain, job->datalen);
|
|
||||||
perror("ERROR: Read failed");
|
|
||||||
return CUPS_BACKEND_CANCEL;
|
|
||||||
}
|
|
||||||
ptr += ret;
|
|
||||||
remain -= ret;
|
|
||||||
} while (remain);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Printer handles generating copies.. */
|
/* Printer handles generating copies.. */
|
||||||
if (le16_to_cpu(job->hdr.copies) < copies)
|
if (le16_to_cpu(job->jp.copies) < (uint16_t)copies)
|
||||||
job->hdr.copies = cpu_to_le16(copies);
|
job->jp.copies = cpu_to_le16(copies);
|
||||||
|
|
||||||
*vjob = job;
|
*vjob = job;
|
||||||
|
|
||||||
|
@ -336,20 +275,18 @@ static int kodak605_main_loop(void *vctx, const void *vjob) {
|
||||||
|
|
||||||
int num, ret;
|
int num, ret;
|
||||||
|
|
||||||
const struct kodak605_printjob *job = vjob;
|
const struct sinfonia_printjob *job = vjob;
|
||||||
|
struct sinfonia_printcmd10_hdr hdr;
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return CUPS_BACKEND_FAILED;
|
return CUPS_BACKEND_FAILED;
|
||||||
if (!job)
|
if (!job)
|
||||||
return CUPS_BACKEND_FAILED;
|
return CUPS_BACKEND_FAILED;
|
||||||
|
|
||||||
struct kodak605_hdr hdr;
|
|
||||||
memcpy(&hdr, &job->hdr, sizeof(hdr));
|
|
||||||
|
|
||||||
/* Validate against supported media list */
|
/* Validate against supported media list */
|
||||||
for (num = 0 ; num < ctx->media->count; num++) {
|
for (num = 0 ; num < ctx->media->count; num++) {
|
||||||
if (ctx->media->entries[num].rows == hdr.rows &&
|
if (ctx->media->entries[num].rows == job->jp.rows &&
|
||||||
ctx->media->entries[num].columns == hdr.columns)
|
ctx->media->entries[num].columns == job->jp.columns)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (num == ctx->media->count) {
|
if (num == ctx->media->count) {
|
||||||
|
@ -400,6 +337,16 @@ static int kodak605_main_loop(void *vctx, const void *vjob) {
|
||||||
/* Use specified jobid */
|
/* Use specified jobid */
|
||||||
hdr.jobid = ctx->jobid;
|
hdr.jobid = ctx->jobid;
|
||||||
|
|
||||||
|
/* Set up header */
|
||||||
|
hdr.hdr.cmd = cpu_to_le16(SINFONIA_CMD_PRINTJOB);
|
||||||
|
hdr.hdr.len = cpu_to_le16(10);
|
||||||
|
hdr.rows = cpu_to_le16(job->jp.rows);
|
||||||
|
hdr.columns = cpu_to_le16(job->jp.columns);
|
||||||
|
hdr.copies = cpu_to_le16(job->jp.copies);
|
||||||
|
hdr.media = job->jp.media;
|
||||||
|
hdr.oc_mode = job->jp.oc_mode;
|
||||||
|
hdr.method = job->jp.method;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
INFO("Sending image header (internal id %u)\n", ctx->jobid);
|
INFO("Sending image header (internal id %u)\n", ctx->jobid);
|
||||||
if ((ret = send_data(ctx->dev, ctx->endp_down,
|
if ((ret = send_data(ctx->dev, ctx->endp_down,
|
||||||
|
@ -497,10 +444,10 @@ static void kodak605_dump_status(struct kodak605_ctx *ctx, struct kodak605_statu
|
||||||
sinfonia_bank_statuses(sts->b2_sts), sts->b2_id,
|
sinfonia_bank_statuses(sts->b2_sts), sts->b2_id,
|
||||||
le16_to_cpu(sts->b2_complete), le16_to_cpu(sts->b2_total));
|
le16_to_cpu(sts->b2_complete), le16_to_cpu(sts->b2_total));
|
||||||
|
|
||||||
INFO("Lifetime prints : %u\n", be32_to_cpu(sts->ctr_life));
|
INFO("Lifetime prints : %u\n", le32_to_cpu(sts->ctr_life));
|
||||||
INFO("Cutter actuations : %u\n", be32_to_cpu(sts->ctr_cut));
|
INFO("Cutter actuations : %u\n", le32_to_cpu(sts->ctr_cut));
|
||||||
INFO("Head prints : %u\n", be32_to_cpu(sts->ctr_head));
|
INFO("Head prints : %u\n", le32_to_cpu(sts->ctr_head));
|
||||||
INFO("Media prints : %u\n", be32_to_cpu(sts->ctr_media));
|
INFO("Media prints : %u\n", le32_to_cpu(sts->ctr_media));
|
||||||
{
|
{
|
||||||
int max;
|
int max;
|
||||||
|
|
||||||
|
@ -509,13 +456,16 @@ static void kodak605_dump_status(struct kodak605_ctx *ctx, struct kodak605_statu
|
||||||
case KODAK6_MEDIA_6TR2:
|
case KODAK6_MEDIA_6TR2:
|
||||||
max = 375;
|
max = 375;
|
||||||
break;
|
break;
|
||||||
|
case KODAK7_MEDIA_6R:
|
||||||
|
max = 570;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
max = 0;
|
max = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max) {
|
if (max) {
|
||||||
INFO("\t Remaining : %u\n", max - be32_to_cpu(sts->ctr_media));
|
INFO("\t Remaining : %u\n", max - le32_to_cpu(sts->ctr_media));
|
||||||
} else {
|
} else {
|
||||||
INFO("\t Remaining : Unknown\n");
|
INFO("\t Remaining : Unknown\n");
|
||||||
}
|
}
|
||||||
|
@ -752,34 +702,37 @@ static int kodak605_query_markers(void *vctx, struct marker **markers, int *coun
|
||||||
|
|
||||||
static const char *kodak605_prefixes[] = {
|
static const char *kodak605_prefixes[] = {
|
||||||
"kodak605", // Family driver, do NOT nuke.
|
"kodak605", // Family driver, do NOT nuke.
|
||||||
"kodak-605",
|
"kodak-605", "kodak-7000", "kodak-7010", "kodak-7015", "kodak-701x", "kodak-7xxx",
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Exported */
|
/* Exported */
|
||||||
struct dyesub_backend kodak605_backend = {
|
struct dyesub_backend kodak605_backend = {
|
||||||
.name = "Kodak 605",
|
.name = "Kodak 605",
|
||||||
.version = "0.38" " (lib " LIBSINFONIA_VER ")",
|
.version = "0.40" " (lib " LIBSINFONIA_VER ")",
|
||||||
.uri_prefixes = kodak605_prefixes,
|
.uri_prefixes = kodak605_prefixes,
|
||||||
.cmdline_usage = kodak605_cmdline,
|
.cmdline_usage = kodak605_cmdline,
|
||||||
.cmdline_arg = kodak605_cmdline_arg,
|
.cmdline_arg = kodak605_cmdline_arg,
|
||||||
.init = kodak605_init,
|
.init = kodak605_init,
|
||||||
.attach = kodak605_attach,
|
.attach = kodak605_attach,
|
||||||
.teardown = kodak605_teardown,
|
.teardown = kodak605_teardown,
|
||||||
.cleanup_job = kodak605_cleanup_job,
|
.cleanup_job = sinfonia_cleanup_job,
|
||||||
.read_parse = kodak605_read_parse,
|
.read_parse = kodak605_read_parse,
|
||||||
.main_loop = kodak605_main_loop,
|
.main_loop = kodak605_main_loop,
|
||||||
.query_markers = kodak605_query_markers,
|
.query_markers = kodak605_query_markers,
|
||||||
.devices = {
|
.devices = {
|
||||||
{ USB_VID_KODAK, USB_PID_KODAK_605, P_KODAK_605, "Kodak", "kodak-605"},
|
{ USB_VID_KODAK, USB_PID_KODAK_605, P_KODAK_605, "Kodak", "kodak-605"},
|
||||||
|
{ USB_VID_KODAK, USB_PID_KODAK_7000, P_KODAK_7000, "Kodak", "kodak-7000"},
|
||||||
|
{ USB_VID_KODAK, USB_PID_KODAK_701X, P_KODAK_701X, "Kodak", "kodak-701x"},
|
||||||
{ 0, 0, 0, NULL, NULL}
|
{ 0, 0, 0, NULL, NULL}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Kodak 605 data format
|
/* Kodak 605/70xx data format
|
||||||
|
|
||||||
Spool file consists of 14-byte header followed by plane-interleaved BGR data.
|
Spool file consists of 14-byte header followed by plane-interleaved BGR data.
|
||||||
Native printer resolution is 1844 pixels per row, and 1240 or 2434 rows.
|
Native printer resolution is 1844 pixels per row on all models but 7015,
|
||||||
|
which is 1548 pixels per row.
|
||||||
|
|
||||||
All fields are LITTLE ENDIAN unless otherwise specified
|
All fields are LITTLE ENDIAN unless otherwise specified
|
||||||
|
|
||||||
|
@ -788,15 +741,18 @@ struct dyesub_backend kodak605_backend = {
|
||||||
01 40 0a 00 Fixed header
|
01 40 0a 00 Fixed header
|
||||||
XX Job ID
|
XX Job ID
|
||||||
CC CC Number of copies (1-???)
|
CC CC Number of copies (1-???)
|
||||||
WW WW Number of columns (Fixed at 1844)
|
WW WW Number of columns (Fixed at 1844 or 1548)
|
||||||
HH HH Number of rows (1240 or 2434)
|
HH HH Number of rows
|
||||||
DD 0x01 (4x6) 0x03 (8x6)
|
DD 0x01 (4x6) 0x03 (8x6)
|
||||||
LL Laminate, 0x01 (off) or 0x02 (on)
|
LL Laminate, 0x01/0x02/0x03 (off/on/satin[70xx only])
|
||||||
00 Print Mode (???)
|
00 Print Mode (???)
|
||||||
|
|
||||||
************************************************************************
|
************************************************************************
|
||||||
|
|
||||||
Note: Kodak 605 is actually a Shinko CHC-S1545-5A
|
Note: Kodak 605 is actually a Shinko CHC-S1545-5A
|
||||||
|
Note: Kodak 7000 is actually a Shinko CHC-S1645-5A
|
||||||
|
Note: Kodak 7010 is actually a Shinko CHC-S1645-5B
|
||||||
|
Note: Kodak 7015 is actually a Shinko CHC-S1645-5C
|
||||||
|
|
||||||
************************************************************************
|
************************************************************************
|
||||||
|
|
||||||
|
|
|
@ -999,16 +999,6 @@ static int shinkos1245_attach(void *vctx, struct libusb_device_handle *dev, int
|
||||||
return CUPS_BACKEND_OK;
|
return CUPS_BACKEND_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shinkos1245_cleanup_job(const void *vjob)
|
|
||||||
{
|
|
||||||
const struct sinfonia_printjob *job = vjob;
|
|
||||||
|
|
||||||
if (job->databuf)
|
|
||||||
free(job->databuf);
|
|
||||||
|
|
||||||
free((void*)job);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shinkos1245_teardown(void *vctx) {
|
static void shinkos1245_teardown(void *vctx) {
|
||||||
struct shinkos1245_ctx *ctx = vctx;
|
struct shinkos1245_ctx *ctx = vctx;
|
||||||
|
|
||||||
|
@ -1307,7 +1297,7 @@ struct dyesub_backend shinkos1245_backend = {
|
||||||
.init = shinkos1245_init,
|
.init = shinkos1245_init,
|
||||||
.attach = shinkos1245_attach,
|
.attach = shinkos1245_attach,
|
||||||
.teardown = shinkos1245_teardown,
|
.teardown = shinkos1245_teardown,
|
||||||
.cleanup_job = shinkos1245_cleanup_job,
|
.cleanup_job = sinfonia_cleanup_job,
|
||||||
.read_parse = shinkos1245_read_parse,
|
.read_parse = shinkos1245_read_parse,
|
||||||
.main_loop = shinkos1245_main_loop,
|
.main_loop = shinkos1245_main_loop,
|
||||||
.query_serno = shinkos1245_query_serno,
|
.query_serno = shinkos1245_query_serno,
|
||||||
|
|
|
@ -1059,16 +1059,6 @@ static int shinkos2145_attach(void *vctx, struct libusb_device_handle *dev, int
|
||||||
return CUPS_BACKEND_OK;
|
return CUPS_BACKEND_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shinkos2145_cleanup_job(const void *vjob)
|
|
||||||
{
|
|
||||||
const struct sinfonia_printjob *job = vjob;
|
|
||||||
|
|
||||||
if (job->databuf)
|
|
||||||
free(job->databuf);
|
|
||||||
|
|
||||||
free((void*)job);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shinkos2145_teardown(void *vctx) {
|
static void shinkos2145_teardown(void *vctx) {
|
||||||
struct shinkos2145_ctx *ctx = vctx;
|
struct shinkos2145_ctx *ctx = vctx;
|
||||||
|
|
||||||
|
@ -1361,7 +1351,7 @@ struct dyesub_backend shinkos2145_backend = {
|
||||||
.init = shinkos2145_init,
|
.init = shinkos2145_init,
|
||||||
.attach = shinkos2145_attach,
|
.attach = shinkos2145_attach,
|
||||||
.teardown = shinkos2145_teardown,
|
.teardown = shinkos2145_teardown,
|
||||||
.cleanup_job = shinkos2145_cleanup_job,
|
.cleanup_job = sinfonia_cleanup_job,
|
||||||
.read_parse = shinkos2145_read_parse,
|
.read_parse = shinkos2145_read_parse,
|
||||||
.main_loop = shinkos2145_main_loop,
|
.main_loop = shinkos2145_main_loop,
|
||||||
.query_serno = shinkos2145_query_serno,
|
.query_serno = shinkos2145_query_serno,
|
||||||
|
|
|
@ -1488,16 +1488,6 @@ static int shinkos6145_attach(void *vctx, struct libusb_device_handle *dev, int
|
||||||
return CUPS_BACKEND_OK;
|
return CUPS_BACKEND_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shinkos6145_cleanup_job(const void *vjob)
|
|
||||||
{
|
|
||||||
const struct sinfonia_printjob *job = vjob;
|
|
||||||
|
|
||||||
if (job->databuf)
|
|
||||||
free(job->databuf);
|
|
||||||
|
|
||||||
free((void*)job);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shinkos6145_teardown(void *vctx) {
|
static void shinkos6145_teardown(void *vctx) {
|
||||||
struct shinkos6145_ctx *ctx = vctx;
|
struct shinkos6145_ctx *ctx = vctx;
|
||||||
|
|
||||||
|
@ -1612,11 +1602,14 @@ static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, in
|
||||||
struct shinkos6145_ctx *ctx = vctx;
|
struct shinkos6145_ctx *ctx = vctx;
|
||||||
struct sinfonia_printjob *job = NULL;
|
struct sinfonia_printjob *job = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
int model;
|
||||||
uint8_t input_ymc;
|
uint8_t input_ymc;
|
||||||
|
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return CUPS_BACKEND_FAILED;
|
return CUPS_BACKEND_FAILED;
|
||||||
|
|
||||||
|
model = ctx->type == P_SHINKO_S6145 ? 6145 : 2245;
|
||||||
|
|
||||||
job = malloc(sizeof(*job));
|
job = malloc(sizeof(*job));
|
||||||
if (!job) {
|
if (!job) {
|
||||||
ERROR("Memory allocation failure!\n");
|
ERROR("Memory allocation failure!\n");
|
||||||
|
@ -1625,7 +1618,11 @@ static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, in
|
||||||
memset(job, 0, sizeof(*job));
|
memset(job, 0, sizeof(*job));
|
||||||
|
|
||||||
/* Common read/parse code */
|
/* Common read/parse code */
|
||||||
ret = sinfonia_read_parse(data_fd, 6145, job);
|
if (ctx->type == P_KODAK_6900) {
|
||||||
|
ret = sinfonia_raw10_read_parse(data_fd, job);
|
||||||
|
} else {
|
||||||
|
ret = sinfonia_read_parse(data_fd, model, job);
|
||||||
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
free(job);
|
free(job);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1650,7 +1647,7 @@ static int shinkos6145_read_parse(void *vctx, const void **vjob, int data_fd, in
|
||||||
int i;
|
int i;
|
||||||
if (!databuf3) {
|
if (!databuf3) {
|
||||||
ERROR("Memory allocation failure!\n");
|
ERROR("Memory allocation failure!\n");
|
||||||
shinkos6145_cleanup_job(job);
|
sinfonia_cleanup_job(job);
|
||||||
return CUPS_BACKEND_RETRY_CURRENT;
|
return CUPS_BACKEND_RETRY_CURRENT;
|
||||||
}
|
}
|
||||||
for (i = 0 ; i < planelen ; i++) {
|
for (i = 0 ; i < planelen ; i++) {
|
||||||
|
@ -1997,14 +1994,14 @@ static const char *shinkos6145_prefixes[] = {
|
||||||
|
|
||||||
struct dyesub_backend shinkos6145_backend = {
|
struct dyesub_backend shinkos6145_backend = {
|
||||||
.name = "Shinko/Sinfonia CHC-S6145/CS2",
|
.name = "Shinko/Sinfonia CHC-S6145/CS2",
|
||||||
.version = "0.34" " (lib " LIBSINFONIA_VER ")",
|
.version = "0.35" " (lib " LIBSINFONIA_VER ")",
|
||||||
.uri_prefixes = shinkos6145_prefixes,
|
.uri_prefixes = shinkos6145_prefixes,
|
||||||
.cmdline_usage = shinkos6145_cmdline,
|
.cmdline_usage = shinkos6145_cmdline,
|
||||||
.cmdline_arg = shinkos6145_cmdline_arg,
|
.cmdline_arg = shinkos6145_cmdline_arg,
|
||||||
.init = shinkos6145_init,
|
.init = shinkos6145_init,
|
||||||
.attach = shinkos6145_attach,
|
.attach = shinkos6145_attach,
|
||||||
.teardown = shinkos6145_teardown,
|
.teardown = shinkos6145_teardown,
|
||||||
.cleanup_job = shinkos6145_cleanup_job,
|
.cleanup_job = sinfonia_cleanup_job,
|
||||||
.read_parse = shinkos6145_read_parse,
|
.read_parse = shinkos6145_read_parse,
|
||||||
.main_loop = shinkos6145_main_loop,
|
.main_loop = shinkos6145_main_loop,
|
||||||
.query_serno = shinkos6145_query_serno,
|
.query_serno = shinkos6145_query_serno,
|
||||||
|
|
|
@ -1087,16 +1087,6 @@ static int shinkos6245_attach(void *vctx, struct libusb_device_handle *dev, int
|
||||||
return CUPS_BACKEND_OK;
|
return CUPS_BACKEND_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shinkos6245_cleanup_job(const void *vjob)
|
|
||||||
{
|
|
||||||
const struct sinfonia_printjob *job = vjob;
|
|
||||||
|
|
||||||
if (job->databuf)
|
|
||||||
free(job->databuf);
|
|
||||||
|
|
||||||
free((void*)job);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shinkos6245_teardown(void *vctx) {
|
static void shinkos6245_teardown(void *vctx) {
|
||||||
struct shinkos6245_ctx *ctx = vctx;
|
struct shinkos6245_ctx *ctx = vctx;
|
||||||
|
|
||||||
|
@ -1122,7 +1112,11 @@ static int shinkos6245_read_parse(void *vctx, const void **vjob, int data_fd, in
|
||||||
memset(job, 0, sizeof(*job));
|
memset(job, 0, sizeof(*job));
|
||||||
|
|
||||||
/* Common read/parse code */
|
/* Common read/parse code */
|
||||||
ret = sinfonia_read_parse(data_fd, 6245, job);
|
if (ctx->type == P_KODAK_8810) {
|
||||||
|
ret = sinfonia_raw18_read_parse(data_fd, job);
|
||||||
|
} else {
|
||||||
|
ret = sinfonia_read_parse(data_fd, 6245, job);
|
||||||
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
free(job);
|
free(job);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1417,9 +1411,11 @@ static int shinkos6245_query_markers(void *vctx, struct marker **markers, int *c
|
||||||
#define USB_PID_SHINKO_S6245 0x001D
|
#define USB_PID_SHINKO_S6245 0x001D
|
||||||
#define USB_VID_HITI 0x0D16
|
#define USB_VID_HITI 0x0D16
|
||||||
#define USB_PID_HITI_P910L 0x000E
|
#define USB_PID_HITI_P910L 0x000E
|
||||||
|
#define USB_VID_KODAK 0x040A
|
||||||
|
#define USB_PID_KODAK_8810 0x404D
|
||||||
|
|
||||||
static const char *shinkos6245_prefixes[] = {
|
static const char *shinkos6245_prefixes[] = {
|
||||||
"sinfonia-chcs6245", "hiti-p910l",
|
"sinfonia-chcs6245", "hiti-p910l", "kodak-8810",
|
||||||
// extras
|
// extras
|
||||||
"shinko-chcs6245",
|
"shinko-chcs6245",
|
||||||
// backwards compatibility
|
// backwards compatibility
|
||||||
|
@ -1429,14 +1425,14 @@ static const char *shinkos6245_prefixes[] = {
|
||||||
|
|
||||||
struct dyesub_backend shinkos6245_backend = {
|
struct dyesub_backend shinkos6245_backend = {
|
||||||
.name = "Shinko/Sinfonia CHC-S6245",
|
.name = "Shinko/Sinfonia CHC-S6245",
|
||||||
.version = "0.18WIP" " (lib " LIBSINFONIA_VER ")",
|
.version = "0.19WIP" " (lib " LIBSINFONIA_VER ")",
|
||||||
.uri_prefixes = shinkos6245_prefixes,
|
.uri_prefixes = shinkos6245_prefixes,
|
||||||
.cmdline_usage = shinkos6245_cmdline,
|
.cmdline_usage = shinkos6245_cmdline,
|
||||||
.cmdline_arg = shinkos6245_cmdline_arg,
|
.cmdline_arg = shinkos6245_cmdline_arg,
|
||||||
.init = shinkos6245_init,
|
.init = shinkos6245_init,
|
||||||
.attach = shinkos6245_attach,
|
.attach = shinkos6245_attach,
|
||||||
.teardown = shinkos6245_teardown,
|
.teardown = shinkos6245_teardown,
|
||||||
.cleanup_job = shinkos6245_cleanup_job,
|
.cleanup_job = sinfonia_cleanup_job,
|
||||||
.read_parse = shinkos6245_read_parse,
|
.read_parse = shinkos6245_read_parse,
|
||||||
.main_loop = shinkos6245_main_loop,
|
.main_loop = shinkos6245_main_loop,
|
||||||
.query_serno = shinkos6245_query_serno,
|
.query_serno = shinkos6245_query_serno,
|
||||||
|
@ -1444,6 +1440,7 @@ struct dyesub_backend shinkos6245_backend = {
|
||||||
.devices = {
|
.devices = {
|
||||||
{ USB_VID_SHINKO, USB_PID_SHINKO_S6245, P_SHINKO_S6245, NULL, "shinfonia-chcs6245"},
|
{ USB_VID_SHINKO, USB_PID_SHINKO_S6245, P_SHINKO_S6245, NULL, "shinfonia-chcs6245"},
|
||||||
{ USB_VID_HITI, USB_PID_HITI_P910L, P_SHINKO_S6245, NULL, "hiti-p910l"},
|
{ USB_VID_HITI, USB_PID_HITI_P910L, P_SHINKO_S6245, NULL, "hiti-p910l"},
|
||||||
|
{ USB_VID_KODAK, USB_PID_KODAK_8810, P_KODAK_8810, NULL, "kodak-8810"},
|
||||||
{ 0, 0, 0, NULL, NULL}
|
{ 0, 0, 0, NULL, NULL}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1467,4 +1464,10 @@ struct dyesub_backend shinkos6245_backend = {
|
||||||
|
|
||||||
04 03 02 01 [[ footer ]]
|
04 03 02 01 [[ footer ]]
|
||||||
|
|
||||||
|
Kodak 8810 data format: (Note: EK8810 is actually a Sinfonia CHC-S1845-5A)
|
||||||
|
|
||||||
|
Spool file is the print_cmd_hdr (22 bytes) followed by RGB-packed data.
|
||||||
|
|
||||||
|
NOTE: NOT YET HANDLED by backend.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -150,6 +150,126 @@ int sinfonia_read_parse(int data_fd, uint32_t model,
|
||||||
return CUPS_BACKEND_OK;
|
return CUPS_BACKEND_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sinfonia_raw10_read_parse(int data_fd, struct sinfonia_printjob *job)
|
||||||
|
{
|
||||||
|
struct sinfonia_printcmd10_hdr hdr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Read in header */
|
||||||
|
ret = read(data_fd, &hdr, sizeof(hdr));
|
||||||
|
if (ret < 0 || ret != sizeof(hdr)) {
|
||||||
|
if (ret == 0)
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
ERROR("Read failed (%d/%d/%d)\n",
|
||||||
|
ret, 0, (int)sizeof(hdr));
|
||||||
|
perror("ERROR: Read failed");
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
}
|
||||||
|
/* Validate header */
|
||||||
|
if (le16_to_cpu(hdr.hdr.cmd) != 0x4001 ||
|
||||||
|
le16_to_cpu(hdr.hdr.len) != 10) {
|
||||||
|
ERROR("Unrecognized data format!\n");
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
}
|
||||||
|
job->jp.copies = le16_to_cpu(hdr.copies);
|
||||||
|
job->jp.rows = le16_to_cpu(hdr.rows);
|
||||||
|
job->jp.columns = le16_to_cpu(hdr.columns);
|
||||||
|
job->jp.media = hdr.media;
|
||||||
|
job->jp.oc_mode = hdr.oc_mode;
|
||||||
|
job->jp.method = hdr.method;
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
job->datalen = job->jp.rows * job->jp.columns * 3;
|
||||||
|
job->databuf = malloc(job->datalen);
|
||||||
|
if (!job->databuf) {
|
||||||
|
ERROR("Memory allocation failure!\n");
|
||||||
|
return CUPS_BACKEND_RETRY_CURRENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int remain = job->datalen;
|
||||||
|
uint8_t *ptr = job->databuf;
|
||||||
|
do {
|
||||||
|
ret = read(data_fd, ptr, remain);
|
||||||
|
if (ret < 0) {
|
||||||
|
ERROR("Read failed (%d/%d/%d)\n",
|
||||||
|
ret, remain, job->datalen);
|
||||||
|
perror("ERROR: Read failed");
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
}
|
||||||
|
ptr += ret;
|
||||||
|
remain -= ret;
|
||||||
|
} while (remain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CUPS_BACKEND_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sinfonia_raw18_read_parse(int data_fd, struct sinfonia_printjob *job)
|
||||||
|
{
|
||||||
|
struct sinfonia_printcmd18_hdr hdr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Read in header */
|
||||||
|
ret = read(data_fd, &hdr, sizeof(hdr));
|
||||||
|
if (ret < 0 || ret != sizeof(hdr)) {
|
||||||
|
if (ret == 0)
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
ERROR("Read failed (%d/%d/%d)\n",
|
||||||
|
ret, 0, (int)sizeof(hdr));
|
||||||
|
perror("ERROR: Read failed");
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
}
|
||||||
|
/* Validate header */
|
||||||
|
if (le16_to_cpu(hdr.hdr.cmd) != SINFONIA_CMD_PRINTJOB ||
|
||||||
|
le16_to_cpu(hdr.hdr.len) != 18) {
|
||||||
|
ERROR("Unrecognized data format!\n");
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
}
|
||||||
|
job->jp.copies = le16_to_cpu(hdr.copies);
|
||||||
|
job->jp.rows = le16_to_cpu(hdr.rows);
|
||||||
|
job->jp.columns = le16_to_cpu(hdr.columns);
|
||||||
|
job->jp.media = hdr.media;
|
||||||
|
job->jp.oc_mode = hdr.oc_mode;
|
||||||
|
job->jp.method = hdr.method;
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
job->datalen = job->jp.rows * job->jp.columns * 3;
|
||||||
|
job->databuf = malloc(job->datalen);
|
||||||
|
if (!job->databuf) {
|
||||||
|
ERROR("Memory allocation failure!\n");
|
||||||
|
return CUPS_BACKEND_RETRY_CURRENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int remain = job->datalen;
|
||||||
|
uint8_t *ptr = job->databuf;
|
||||||
|
do {
|
||||||
|
ret = read(data_fd, ptr, remain);
|
||||||
|
if (ret < 0) {
|
||||||
|
ERROR("Read failed (%d/%d/%d)\n",
|
||||||
|
ret, remain, job->datalen);
|
||||||
|
perror("ERROR: Read failed");
|
||||||
|
return CUPS_BACKEND_CANCEL;
|
||||||
|
}
|
||||||
|
ptr += ret;
|
||||||
|
remain -= ret;
|
||||||
|
} while (remain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CUPS_BACKEND_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sinfonia_cleanup_job(const void *vjob)
|
||||||
|
{
|
||||||
|
const struct sinfonia_printjob *job = vjob;
|
||||||
|
|
||||||
|
if (job->databuf)
|
||||||
|
free(job->databuf);
|
||||||
|
|
||||||
|
free((void*)job);
|
||||||
|
}
|
||||||
|
|
||||||
const char *sinfonia_update_targets (uint8_t v) {
|
const char *sinfonia_update_targets (uint8_t v) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case UPDATE_TARGET_USER:
|
case UPDATE_TARGET_USER:
|
||||||
|
@ -413,7 +533,9 @@ const char *kodak6_mediatypes(int type)
|
||||||
return "No media";
|
return "No media";
|
||||||
case KODAK6_MEDIA_6R:
|
case KODAK6_MEDIA_6R:
|
||||||
case KODAK6_MEDIA_6TR2:
|
case KODAK6_MEDIA_6TR2:
|
||||||
|
case KODAK7_MEDIA_6R:
|
||||||
return "Kodak 6R";
|
return "Kodak 6R";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LIBSINFONIA_VER "0.1"
|
#define LIBSINFONIA_VER "0.02"
|
||||||
|
|
||||||
#define SINFONIA_HDR1_LEN 0x10
|
#define SINFONIA_HDR1_LEN 0x10
|
||||||
#define SINFONIA_HDR2_LEN 0x64
|
#define SINFONIA_HDR2_LEN 0x64
|
||||||
|
@ -62,6 +62,10 @@ struct sinfonia_printjob {
|
||||||
int sinfonia_read_parse(int data_fd, uint32_t model,
|
int sinfonia_read_parse(int data_fd, uint32_t model,
|
||||||
struct sinfonia_printjob *job);
|
struct sinfonia_printjob *job);
|
||||||
|
|
||||||
|
int sinfonia_raw10_read_parse(int data_fd, struct sinfonia_printjob *job);
|
||||||
|
int sinfonia_raw18_read_parse(int data_fd, struct sinfonia_printjob *job);
|
||||||
|
void sinfonia_cleanup_job(const void *vjob);
|
||||||
|
|
||||||
#define BANK_STATUS_FREE 0x00
|
#define BANK_STATUS_FREE 0x00
|
||||||
#define BANK_STATUS_XFER 0x01
|
#define BANK_STATUS_XFER 0x01
|
||||||
#define BANK_STATUS_FULL 0x02
|
#define BANK_STATUS_FULL 0x02
|
||||||
|
@ -226,6 +230,28 @@ struct sinfonia_seteeprom_cmd {
|
||||||
uint8_t data[256]; /* Maxlen */
|
uint8_t data[256]; /* Maxlen */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct sinfonia_printcmd10_hdr {
|
||||||
|
struct sinfonia_cmd_hdr hdr;
|
||||||
|
uint8_t jobid;
|
||||||
|
uint16_t copies;
|
||||||
|
uint16_t columns;
|
||||||
|
uint16_t rows;
|
||||||
|
uint8_t media;
|
||||||
|
uint8_t oc_mode;
|
||||||
|
uint8_t method;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct sinfonia_printcmd18_hdr {
|
||||||
|
struct sinfonia_cmd_hdr hdr;
|
||||||
|
uint8_t jobid;
|
||||||
|
uint16_t copies;
|
||||||
|
uint16_t columns;
|
||||||
|
uint16_t rows;
|
||||||
|
uint8_t media;
|
||||||
|
uint8_t oc_mode;
|
||||||
|
uint8_t method;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
#define CODE_4x6 0x00
|
#define CODE_4x6 0x00
|
||||||
#define CODE_3_5x5 0x01
|
#define CODE_3_5x5 0x01
|
||||||
#define CODE_5x7 0x03
|
#define CODE_5x7 0x03
|
||||||
|
@ -316,6 +342,7 @@ const char *sinfonia_cmd_names(uint16_t v);
|
||||||
#define KODAK6_MEDIA_UNK 0x03
|
#define KODAK6_MEDIA_UNK 0x03
|
||||||
#define KODAK6_MEDIA_6TR2 0x2c // 396-2941
|
#define KODAK6_MEDIA_6TR2 0x2c // 396-2941
|
||||||
#define KODAK6_MEDIA_NONE 0x00
|
#define KODAK6_MEDIA_NONE 0x00
|
||||||
|
#define KODAK7_MEDIA_6R 0x29
|
||||||
|
|
||||||
const char *kodak6_mediatypes(int type);
|
const char *kodak6_mediatypes(int type);
|
||||||
void kodak6_dumpmediacommon(int type);
|
void kodak6_dumpmediacommon(int type);
|
||||||
|
|
12
blacklist
12
blacklist
|
@ -123,6 +123,18 @@
|
||||||
# Kodak 6850
|
# Kodak 6850
|
||||||
0x040a 0x402b blacklist
|
0x040a 0x402b blacklist
|
||||||
|
|
||||||
|
# Kodak 7000
|
||||||
|
0x040a 0x4035 blacklist
|
||||||
|
|
||||||
|
# Kodak 7010/7015
|
||||||
|
0x040a 0x4037 blacklist
|
||||||
|
|
||||||
|
# Kodak 8800/9810
|
||||||
|
0x040a 0x4023 blacklist
|
||||||
|
|
||||||
|
# Kodak 8810
|
||||||
|
0x040a 0x404d blacklist
|
||||||
|
|
||||||
# Kodak 605
|
# Kodak 605
|
||||||
0x040a 0x402e blacklist
|
0x040a 0x402e blacklist
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,11 @@ kodak-605,0x040a,0x402e,0xb,PageSize=w216h432
|
||||||
kodak-605,0x040a,0x402e,0xb,PageSize=w288h432
|
kodak-605,0x040a,0x402e,0xb,PageSize=w288h432
|
||||||
kodak-605,0x040a,0x402e,0xb,PageSize=w432h576
|
kodak-605,0x040a,0x402e,0xb,PageSize=w432h576
|
||||||
kodak-605,0x040a,0x402e,0x3,PageSize=w360h504
|
kodak-605,0x040a,0x402e,0x3,PageSize=w360h504
|
||||||
|
kodak-7000,0x040a,0x4035,0xb,PageSize=w288h432
|
||||||
|
kodak-7000,0x040a,0x4035,0xb,PageSize=w432h576
|
||||||
|
kodak-7010,0x040a,0x4037,0xb,PageSize=w288h432
|
||||||
|
kodak-7010,0x040a,0x4037,0xb,PageSize=w432h576
|
||||||
|
kodak-7015,0x040a,0x4037,0x3,PageSize=w360h504
|
||||||
#
|
#
|
||||||
shinko-chcs1245,0x10ce,0x0007,0,PageSize=w288h576
|
shinko-chcs1245,0x10ce,0x0007,0,PageSize=w288h576
|
||||||
shinko-chcs1245,0x10ce,0x0007,0,PageSize=w360h576
|
shinko-chcs1245,0x10ce,0x0007,0,PageSize=w360h576
|
||||||
|
|
|
Loading…
Reference in New Issue