kopia lustrzana https://gitlab.com/sane-project/backends
Added 2 commands for MP800.
rodzic
653e3c2226
commit
890d2dee95
|
@ -91,9 +91,9 @@ enum mp150_cmd_t
|
||||||
cmd_abort_session = 0xef20,
|
cmd_abort_session = 0xef20,
|
||||||
cmd_time = 0xeb80,
|
cmd_time = 0xeb80,
|
||||||
cmd_read_image = 0xd420,
|
cmd_read_image = 0xd420,
|
||||||
|
cmd_error_info = 0xff20,
|
||||||
|
|
||||||
cmd_error_info = 0xff20, /* seen in MP800 */
|
cmd_e920 = 0xe920 /* seen in MP800 */
|
||||||
cmd_e920 = 0xe920 /* " */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mp150_t
|
typedef struct mp150_t
|
||||||
|
@ -154,7 +154,7 @@ typedef struct mp150_t
|
||||||
result:
|
result:
|
||||||
u16be STAT
|
u16be STAT
|
||||||
u8[6] 0
|
u8[6] 0
|
||||||
u8 block info byte 0x38 = last image data block
|
u8 block info bitfield: 0x8 = end of scan, 0x10 = no more paper, 0x20 = no more data
|
||||||
u8[3] 0
|
u8[3] 0
|
||||||
u32be ILEN image data size
|
u32be ILEN image data size
|
||||||
u8[ILEN] image data
|
u8[ILEN] image data
|
||||||
|
@ -180,8 +180,7 @@ static void
|
||||||
drain_bulk_in (pixma_t * s)
|
drain_bulk_in (pixma_t * s)
|
||||||
{
|
{
|
||||||
mp150_t *mp = (mp150_t *) s->subdriver;
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
while (pixma_read (s->io, mp->imgbuf, IMAGE_BLOCK_SIZE) ==
|
while (pixma_read (s->io, mp->imgbuf, IMAGE_BLOCK_SIZE) >= 0);
|
||||||
IMAGE_BLOCK_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -191,6 +190,13 @@ abort_session (pixma_t * s)
|
||||||
return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session);
|
return pixma_exec_short_cmd (s, &mp->cb, cmd_abort_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
send_cmd_e920 (pixma_t * s)
|
||||||
|
{
|
||||||
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
|
return pixma_exec_short_cmd (s, &mp->cb, cmd_e920);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
start_session (pixma_t * s)
|
start_session (pixma_t * s)
|
||||||
{
|
{
|
||||||
|
@ -227,19 +233,26 @@ send_gamma_table (pixma_t * s)
|
||||||
return pixma_exec (s, &mp->cb);
|
return pixma_exec (s, &mp->cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
calc_raw_width (const pixma_scan_param_t * param)
|
||||||
|
{
|
||||||
|
unsigned raw_width;
|
||||||
|
/* NOTE: Actually, we can send arbitary width to MP150. Lines returned
|
||||||
|
are always padded to multiple of 4 or 12 pixels. Is this valid for
|
||||||
|
other models, too? */
|
||||||
|
if (param->channels == 1)
|
||||||
|
raw_width = ALIGN (param->w, 12);
|
||||||
|
else
|
||||||
|
raw_width = ALIGN (param->w, 4);
|
||||||
|
return raw_width;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_scan_param (pixma_t * s)
|
send_scan_param (pixma_t * s)
|
||||||
{
|
{
|
||||||
mp150_t *mp = (mp150_t *) s->subdriver;
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
unsigned raw_width;
|
unsigned raw_width = calc_raw_width (s->param);
|
||||||
|
|
||||||
/* NOTE: MP150 can cope with "unaligned" width. It always correctly
|
|
||||||
returns padded rows. Can other models do this, too? */
|
|
||||||
if (s->param->channels == 1)
|
|
||||||
raw_width = ALIGN (s->param->w, 12);
|
|
||||||
else
|
|
||||||
raw_width = ALIGN (s->param->w, 4);
|
|
||||||
|
|
||||||
data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x30, 0);
|
data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x30, 0);
|
||||||
pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x04);
|
pixma_set_be16 (s->param->xdpi | 0x8000, data + 0x04);
|
||||||
|
@ -269,9 +282,8 @@ query_status (pixma_t * s)
|
||||||
if (error >= 0)
|
if (error >= 0)
|
||||||
{
|
{
|
||||||
memcpy (mp->current_status, data, 12);
|
memcpy (mp->current_status, data, 12);
|
||||||
PDBG (pixma_dbg (3, "Current status: %s %s\n",
|
PDBG (pixma_dbg (3, "Current status: paper=%u cal=%u lamp=%u busy=%u\n",
|
||||||
is_calibrated (s) ? "Calibrated" : "Calibrating",
|
data[1], data[8], data[7], data[9]));
|
||||||
has_paper (s) ? "HasPaper" : "NoPaper"));
|
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -340,6 +352,27 @@ read_image_block (pixma_t * s, uint8_t * header, uint8_t * data)
|
||||||
return datalen;
|
return datalen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_error_info (pixma_t * s, void *buf, unsigned size)
|
||||||
|
{
|
||||||
|
unsigned len = 16;
|
||||||
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
|
uint8_t *data;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
data = pixma_newcmd (&mp->cb, cmd_error_info, 0, len);
|
||||||
|
error = pixma_exec (s, &mp->cb);
|
||||||
|
if (error >= 0 && buf)
|
||||||
|
{
|
||||||
|
if (len < size)
|
||||||
|
size = len;
|
||||||
|
/* NOTE: I've absolutely no idea what the returned data mean. */
|
||||||
|
memcpy (buf, data, size);
|
||||||
|
error = len;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
handle_interrupt() waits until it receives an interrupt packet or times out.
|
handle_interrupt() waits until it receives an interrupt packet or times out.
|
||||||
It calls send_time() and query_status() if necessary. Therefore, make sure
|
It calls send_time() and query_status() if necessary. Therefore, make sure
|
||||||
|
@ -370,26 +403,15 @@ handle_interrupt (pixma_t * s, int timeout)
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (buf[0])
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
/* no button pressed */
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
s->events = PIXMA_EV_BUTTON1 | buf[1];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
s->events = PIXMA_EV_BUTTON2 | buf[1];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PDBG (pixma_dbg (2, "Interesting interrupt packet\n"));
|
|
||||||
PDBG (pixma_hexdump (2, buf, 16));
|
|
||||||
}
|
|
||||||
/* More than one event can be reported at the same time. */
|
/* More than one event can be reported at the same time. */
|
||||||
if (buf[3] & 1)
|
if (buf[3] & 1)
|
||||||
send_time (s);
|
send_time (s);
|
||||||
if (buf[9] & 2)
|
if (buf[9] & 2)
|
||||||
query_status (s);
|
query_status (s);
|
||||||
|
if (buf[0] & 2)
|
||||||
|
s->events = PIXMA_EV_BUTTON2 | buf[1]; /* b/w scan */
|
||||||
|
if (buf[0] & 1)
|
||||||
|
s->events = PIXMA_EV_BUTTON1 | buf[1]; /* color scan */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,23 +492,17 @@ mp150_close (pixma_t * s)
|
||||||
static int
|
static int
|
||||||
mp150_check_param (pixma_t * s, pixma_scan_param_t * sp)
|
mp150_check_param (pixma_t * s, pixma_scan_param_t * sp)
|
||||||
{
|
{
|
||||||
unsigned raw_width;
|
|
||||||
|
|
||||||
UNUSED (s);
|
UNUSED (s);
|
||||||
|
|
||||||
sp->depth = 8; /* MP150 only supports 8 bit per channel. */
|
sp->depth = 8; /* MP150 only supports 8 bit per channel. */
|
||||||
if (sp->channels == 1)
|
sp->line_size = calc_raw_width (sp) * sp->channels;
|
||||||
raw_width = ALIGN (sp->w, 12);
|
|
||||||
else
|
|
||||||
raw_width = ALIGN (sp->w, 4);
|
|
||||||
sp->line_size = raw_width * sp->channels;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mp150_scan (pixma_t * s)
|
mp150_scan (pixma_t * s)
|
||||||
{
|
{
|
||||||
int error, tmo;
|
int error = 0, tmo;
|
||||||
mp150_t *mp = (mp150_t *) s->subdriver;
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
|
|
||||||
if (mp->state != state_idle)
|
if (mp->state != state_idle)
|
||||||
|
@ -514,6 +530,27 @@ mp150_scan (pixma_t * s)
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->cfg->vid == 0x170d /*MP800 */ )
|
||||||
|
{
|
||||||
|
/* FIXME: What does this command do? */
|
||||||
|
error = send_cmd_e920 (s);
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
query_status (s);
|
||||||
|
}
|
||||||
|
if (error == -ECANCELED || error == -EBUSY)
|
||||||
|
{
|
||||||
|
PDBG (pixma_dbg (2, "cmd e920 returned %s\n", strerror (-error)));
|
||||||
|
query_status (s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PDBG (pixma_dbg (1, "WARNING:cmd e920 failed %s\n",
|
||||||
|
strerror (-error)));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error = start_session (s);
|
error = start_session (s);
|
||||||
tmo = 10;
|
tmo = 10;
|
||||||
while (error == -EBUSY && --tmo >= 0)
|
while (error == -EBUSY && --tmo >= 0)
|
||||||
|
@ -586,12 +623,20 @@ mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib)
|
||||||
|
|
||||||
error = read_image_block (s, header, mp->imgbuf);
|
error = read_image_block (s, header, mp->imgbuf);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
return error;
|
{
|
||||||
|
if (error == -ECANCELED)
|
||||||
|
{
|
||||||
|
/* NOTE: I see this in traffic logs but I don't know
|
||||||
|
its meaning. */
|
||||||
|
read_error_info (s, NULL, 0);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
bytes_received = error;
|
bytes_received = error;
|
||||||
block_size = pixma_get_be32 (header + 12);
|
block_size = pixma_get_be32 (header + 12);
|
||||||
mp->last_block = (header[8] == 0x38);
|
mp->last_block = ((header[8] & 0x28) == 0x28);
|
||||||
if (header[8] != 0 && header[8] != 0x38)
|
if ((header[8] & ~0x38) != 0)
|
||||||
{
|
{
|
||||||
PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n"));
|
PDBG (pixma_dbg (1, "WARNING: Unexpected result header\n"));
|
||||||
PDBG (pixma_hexdump (1, header, 16));
|
PDBG (pixma_hexdump (1, header, 16));
|
||||||
|
@ -630,6 +675,7 @@ mp150_finish_scan (pixma_t * s)
|
||||||
strerror (-error)));
|
strerror (-error)));
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case state_finished:
|
case state_finished:
|
||||||
|
while (handle_interrupt (s, 0) > 0);
|
||||||
mp->state = state_idle;
|
mp->state = state_idle;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case state_idle:
|
case state_idle:
|
||||||
|
|
Ładowanie…
Reference in New Issue