kopia lustrzana https://gitlab.com/sane-project/backends
Changes for ADF simplex and duplex scan, MP970 4800 dpi and TPU scan.
rodzic
7fa6ae708c
commit
1aa1677ef2
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
||||||
|
2008-10-04 Nicolas Martin <nicols-guest at users.alioth.debian.org>
|
||||||
|
* backend/pixma.c, backend/pixma.h, backend/pixma_common.c,
|
||||||
|
backend/pixma_io_sanei.c, backend/pixma_mp150.c,
|
||||||
|
doc/sane-pixma.man, doc/description/pixma.desc:
|
||||||
|
MP970 scanning improvements, up to 4800 dpi. On the way soon,
|
||||||
|
network BJNP protocol designed by Louis Lagendijk to be added to CVS.
|
||||||
|
MX7600 reported to work fine with the backend.
|
||||||
|
ADF scanning:
|
||||||
|
- improved for latest PIXMAs like MX850, MX310.
|
||||||
|
- bug fix in Sane_start, when scanning several pages with ADF.
|
||||||
|
ADF DUPLEX scanning:
|
||||||
|
- new code for ADF Duplex, (to be tested) based on a MX850 Snoop. Changes
|
||||||
|
might fit also MP830 (To be confirmed).
|
||||||
|
TPU scanning:
|
||||||
|
- MP970 TPU scanning: Protocol works, get scanned TPU images with 48 bits
|
||||||
|
to 24 bits conversion, full 48 bit version yet to be debugged.
|
||||||
|
|
||||||
2008-10-03 m. allan noah <kitno455 a t gmail d o t com>
|
2008-10-03 m. allan noah <kitno455 a t gmail d o t com>
|
||||||
* backend/epjitsu.[ch]: backend v17:
|
* backend/epjitsu.[ch]: backend v17:
|
||||||
- increase scan height ~1/2 inch due to head offset
|
- increase scan height ~1/2 inch due to head offset
|
||||||
|
|
480
backend/pixma.c
480
backend/pixma.c
|
@ -174,11 +174,11 @@ cleanup_device_list (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; dev_list[i]; i++)
|
for (i = 0; dev_list[i]; i++)
|
||||||
{
|
{
|
||||||
free (CONST_CAST (void *, dev_list[i]->name));
|
free (CONST_CAST (void *, dev_list[i]->name));
|
||||||
free (CONST_CAST (void *, dev_list[i]->model));
|
free (CONST_CAST (void *, dev_list[i]->model));
|
||||||
free (CONST_CAST (void *, dev_list[i]));
|
free (CONST_CAST (void *, dev_list[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (dev_list);
|
free (dev_list);
|
||||||
dev_list = NULL;
|
dev_list = NULL;
|
||||||
|
@ -201,16 +201,16 @@ find_scanners (void)
|
||||||
SANE_Device *sdev = (SANE_Device *) calloc (1, sizeof (*sdev));
|
SANE_Device *sdev = (SANE_Device *) calloc (1, sizeof (*sdev));
|
||||||
char *name, *model;
|
char *name, *model;
|
||||||
if (!sdev)
|
if (!sdev)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
name = strdup (pixma_get_device_id (i));
|
name = strdup (pixma_get_device_id (i));
|
||||||
model = strdup (pixma_get_device_model (i));
|
model = strdup (pixma_get_device_model (i));
|
||||||
if (!name || !model)
|
if (!name || !model)
|
||||||
{
|
{
|
||||||
free (name);
|
free (name);
|
||||||
free (model);
|
free (model);
|
||||||
free (sdev);
|
free (sdev);
|
||||||
goto nomem;
|
goto nomem;
|
||||||
}
|
}
|
||||||
sdev->name = name;
|
sdev->name = name;
|
||||||
sdev->model = model;
|
sdev->model = model;
|
||||||
sdev->vendor = vendor_str;
|
sdev->vendor = vendor_str;
|
||||||
|
@ -281,23 +281,23 @@ clamp_value (pixma_sane_t * ss, SANE_Int n, void *v, SANE_Int * info)
|
||||||
{
|
{
|
||||||
SANE_Word value = va[i];
|
SANE_Word value = va[i];
|
||||||
if (value < range->min)
|
if (value < range->min)
|
||||||
{
|
{
|
||||||
value = range->min;
|
value = range->min;
|
||||||
}
|
}
|
||||||
else if (value > range->max)
|
else if (value > range->max)
|
||||||
{
|
{
|
||||||
value = range->max;
|
value = range->max;
|
||||||
}
|
}
|
||||||
if (range->quant != 0)
|
if (range->quant != 0)
|
||||||
{
|
{
|
||||||
value = (value - range->min + range->quant / 2) /
|
value = (value - range->min + range->quant / 2) /
|
||||||
range->quant * range->quant;
|
range->quant * range->quant;
|
||||||
}
|
}
|
||||||
if (value != va[i])
|
if (value != va[i])
|
||||||
{
|
{
|
||||||
va[i] = value;
|
va[i] = value;
|
||||||
*info |= SANE_INFO_INEXACT;
|
*info |= SANE_INFO_INEXACT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,21 +317,21 @@ select_value_from_list (pixma_sane_t * ss, SANE_Int n, void *v,
|
||||||
SANE_Word mindelta = abs (value - list[1]);
|
SANE_Word mindelta = abs (value - list[1]);
|
||||||
SANE_Word nearest = list[1];
|
SANE_Word nearest = list[1];
|
||||||
for (j = 2; j <= list[0]; j++)
|
for (j = 2; j <= list[0]; j++)
|
||||||
{
|
{
|
||||||
SANE_Word delta = abs (value - list[j]);
|
SANE_Word delta = abs (value - list[j]);
|
||||||
if (delta < mindelta)
|
if (delta < mindelta)
|
||||||
{
|
{
|
||||||
mindelta = delta;
|
mindelta = delta;
|
||||||
nearest = list[j];
|
nearest = list[j];
|
||||||
}
|
}
|
||||||
if (mindelta == 0)
|
if (mindelta == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (va[i] != nearest)
|
if (va[i] != nearest)
|
||||||
{
|
{
|
||||||
va[i] = nearest;
|
va[i] = nearest;
|
||||||
*info |= SANE_INFO_INEXACT;
|
*info |= SANE_INFO_INEXACT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,51 +346,51 @@ control_scalar_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v,
|
||||||
{
|
{
|
||||||
case SANE_ACTION_GET_VALUE:
|
case SANE_ACTION_GET_VALUE:
|
||||||
switch (opt->sod.type)
|
switch (opt->sod.type)
|
||||||
{
|
{
|
||||||
case SANE_TYPE_BOOL:
|
case SANE_TYPE_BOOL:
|
||||||
case SANE_TYPE_INT:
|
case SANE_TYPE_INT:
|
||||||
case SANE_TYPE_FIXED:
|
case SANE_TYPE_FIXED:
|
||||||
*(SANE_Word *) v = opt->val.w;
|
*(SANE_Word *) v = opt->val.w;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
case SANE_ACTION_SET_VALUE:
|
case SANE_ACTION_SET_VALUE:
|
||||||
switch (opt->sod.type)
|
switch (opt->sod.type)
|
||||||
{
|
{
|
||||||
case SANE_TYPE_BOOL:
|
case SANE_TYPE_BOOL:
|
||||||
val = *(SANE_Word *) v;
|
val = *(SANE_Word *) v;
|
||||||
if (val != SANE_TRUE && val != SANE_FALSE)
|
if (val != SANE_TRUE && val != SANE_FALSE)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
opt->val.w = val;
|
opt->val.w = val;
|
||||||
break;
|
break;
|
||||||
case SANE_TYPE_INT:
|
case SANE_TYPE_INT:
|
||||||
case SANE_TYPE_FIXED:
|
case SANE_TYPE_FIXED:
|
||||||
if (opt->sod.constraint_type == SANE_CONSTRAINT_RANGE)
|
if (opt->sod.constraint_type == SANE_CONSTRAINT_RANGE)
|
||||||
clamp_value (ss, n, v, info);
|
clamp_value (ss, n, v, info);
|
||||||
else if (opt->sod.constraint_type == SANE_CONSTRAINT_WORD_LIST)
|
else if (opt->sod.constraint_type == SANE_CONSTRAINT_WORD_LIST)
|
||||||
select_value_from_list (ss, n, v, info);
|
select_value_from_list (ss, n, v, info);
|
||||||
opt->val.w = *(SANE_Word *) v;
|
opt->val.w = *(SANE_Word *) v;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
*info |= opt->info;
|
*info |= opt->info;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
case SANE_ACTION_SET_AUTO:
|
case SANE_ACTION_SET_AUTO:
|
||||||
switch (opt->sod.type)
|
switch (opt->sod.type)
|
||||||
{
|
{
|
||||||
case SANE_TYPE_BOOL:
|
case SANE_TYPE_BOOL:
|
||||||
case SANE_TYPE_INT:
|
case SANE_TYPE_INT:
|
||||||
case SANE_TYPE_FIXED:
|
case SANE_TYPE_FIXED:
|
||||||
opt->val.w = opt->def.w;
|
opt->val.w = opt->def.w;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
*info |= opt->info;
|
*info |= opt->info;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
@ -409,45 +409,45 @@ control_string_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v,
|
||||||
if (opt->sod.constraint_type == SANE_CONSTRAINT_NONE)
|
if (opt->sod.constraint_type == SANE_CONSTRAINT_NONE)
|
||||||
{
|
{
|
||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
case SANE_ACTION_GET_VALUE:
|
case SANE_ACTION_GET_VALUE:
|
||||||
strcpy (str, opt->val.s);
|
strcpy (str, opt->val.s);
|
||||||
break;
|
break;
|
||||||
case SANE_ACTION_SET_AUTO:
|
case SANE_ACTION_SET_AUTO:
|
||||||
str = opt->def.s;
|
str = opt->def.s;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case SANE_ACTION_SET_VALUE:
|
case SANE_ACTION_SET_VALUE:
|
||||||
strncpy (opt->val.s, str, opt->sod.size - 1);
|
strncpy (opt->val.s, str, opt->sod.size - 1);
|
||||||
*info |= opt->info;
|
*info |= opt->info;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
case SANE_ACTION_GET_VALUE:
|
case SANE_ACTION_GET_VALUE:
|
||||||
strcpy (str, slist[opt->val.w]);
|
strcpy (str, slist[opt->val.w]);
|
||||||
break;
|
break;
|
||||||
case SANE_ACTION_SET_AUTO:
|
case SANE_ACTION_SET_AUTO:
|
||||||
str = opt->def.ptr;
|
str = opt->def.ptr;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case SANE_ACTION_SET_VALUE:
|
case SANE_ACTION_SET_VALUE:
|
||||||
i = 0;
|
i = 0;
|
||||||
while (slist[i] && strcasecmp (str, slist[i]) != 0)
|
while (slist[i] && strcasecmp (str, slist[i]) != 0)
|
||||||
i++;
|
i++;
|
||||||
if (!slist[i])
|
if (!slist[i])
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
if (strcmp (slist[i], str) != 0)
|
if (strcmp (slist[i], str) != 0)
|
||||||
{
|
{
|
||||||
strcpy (str, slist[i]);
|
strcpy (str, slist[i]);
|
||||||
*info |= SANE_INFO_INEXACT;
|
*info |= SANE_INFO_INEXACT;
|
||||||
}
|
}
|
||||||
opt->val.w = i;
|
opt->val.w = i;
|
||||||
*info |= opt->info;
|
*info |= opt->info;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,37 +461,37 @@ control_option (pixma_sane_t * ss, SANE_Int n,
|
||||||
result = SANE_STATUS_UNSUPPORTED;
|
result = SANE_STATUS_UNSUPPORTED;
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
case opt_gamma_table:
|
case opt_gamma_table:
|
||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
case SANE_ACTION_SET_VALUE:
|
case SANE_ACTION_SET_VALUE:
|
||||||
clamp_value (ss, n, v, info);
|
clamp_value (ss, n, v, info);
|
||||||
for (i = 0; i != 4096; i++)
|
for (i = 0; i != 4096; i++)
|
||||||
ss->gamma_table[i] = *((SANE_Int *) v + i);
|
ss->gamma_table[i] = *((SANE_Int *) v + i);
|
||||||
break;
|
break;
|
||||||
case SANE_ACTION_GET_VALUE:
|
case SANE_ACTION_GET_VALUE:
|
||||||
for (i = 0; i != 4096; i++)
|
for (i = 0; i != 4096; i++)
|
||||||
*((SANE_Int *) v + i) = ss->gamma_table[i];
|
*((SANE_Int *) v + i) = ss->gamma_table[i];
|
||||||
break;
|
break;
|
||||||
case SANE_ACTION_SET_AUTO:
|
case SANE_ACTION_SET_AUTO:
|
||||||
pixma_fill_gamma_table (AUTO_GAMMA, ss->gamma_table,
|
pixma_fill_gamma_table (AUTO_GAMMA, ss->gamma_table,
|
||||||
sizeof (ss->gamma_table));
|
sizeof (ss->gamma_table));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
case opt_button_update:
|
case opt_button_update:
|
||||||
if (a == SANE_ACTION_SET_VALUE)
|
if (a == SANE_ACTION_SET_VALUE)
|
||||||
{
|
{
|
||||||
update_button_state (ss, info);
|
update_button_state (ss, info);
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,10 +518,10 @@ control_option (pixma_sane_t * ss, SANE_Int n,
|
||||||
{
|
{
|
||||||
case opt_custom_gamma:
|
case opt_custom_gamma:
|
||||||
if (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO)
|
if (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO)
|
||||||
{
|
{
|
||||||
if (enable_option (ss, opt_gamma_table, OVAL (opt_custom_gamma).b))
|
if (enable_option (ss, opt_gamma_table, OVAL (opt_custom_gamma).b))
|
||||||
*info |= SANE_INFO_RELOAD_OPTIONS;
|
*info |= SANE_INFO_RELOAD_OPTIONS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,6 +582,7 @@ calc_scan_param (pixma_sane_t * ss, pixma_scan_param_t * sp)
|
||||||
|
|
||||||
sp->gamma_table = (OVAL (opt_custom_gamma).b) ? ss->gamma_table : NULL;
|
sp->gamma_table = (OVAL (opt_custom_gamma).b) ? ss->gamma_table : NULL;
|
||||||
sp->source = ss->source_map[OVAL (opt_source).w];
|
sp->source = ss->source_map[OVAL (opt_source).w];
|
||||||
|
sp->adf_pageid = ss->page_count;
|
||||||
|
|
||||||
error = pixma_check_scan_param (ss->s, sp);
|
error = pixma_check_scan_param (ss->s, sp);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
|
@ -646,7 +647,7 @@ init_option_descriptors (pixma_sane_t * ss)
|
||||||
ss->source_map[i] = PIXMA_SOURCE_ADFDUP;
|
ss->source_map[i] = PIXMA_SOURCE_ADFDUP;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 1
|
||||||
if (cfg->cap & PIXMA_CAP_TPU)
|
if (cfg->cap & PIXMA_CAP_TPU)
|
||||||
{
|
{
|
||||||
ss->source_list[i] = SANE_I18N ("Transparency Unit");
|
ss->source_list[i] = SANE_I18N ("Transparency Unit");
|
||||||
|
@ -728,36 +729,36 @@ reader_loop (pixma_sane_t * ss)
|
||||||
"To cancel, press 'GRAY' button.\n");
|
"To cancel, press 'GRAY' button.\n");
|
||||||
#endif
|
#endif
|
||||||
while (pixma_wait_event (ss->s, 10) != 0)
|
while (pixma_wait_event (ss->s, 10) != 0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
while (!start)
|
while (!start)
|
||||||
{
|
{
|
||||||
uint32_t events;
|
uint32_t events;
|
||||||
if (ss->reader_stop)
|
if (ss->reader_stop)
|
||||||
{
|
{
|
||||||
count = PIXMA_ECANCELED;
|
count = PIXMA_ECANCELED;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
events = pixma_wait_event (ss->s, 1000);
|
events = pixma_wait_event (ss->s, 1000);
|
||||||
switch (events & ~PIXMA_EV_ACTION_MASK)
|
switch (events & ~PIXMA_EV_ACTION_MASK)
|
||||||
{
|
{
|
||||||
case PIXMA_EV_BUTTON1:
|
case PIXMA_EV_BUTTON1:
|
||||||
start = 1;
|
start = 1;
|
||||||
break;
|
break;
|
||||||
case PIXMA_EV_BUTTON2:
|
case PIXMA_EV_BUTTON2:
|
||||||
count = PIXMA_ECANCELED;
|
count = PIXMA_ECANCELED;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
count = pixma_scan (ss->s, &ss->sp);
|
count = pixma_scan (ss->s, &ss->sp);
|
||||||
if (count >= 0)
|
if (count >= 0)
|
||||||
{
|
{
|
||||||
while ((count = pixma_read_image (ss->s, buf, bufsize)) > 0)
|
while ((count = pixma_read_image (ss->s, buf, bufsize)) > 0)
|
||||||
{
|
{
|
||||||
if (write_all (ss, buf, count) != count)
|
if (write_all (ss, buf, count) != count)
|
||||||
pixma_cancel (ss->s);
|
pixma_cancel (ss->s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -839,7 +840,7 @@ terminate_reader_task (pixma_sane_t * ss, int *exit_code)
|
||||||
if (result == pid)
|
if (result == pid)
|
||||||
{
|
{
|
||||||
if (exit_code)
|
if (exit_code)
|
||||||
*exit_code = status;
|
*exit_code = status;
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -886,10 +887,10 @@ start_reader_task (pixma_sane_t * ss)
|
||||||
{
|
{
|
||||||
pid = sanei_thread_begin (reader_process, ss);
|
pid = sanei_thread_begin (reader_process, ss);
|
||||||
if (pid > 0)
|
if (pid > 0)
|
||||||
{
|
{
|
||||||
close (ss->wpipe);
|
close (ss->wpipe);
|
||||||
ss->wpipe = -1;
|
ss->wpipe = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -923,8 +924,8 @@ read_image (pixma_sane_t * ss, void *buf, unsigned size, int *readlen)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (ss->cancel)
|
if (ss->cancel)
|
||||||
/* ss->rpipe has already been closed by sane_cancel(). */
|
/* ss->rpipe has already been closed by sane_cancel(). */
|
||||||
return SANE_STATUS_CANCELLED;
|
return SANE_STATUS_CANCELLED;
|
||||||
count = read (ss->rpipe, buf, size);
|
count = read (ss->rpipe, buf, size);
|
||||||
}
|
}
|
||||||
while (count == -1 && errno == EINTR);
|
while (count == -1 && errno == EINTR);
|
||||||
|
@ -932,12 +933,12 @@ read_image (pixma_sane_t * ss, void *buf, unsigned size, int *readlen)
|
||||||
if (count == -1)
|
if (count == -1)
|
||||||
{
|
{
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
if (!ss->cancel)
|
if (!ss->cancel)
|
||||||
{
|
{
|
||||||
PDBG (pixma_dbg (1, "WARNING:read_image():read() failed %s\n",
|
PDBG (pixma_dbg (1, "WARNING:read_image():read() failed %s\n",
|
||||||
strerror (errno)));
|
strerror (errno)));
|
||||||
}
|
}
|
||||||
close (ss->rpipe);
|
close (ss->rpipe);
|
||||||
ss->rpipe = -1;
|
ss->rpipe = -1;
|
||||||
terminate_reader_task (ss, NULL);
|
terminate_reader_task (ss, NULL);
|
||||||
|
@ -964,16 +965,16 @@ read_image (pixma_sane_t * ss, void *buf, unsigned size, int *readlen)
|
||||||
close (ss->rpipe);
|
close (ss->rpipe);
|
||||||
ss->rpipe = -1;
|
ss->rpipe = -1;
|
||||||
if (terminate_reader_task (ss, &status) != -1
|
if (terminate_reader_task (ss, &status) != -1
|
||||||
&& status != SANE_STATUS_GOOD)
|
&& status != SANE_STATUS_GOOD)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* either terminate_reader_task failed or
|
/* either terminate_reader_task failed or
|
||||||
rpipe was closed but we expect more data */
|
rpipe was closed but we expect more data */
|
||||||
return SANE_STATUS_IO_ERROR;
|
return SANE_STATUS_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (readlen)
|
if (readlen)
|
||||||
*readlen = count;
|
*readlen = count;
|
||||||
|
@ -1051,17 +1052,17 @@ sane_open (SANE_String_Const name, SANE_Handle * h)
|
||||||
for (ss = first_scanner; ss; ss = ss->next)
|
for (ss = first_scanner; ss; ss = ss->next)
|
||||||
{
|
{
|
||||||
if (strcmp (pixma_get_string (ss->s, PIXMA_STRING_ID), name) == 0)
|
if (strcmp (pixma_get_string (ss->s, PIXMA_STRING_ID), name) == 0)
|
||||||
{
|
{
|
||||||
/* We have already opened it! */
|
/* We have already opened it! */
|
||||||
return SANE_STATUS_DEVICE_BUSY;
|
return SANE_STATUS_DEVICE_BUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (strcmp (pixma_get_device_id (i), name) != 0)
|
while (strcmp (pixma_get_device_id (i), name) != 0)
|
||||||
{
|
{
|
||||||
if (++i >= nscanners)
|
if (++i >= nscanners)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
cfg = pixma_get_device_config (i);
|
cfg = pixma_get_device_config (i);
|
||||||
if ((cfg->cap & PIXMA_CAP_EXPERIMENT) != 0)
|
if ((cfg->cap & PIXMA_CAP_EXPERIMENT) != 0)
|
||||||
|
@ -1070,13 +1071,13 @@ sane_open (SANE_String_Const name, SANE_Handle * h)
|
||||||
pixma_dbg (1, "WARNING:"
|
pixma_dbg (1, "WARNING:"
|
||||||
"Experimental backend CAN DAMAGE your hardware!\n");
|
"Experimental backend CAN DAMAGE your hardware!\n");
|
||||||
if (getenv_atoi ("PIXMA_EXPERIMENT", 0) == 0)
|
if (getenv_atoi ("PIXMA_EXPERIMENT", 0) == 0)
|
||||||
{
|
{
|
||||||
pixma_dbg (1, "Experimental SANE backend for %s is disabled "
|
pixma_dbg (1, "Experimental SANE backend for %s is disabled "
|
||||||
"by default.\n", pixma_get_device_model (i));
|
"by default.\n", pixma_get_device_model (i));
|
||||||
pixma_dbg (1, "To enable it, set the environment variable "
|
pixma_dbg (1, "To enable it, set the environment variable "
|
||||||
"PIXMA_EXPERIMENT to non-zero.\n");
|
"PIXMA_EXPERIMENT to non-zero.\n");
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return SANE_STATUS_UNSUPPORTED;
|
return SANE_STATUS_UNSUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1220,9 +1221,20 @@ sane_start (SANE_Handle h)
|
||||||
if (!ss)
|
if (!ss)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
if (!ss->idle && ss->scanning)
|
if (!ss->idle && ss->scanning)
|
||||||
return SANE_STATUS_INVAL;
|
{
|
||||||
|
PDBG (pixma_dbg (3, "Warning in Sane_start: !idle && scanning. idle=%d, ss->scanning=%d\n",
|
||||||
|
ss->idle, ss->scanning));
|
||||||
|
if (ss->sp.source != PIXMA_SOURCE_ADF && ss->sp.source != PIXMA_SOURCE_ADFDUP)
|
||||||
|
return SANE_STATUS_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ss->cancel = SANE_FALSE;
|
ss->cancel = SANE_FALSE;
|
||||||
|
if (ss->idle ||
|
||||||
|
ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_FLATBED ||
|
||||||
|
ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU)
|
||||||
|
ss->page_count = 0; /* start from idle state or scan from flatbed or TPU */
|
||||||
|
else
|
||||||
|
ss->page_count++;
|
||||||
if (calc_scan_param (ss, &ss->sp) < 0)
|
if (calc_scan_param (ss, &ss->sp) < 0)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
ss->image_bytes_read = 0;
|
ss->image_bytes_read = 0;
|
||||||
|
@ -1233,12 +1245,6 @@ sane_start (SANE_Handle h)
|
||||||
{
|
{
|
||||||
ss->output_line_size = ss->sp.w * ss->sp.channels * (ss->sp.depth / 8);
|
ss->output_line_size = ss->sp.w * ss->sp.channels * (ss->sp.depth / 8);
|
||||||
ss->byte_pos_in_line = 0;
|
ss->byte_pos_in_line = 0;
|
||||||
if (ss->idle ||
|
|
||||||
ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_FLATBED ||
|
|
||||||
ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU)
|
|
||||||
ss->page_count = 0; /* start from idle state or scan from flatbed or TPU */
|
|
||||||
else
|
|
||||||
ss->page_count++;
|
|
||||||
ss->last_read_status = SANE_STATUS_GOOD;
|
ss->last_read_status = SANE_STATUS_GOOD;
|
||||||
ss->scanning = SANE_TRUE;
|
ss->scanning = SANE_TRUE;
|
||||||
ss->idle = SANE_FALSE;
|
ss->idle = SANE_FALSE;
|
||||||
|
@ -1277,38 +1283,36 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||||||
the end of line, we've to remove it here in the backend! */
|
the end of line, we've to remove it here in the backend! */
|
||||||
sum = 0;
|
sum = 0;
|
||||||
while (sum < maxlen)
|
while (sum < maxlen)
|
||||||
{
|
{
|
||||||
if (ss->byte_pos_in_line < ss->output_line_size)
|
if (ss->byte_pos_in_line < ss->output_line_size)
|
||||||
{
|
{
|
||||||
n = ss->output_line_size - ss->byte_pos_in_line;
|
n = ss->output_line_size - ss->byte_pos_in_line;
|
||||||
if ((maxlen - sum) < n)
|
if ((maxlen - sum) < n)
|
||||||
n = maxlen - sum;
|
n = maxlen - sum;
|
||||||
status = read_image (ss, buf, n, &n);
|
status = read_image (ss, buf, n, &n);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
break;
|
break;
|
||||||
sum += n;
|
sum += n;
|
||||||
buf += n;
|
buf += n;
|
||||||
ss->byte_pos_in_line += n;
|
ss->byte_pos_in_line += n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* skip padding */
|
/* skip padding */
|
||||||
n = ss->sp.line_size - ss->byte_pos_in_line;
|
n = ss->sp.line_size - ss->byte_pos_in_line;
|
||||||
if (n > (int) sizeof (temp))
|
if (n > (int) sizeof (temp))
|
||||||
{
|
{
|
||||||
PDBG (pixma_dbg (3,
|
PDBG (pixma_dbg (3, "Inefficient skip buffer. Should be %d\n", n));
|
||||||
"Inefficient skip buffer. Should be %d\n",
|
n = sizeof (temp);
|
||||||
n));
|
}
|
||||||
n = sizeof (temp);
|
status = read_image (ss, temp, n, &n);
|
||||||
}
|
if (n == 0)
|
||||||
status = read_image (ss, temp, n, &n);
|
break;
|
||||||
if (n == 0)
|
ss->byte_pos_in_line += n;
|
||||||
break;
|
if (ss->byte_pos_in_line == ss->sp.line_size)
|
||||||
ss->byte_pos_in_line += n;
|
ss->byte_pos_in_line = 0;
|
||||||
if (ss->byte_pos_in_line == ss->sp.line_size)
|
}
|
||||||
ss->byte_pos_in_line = 0;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ss->cancel)
|
if (ss->cancel)
|
||||||
status = SANE_STATUS_CANCELLED;
|
status = SANE_STATUS_CANCELLED;
|
||||||
|
|
|
@ -266,6 +266,9 @@ struct pixma_scan_param_t
|
||||||
|
|
||||||
/** \see #pixma_paper_source_t */
|
/** \see #pixma_paper_source_t */
|
||||||
pixma_paper_source_t source;
|
pixma_paper_source_t source;
|
||||||
|
|
||||||
|
/** The current page # in the same ADF scan session, 0 in non ADF */
|
||||||
|
unsigned adf_pageid;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** PIXMA model information */
|
/** PIXMA model information */
|
||||||
|
|
|
@ -122,16 +122,16 @@ pixma_hexdump (int level, const void *d_, unsigned len)
|
||||||
line[9] = ':';
|
line[9] = ':';
|
||||||
p = line + 10;
|
p = line + 10;
|
||||||
for (c = 0; c != 16 && (ofs + c) < len; c++)
|
for (c = 0; c != 16 && (ofs + c) < len; c++)
|
||||||
{
|
{
|
||||||
u8tohex (d[ofs + c], p);
|
u8tohex (d[ofs + c], p);
|
||||||
p[2] = ' ';
|
p[2] = ' ';
|
||||||
p += 3;
|
p += 3;
|
||||||
if (c == 7)
|
if (c == 7)
|
||||||
{
|
{
|
||||||
p[0] = ' ';
|
p[0] = ' ';
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p[0] = '\0';
|
p[0] = '\0';
|
||||||
pixma_dbg (level, "%s\n", line);
|
pixma_dbg (level, "%s\n", line);
|
||||||
ofs += c;
|
ofs += c;
|
||||||
|
@ -621,67 +621,65 @@ pixma_read_image (pixma_t * s, void *buf, unsigned len)
|
||||||
if (s->underrun)
|
if (s->underrun)
|
||||||
{
|
{
|
||||||
if (s->cur_image_size < s->param->image_size)
|
if (s->cur_image_size < s->param->image_size)
|
||||||
{
|
{
|
||||||
ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff);
|
ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PDBG (pixma_dbg
|
PDBG (pixma_dbg
|
||||||
(3, "pixma_read_image():completed (underrun detected)\n"));
|
(3, "pixma_read_image():completed (underrun detected)\n"));
|
||||||
s->scanning = 0;
|
s->scanning = 0;
|
||||||
}
|
}
|
||||||
return ib.wptr - (uint8_t *) buf;
|
return ib.wptr - (uint8_t *) buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ib.wptr != ib.wend)
|
while (ib.wptr != ib.wend)
|
||||||
{
|
{
|
||||||
if (ib.rptr == ib.rend)
|
if (ib.rptr == ib.rend)
|
||||||
{
|
{
|
||||||
ib.rptr = ib.rend = NULL;
|
ib.rptr = ib.rend = NULL;
|
||||||
result = s->ops->fill_buffer (s, &ib);
|
result = s->ops->fill_buffer (s, &ib);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
goto cancel;
|
goto cancel;
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{ /* end of image? */
|
{ /* end of image? */
|
||||||
s->ops->finish_scan (s);
|
s->ops->finish_scan (s);
|
||||||
#ifndef NDEBUG
|
if (s->cur_image_size != s->param->image_size)
|
||||||
if (s->cur_image_size != s->param->image_size)
|
{
|
||||||
{
|
pixma_dbg (1, "WARNING:image size mismatches\n");
|
||||||
pixma_dbg (1, "WARNING:image size mismatches\n");
|
pixma_dbg (1,
|
||||||
pixma_dbg (1,
|
" %u expected (%d lines) but %u received (%d lines)\n",
|
||||||
" %u expected (%d lines) but %u received (%d lines)\n",
|
s->param->image_size, s->param->h,
|
||||||
s->param->image_size, s->param->h,
|
s->cur_image_size,
|
||||||
s->cur_image_size,
|
s->cur_image_size / s->param->line_size);
|
||||||
s->cur_image_size / s->param->line_size);
|
if ((s->cur_image_size % s->param->line_size) != 0)
|
||||||
if ((s->cur_image_size % s->param->line_size) != 0)
|
{
|
||||||
{
|
pixma_dbg (1,
|
||||||
pixma_dbg (1,
|
"BUG:received data not multiple of line_size\n");
|
||||||
"BUG:received data not multiple of line_size\n");
|
}
|
||||||
}
|
}
|
||||||
}
|
if (s->cur_image_size < s->param->image_size)
|
||||||
#endif /* !NDEBUG */
|
{
|
||||||
if (s->cur_image_size < s->param->image_size)
|
s->underrun = 1;
|
||||||
{
|
ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff);
|
||||||
s->underrun = 1;
|
}
|
||||||
ib.wptr = fill_pixels (s, ib.wptr, ib.wend, 0xff);
|
else
|
||||||
}
|
{
|
||||||
else
|
PDBG (pixma_dbg (3, "pixma_read_image():completed\n"));
|
||||||
{
|
s->scanning = 0;
|
||||||
PDBG (pixma_dbg (3, "pixma_read_image():completed\n"));
|
}
|
||||||
s->scanning = 0;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
s->cur_image_size += result;
|
||||||
}
|
PASSERT (s->cur_image_size <= s->param->image_size);
|
||||||
s->cur_image_size += result;
|
}
|
||||||
PASSERT (s->cur_image_size <= s->param->image_size);
|
|
||||||
}
|
|
||||||
if (ib.rptr)
|
if (ib.rptr)
|
||||||
{
|
{
|
||||||
unsigned count = MIN (ib.rend - ib.rptr, ib.wend - ib.wptr);
|
unsigned count = MIN (ib.rend - ib.rptr, ib.wend - ib.wptr);
|
||||||
memcpy (ib.wptr, ib.rptr, count);
|
memcpy (ib.wptr, ib.rptr, count);
|
||||||
ib.rptr += count;
|
ib.rptr += count;
|
||||||
ib.wptr += count;
|
ib.wptr += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->imagebuf = ib; /* store rptr and rend */
|
s->imagebuf = ib; /* store rptr and rend */
|
||||||
return ib.wptr - (uint8_t *) buf;
|
return ib.wptr - (uint8_t *) buf;
|
||||||
|
@ -764,37 +762,37 @@ pixma_check_scan_param (pixma_t * s, pixma_scan_param_t * sp)
|
||||||
|
|
||||||
case PIXMA_SOURCE_TPU:
|
case PIXMA_SOURCE_TPU:
|
||||||
if ((s->cfg->cap & PIXMA_CAP_TPU) != PIXMA_CAP_TPU)
|
if ((s->cfg->cap & PIXMA_CAP_TPU) != PIXMA_CAP_TPU)
|
||||||
{
|
{
|
||||||
sp->source = PIXMA_SOURCE_FLATBED;
|
sp->source = PIXMA_SOURCE_FLATBED;
|
||||||
PDBG (pixma_dbg
|
PDBG (pixma_dbg
|
||||||
(1, "WARNING: TPU unsupported, fallback to flatbed.\n"));
|
(1, "WARNING: TPU unsupported, fallback to flatbed.\n"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIXMA_SOURCE_ADF:
|
case PIXMA_SOURCE_ADF:
|
||||||
if ((s->cfg->cap & PIXMA_CAP_ADF) != PIXMA_CAP_ADF)
|
if ((s->cfg->cap & PIXMA_CAP_ADF) != PIXMA_CAP_ADF)
|
||||||
{
|
{
|
||||||
sp->source = PIXMA_SOURCE_FLATBED;
|
sp->source = PIXMA_SOURCE_FLATBED;
|
||||||
PDBG (pixma_dbg
|
PDBG (pixma_dbg
|
||||||
(1, "WARNING: ADF unsupported, fallback to flatbed.\n"));
|
(1, "WARNING: ADF unsupported, fallback to flatbed.\n"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIXMA_SOURCE_ADFDUP:
|
case PIXMA_SOURCE_ADFDUP:
|
||||||
if ((s->cfg->cap & PIXMA_CAP_ADFDUP) != PIXMA_CAP_ADFDUP)
|
if ((s->cfg->cap & PIXMA_CAP_ADFDUP) != PIXMA_CAP_ADFDUP)
|
||||||
{
|
{
|
||||||
if (s->cfg->cap & PIXMA_CAP_ADF)
|
if (s->cfg->cap & PIXMA_CAP_ADF)
|
||||||
{
|
{
|
||||||
sp->source = PIXMA_SOURCE_ADF;
|
sp->source = PIXMA_SOURCE_ADF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp->source = PIXMA_SOURCE_FLATBED;
|
sp->source = PIXMA_SOURCE_FLATBED;
|
||||||
}
|
}
|
||||||
PDBG (pixma_dbg
|
PDBG (pixma_dbg
|
||||||
(1, "WARNING: ADF duplex unsupported, fallback to %d.\n",
|
(1, "WARNING: ADF duplex unsupported, fallback to %d.\n",
|
||||||
sp->source));
|
sp->source));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -272,19 +272,19 @@ pixma_collect_devices (const struct pixma_config_t *const pixma_devices[])
|
||||||
for (i = 0; pixma_devices[i]; i++)
|
for (i = 0; pixma_devices[i]; i++)
|
||||||
{
|
{
|
||||||
for (cfg = pixma_devices[i]; cfg->name; cfg++)
|
for (cfg = pixma_devices[i]; cfg->name; cfg++)
|
||||||
{
|
{
|
||||||
sanei_usb_find_devices (cfg->vid, cfg->pid, attach);
|
sanei_usb_find_devices (cfg->vid, cfg->pid, attach);
|
||||||
si = first_scanner;
|
si = first_scanner;
|
||||||
while (j < nscanners)
|
while (j < nscanners)
|
||||||
{
|
{
|
||||||
PDBG (pixma_dbg (3, "pixma_collect_devices() found %s at %s\n",
|
PDBG (pixma_dbg (3, "pixma_collect_devices() found %s at %s\n",
|
||||||
cfg->name, si->devname));
|
cfg->name, si->devname));
|
||||||
si->cfg = cfg;
|
si->cfg = cfg;
|
||||||
read_serial_number (si);
|
read_serial_number (si);
|
||||||
si = si->next;
|
si = si->next;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nscanners;
|
return nscanners;
|
||||||
}
|
}
|
||||||
|
|
Plik diff jest za duży
Load Diff
|
@ -158,7 +158,7 @@
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
:usbid "0x04a9" "0x1713"
|
:usbid "0x04a9" "0x1713"
|
||||||
:status :basic
|
:status :basic
|
||||||
:comment "Single-side ADF works but duplex doesn't work yet."
|
:comment "Single-side ADF works, Duplex ADF to be tested."
|
||||||
|
|
||||||
:model "PIXMA MP960"
|
:model "PIXMA MP960"
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
|
@ -169,7 +169,7 @@
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
:usbid "0x04a9" "0x1726"
|
:usbid "0x04a9" "0x1726"
|
||||||
:status :good
|
:status :good
|
||||||
:comment "All resolutions supported (up to 4800DPI)"
|
:comment "All resolutions supported (up to 4800DPI). TPU support currently experimental."
|
||||||
|
|
||||||
:model "SmartBase MP360"
|
:model "SmartBase MP360"
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
|
@ -240,8 +240,8 @@
|
||||||
:model "PIXMA MX7600"
|
:model "PIXMA MX7600"
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
:usbid "0x04a9" "0x171c"
|
:usbid "0x04a9" "0x171c"
|
||||||
:status :untested
|
:status :good
|
||||||
:comment "Generation 3 protocol? Testers needed!"
|
:comment "Flatbed and ADF scan. All resolutions supported (up to 4800DPI)"
|
||||||
|
|
||||||
:model "imageCLASS MF5630"
|
:model "imageCLASS MF5630"
|
||||||
:interface "USB"
|
:interface "USB"
|
||||||
|
|
|
@ -18,7 +18,7 @@ PIXMA MP600, MP600R, MP610, MP710
|
||||||
.br
|
.br
|
||||||
PIXMA MP800, MP800R, MP810, MP830, MP960, MP970
|
PIXMA MP800, MP800R, MP810, MP830, MP960, MP970
|
||||||
.br
|
.br
|
||||||
PIXMA MX300, MX310, MX700
|
PIXMA MX300, MX310, MX700, MX850, MX7600
|
||||||
.br
|
.br
|
||||||
MultiPASS MP700, PIXMA MP750 (no grayscale)
|
MultiPASS MP700, PIXMA MP750 (no grayscale)
|
||||||
.br
|
.br
|
||||||
|
@ -47,13 +47,13 @@ ImageCLASS MF3110, MF3240
|
||||||
ImageCLASS MF5630, MF5650, MF5730, MF5750, MF5770, MF8170c
|
ImageCLASS MF5630, MF5650, MF5730, MF5750, MF5770, MF8170c
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
The following models may use partly the same Pixma protocol as MPs listed
|
\#The following models may use partly the same Pixma protocol as MPs listed
|
||||||
above, but may still need some work. They are declared in the backend as
|
\#above, but may still need some work. They are declared in the backend as
|
||||||
experimental. Snoop logs are required to further investigate, please contact
|
\#experimental. Snoop logs are required to further investigate, please contact
|
||||||
the sane\-devel mailing list.
|
\#the sane\-devel mailing list.
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
PIXMA MX850
|
\#PIXMA MX850
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
The backend supports
|
The backend supports
|
||||||
|
@ -64,7 +64,9 @@ The backend supports
|
||||||
.br
|
.br
|
||||||
* a custom gamma table and
|
* a custom gamma table and
|
||||||
.br
|
.br
|
||||||
* automatic document feeder (only single side, duplex needs some work).
|
* Automatic Document Feeder (Duplex for some models).
|
||||||
|
.br
|
||||||
|
* Transparency Unit support is still experimental.
|
||||||
.PP
|
.PP
|
||||||
The device name is in the form pixma:xxxxyyyy_zzzzz
|
The device name is in the form pixma:xxxxyyyy_zzzzz
|
||||||
where x, y and z are vendor ID, product ID and serial number respectively.
|
where x, y and z are vendor ID, product ID and serial number respectively.
|
||||||
|
|
Ładowanie…
Reference in New Issue