Added 2 commands for MP800.

merge-requests/1/head
Wittawat Yamwong 2006-06-08 17:48:06 +00:00
rodzic 653e3c2226
commit 890d2dee95
1 zmienionych plików z 88 dodań i 42 usunięć

Wyświetl plik

@ -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: