kopia lustrzana https://gitlab.com/sane-project/backends
Update pixma backend for Grayscale scan for MP970 (tested), and probably other CCD sensor MPs (yet untested).
rodzic
9a70825259
commit
7b695e1c8e
71
ChangeLog
71
ChangeLog
|
@ -1,4 +1,75 @@
|
||||||
|
2008-04-22 Nicolas Martin <nicols-guest at users.alioth.debian.org>
|
||||||
|
* backend/pixma_mp150.c:
|
||||||
|
Updated pixma backend to have MP970 (tested), and probably other
|
||||||
|
CCD sensor MPs, working for Grayscale scan.
|
||||||
|
|
||||||
|
2008-04-21 Nicolas Martin <nicols-guest at users.alioth.debian.org>
|
||||||
|
* backend/pixma.c, backend/pixma_common.c, backend/pixma_rename.h
|
||||||
|
doc/sane-pixma.man, doc/descriptions/pixma.desc
|
||||||
|
(new) backend/pixma_imageclass.c, backend/Makefile.in:
|
||||||
|
Thanks to Dennis Lou, who adapted the pixma backend to add support
|
||||||
|
for Canon ImageCLASS series, fully tested for MF4270, and includes
|
||||||
|
PIDs declarations for other ImageCLASS devices, yet to be tested.
|
||||||
|
Fixes also a bug for ADF and ADF Duplex scan source selection.
|
||||||
|
|
||||||
|
2008-04-20 m. allan noah <kitno455 a t gmail d o t com>
|
||||||
|
* backend/fujitsu.h: remove #define SANE_FRAME_JPEG
|
||||||
|
|
||||||
|
2008-04-19 m. allan noah <kitno455 a t gmail d o t com>
|
||||||
|
* backend/fujitsu.[ch], backend/fujitsu-scsi.h: backend v1.0.58,
|
||||||
|
rename page code 32 to 'unknown', compile if NDEBUG is set,
|
||||||
|
proper async sane_cancel support, re-enable JPEG support
|
||||||
|
various functions rewritten (shorter, more clear)
|
||||||
|
* doc/descriptions/fujitsu.desc: add new fi-6xxx machines
|
||||||
|
|
||||||
|
2008-04-18 Alessandro Zummo <a.zummo@towertech.it>
|
||||||
|
* backend/epson2.c: fixed attach() error path.
|
||||||
|
|
||||||
2008-04-14 Nicolas Martin <nicols-guest at users.alioth.debian.org>
|
2008-04-14 Nicolas Martin <nicols-guest at users.alioth.debian.org>
|
||||||
|
* backend/pixma_mp150.c, backend/pixma.h, backend/pixma_mp150.c
|
||||||
|
doc/sane-pixma.man, doc/descriptions/pixma.desc:
|
||||||
|
With feedback from MP970 owner, updated pixma backend for MP970
|
||||||
|
CCD sensor support (yet in color only), and more generally,
|
||||||
|
support for other CCD sensor PIXMA: MP800, MP810, MP830, MP960,
|
||||||
|
but yet untested, which produce shifted color planes
|
||||||
|
scanned images. Current trim based on sample images provided
|
||||||
|
in bug reports and other web pages, but might require some
|
||||||
|
few and simple final tweaks.
|
||||||
|
Also fixed a bug for MP220 at 1200 dpi, MP220 is now reported
|
||||||
|
to work fine.
|
||||||
|
|
||||||
|
2008-04-13 Julien Blache <jb@jblache.org>
|
||||||
|
* frontend/saned.c: fix typo.
|
||||||
|
* backend/net.c: plug an information leak in the net backend. When
|
||||||
|
sending out a SANE_NET_CONTROL_OPTION RPC for the
|
||||||
|
SANE_ACTION_GET_VALUE action (and SANE_ACTION_SET_AUTO for the
|
||||||
|
network protocol versions < 3), the backend was not clearing the
|
||||||
|
memory area for the value argument before sending it over the
|
||||||
|
network, resulting in an information leak for the
|
||||||
|
SANE_ACTION_GET_VALUE case.
|
||||||
|
|
||||||
|
2008-04-12 Mattias Ellert <mattias.ellert@fysast.uu.se>
|
||||||
|
* backend/rts8891.c, backend/rts88xx_lib.c: fix format warning
|
||||||
|
* doc/sane-rts8891.man: man page fixes
|
||||||
|
* AUTHORS: e-mail update
|
||||||
|
|
||||||
|
2008-04-11 Julien Blache <jb@jblache.org>
|
||||||
|
* frontend/saned.c: announce the _sane-port._tcp service via mDNS
|
||||||
|
(Avahi) when running in standalone or debug mode. A separate
|
||||||
|
process is responsible for the announcement through Avahi.
|
||||||
|
* backend/net.c: look for _sane-port._tcp service announcements
|
||||||
|
via mDNS (Avahi). A separate thread listens to announcements
|
||||||
|
through Avahi. Start the thread as early as possible in
|
||||||
|
sane_init() so as to get as much data as possible until
|
||||||
|
sane_get_devices() is called.
|
||||||
|
* aclocal.m4, configure, configure.in, include/sane/config.h.in:
|
||||||
|
add autofoo stuff for Avahi support, disabled by default.
|
||||||
|
|
||||||
|
2008-04-10 Julien Blache <jb@jblache.org>
|
||||||
|
* frontend/saned.c: do not use daemon(), as it's a 4.4BSD/glibc
|
||||||
|
function; OS/2 for instance does not have it. Use an open-coded
|
||||||
|
equivalent. Add a PID file. saned -a username now drops privileges
|
||||||
|
2008-04-22 Nicolas Martin <nicols-guest at users.alioth.debian.org>
|
||||||
* backend/pixma.c, backend/pixma_common.c, backend/pixma_rename.h
|
* backend/pixma.c, backend/pixma_common.c, backend/pixma_rename.h
|
||||||
doc/sane-pixma.man, doc/descriptions/pixma.desc
|
doc/sane-pixma.man, doc/descriptions/pixma.desc
|
||||||
(new) backend/pixma_imageclass.c, backend/Makefile.in:
|
(new) backend/pixma_imageclass.c, backend/Makefile.in:
|
||||||
|
|
|
@ -395,6 +395,31 @@ calc_raw_width (const mp150_t * mp, const pixma_scan_param_t * param)
|
||||||
return raw_width;
|
return raw_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
has_ccd_sensor (pixma_t * s)
|
||||||
|
{
|
||||||
|
return ((s->cfg->cap & PIXMA_CAP_CCD) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_ccd_grayscale (pixma_t * s)
|
||||||
|
{
|
||||||
|
return (has_ccd_sensor (s) && (s->param->channels == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CCD sensors don't have a Grayscale mode, but use color mode instead */
|
||||||
|
static unsigned
|
||||||
|
get_cis_ccd_line_size (pixma_t * s)
|
||||||
|
{
|
||||||
|
return (s->param->line_size * ((is_ccd_grayscale (s)) ? 3 : 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_scanning_from_adf (pixma_t * s)
|
||||||
|
{
|
||||||
|
return (s->param->source == PIXMA_SOURCE_ADF
|
||||||
|
|| s->param->source == PIXMA_SOURCE_ADFDUP);
|
||||||
|
}
|
||||||
static int
|
static int
|
||||||
send_scan_param (pixma_t * s)
|
send_scan_param (pixma_t * s)
|
||||||
{
|
{
|
||||||
|
@ -411,8 +436,8 @@ send_scan_param (pixma_t * s)
|
||||||
pixma_set_be32 (s->param->y, data + 0x0c);
|
pixma_set_be32 (s->param->y, data + 0x0c);
|
||||||
pixma_set_be32 (raw_width, data + 0x10);
|
pixma_set_be32 (raw_width, data + 0x10);
|
||||||
pixma_set_be32 (s->param->h, data + 0x14);
|
pixma_set_be32 (s->param->h, data + 0x14);
|
||||||
data[0x18] = (s->param->channels == 1) ? 0x04 : 0x08;
|
data[0x18] = ((s->param->channels != 1) || is_ccd_grayscale (s)) ? 0x08 : 0x04;
|
||||||
data[0x19] = s->param->channels * s->param->depth; /* bits per pixel */
|
data[0x19] = s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */
|
||||||
data[0x20] = 0xff;
|
data[0x20] = 0xff;
|
||||||
data[0x23] = 0x81;
|
data[0x23] = 0x81;
|
||||||
data[0x26] = 0x02;
|
data[0x26] = 0x02;
|
||||||
|
@ -431,8 +456,8 @@ send_scan_param (pixma_t * s)
|
||||||
pixma_set_be32 (s->param->y, data + 0x10);
|
pixma_set_be32 (s->param->y, data + 0x10);
|
||||||
pixma_set_be32 (raw_width, data + 0x14);
|
pixma_set_be32 (raw_width, data + 0x14);
|
||||||
pixma_set_be32 (s->param->h, data + 0x18);
|
pixma_set_be32 (s->param->h, data + 0x18);
|
||||||
data[0x1c] = (s->param->channels == 1) ? 0x04 : 0x08;
|
data[0x1c] = ((s->param->channels != 1) || is_ccd_grayscale (s)) ? 0x08 : 0x04;
|
||||||
data[0x1d] = s->param->channels * s->param->depth; /* bits per pixel */
|
data[0x1d] = s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */
|
||||||
data[0x1f] = 0x01;
|
data[0x1f] = 0x01;
|
||||||
data[0x20] = 0xff;
|
data[0x20] = 0xff;
|
||||||
data[0x21] = 0x81;
|
data[0x21] = 0x81;
|
||||||
|
@ -666,20 +691,6 @@ wait_until_ready (pixma_t * s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
has_ccd_sensor (pixma_t * s)
|
|
||||||
{
|
|
||||||
return ((s->cfg->cap & PIXMA_CAP_CCD) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
is_scanning_from_adf (pixma_t * s)
|
|
||||||
{
|
|
||||||
return (s->param->source == PIXMA_SOURCE_ADF
|
|
||||||
|| s->param->source == PIXMA_SOURCE_ADFDUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mp150_open (pixma_t * s)
|
mp150_open (pixma_t * s)
|
||||||
{
|
{
|
||||||
|
@ -864,52 +875,88 @@ mp150_scan (pixma_t * s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This post process function deals both with CCD sensors PIXMAs
|
static uint8_t *
|
||||||
* producing shifted color planes images, and Generation 3 high dpi images.
|
shift_colors (uint8_t * dptr, uint8_t * sptr, unsigned w, int sr, int sg, int sb)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
{
|
||||||
|
*sptr++ = *(dptr++ + sr);
|
||||||
|
*sptr++ = *(dptr++ + sg);
|
||||||
|
*sptr++ = *(dptr++ + sb);
|
||||||
|
}
|
||||||
|
return dptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *
|
||||||
|
rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w)
|
||||||
|
{
|
||||||
|
unsigned i, g;
|
||||||
|
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
{
|
||||||
|
g = *sptr++;
|
||||||
|
g += *sptr++;
|
||||||
|
*gptr++ = (*sptr++ + g) / 3;
|
||||||
|
}
|
||||||
|
return gptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned n,
|
||||||
|
unsigned m, unsigned w, unsigned line_size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < w; i++)
|
||||||
|
{
|
||||||
|
memcpy (linebuf + c * (n * (i % m) + i / m), sptr + c * i, c);
|
||||||
|
}
|
||||||
|
memcpy (sptr, linebuf, line_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function deals both with PIXMA CCD sensors producing shifted color
|
||||||
|
* planes images, Grayscale CCD scan and Generation 3 high dpi images.
|
||||||
* Each complete line in mp->imgbuf is processed for shifting CCD sensor
|
* Each complete line in mp->imgbuf is processed for shifting CCD sensor
|
||||||
* color planes, and reordering pixels for above 600 dpi Generation 3 format. */
|
* color planes, reordering pixels above 600 dpi for Generation 3, and
|
||||||
|
* converting to Grayscale for CCD sensors. */
|
||||||
static unsigned
|
static unsigned
|
||||||
post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
|
post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
|
||||||
{
|
{
|
||||||
mp150_t *mp = (mp150_t *) s->subdriver;
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
const unsigned n = s->param->xdpi / 600;
|
unsigned c, lines, i, line_size, n, m;
|
||||||
const unsigned c = s->param->channels;
|
uint8_t *sptr, *dptr, *gptr;
|
||||||
const unsigned m = (n > 0) ? s->param->w / n : 1;
|
|
||||||
unsigned lines, i, j;
|
|
||||||
uint8_t *sptr = mp->imgbuf;
|
|
||||||
uint8_t *dptr = mp->imgbuf;
|
|
||||||
const int sr = mp->shift[0];
|
|
||||||
const int sg = mp->shift[1];
|
|
||||||
const int sb = mp->shift[2];
|
|
||||||
|
|
||||||
lines = (ib->rend - ib->rptr) / s->param->line_size;
|
c = (is_ccd_grayscale (s)) ? 3 : s->param->channels;
|
||||||
|
n = s->param->xdpi / 600;
|
||||||
|
m = (n > 0) ? s->param->w / n : 1;
|
||||||
|
sptr = dptr = gptr = mp->imgbuf;
|
||||||
|
line_size = get_cis_ccd_line_size (s);
|
||||||
|
|
||||||
|
lines = (mp->data_left_ofs - mp->imgbuf) / line_size;
|
||||||
if (lines > 2 * mp->lines_shift)
|
if (lines > 2 * mp->lines_shift)
|
||||||
{
|
{
|
||||||
for (j = 0; j < lines - 2 * mp->lines_shift; j++)
|
lines -= 2 * mp->lines_shift;
|
||||||
|
for (i = 0; i < lines; i++, sptr += line_size)
|
||||||
{
|
{
|
||||||
if (has_ccd_sensor (s) && (c == 3))
|
/* Color plane shift needed by e.g. CCD */
|
||||||
{
|
if (c == 3)
|
||||||
for (i = 0; i < s->param->w; i++)
|
dptr = shift_colors (dptr, sptr, s->param->w,
|
||||||
{
|
mp->shift[0], mp->shift[1], mp->shift[2]);
|
||||||
*sptr++ = *(dptr++ + sr);
|
|
||||||
*sptr++ = *(dptr++ + sg);
|
/* special image format for *most* Generation 3 devices */
|
||||||
*sptr++ = *(dptr++ + sb);
|
|
||||||
}
|
|
||||||
sptr -= s->param->line_size;
|
|
||||||
}
|
|
||||||
if ((mp->generation == 3) && (s->cfg->pid != MP220_PID))
|
if ((mp->generation == 3) && (s->cfg->pid != MP220_PID))
|
||||||
{
|
reorder_pixels (mp->linebuf, sptr, c, n, m, s->param->w, line_size);
|
||||||
for (i = 0; i < s->param->w; i++)
|
|
||||||
{
|
/* Color to Grayscale convert for CCD sensor */
|
||||||
memcpy (mp->linebuf + (c * (n * (i % m) + i / m)),
|
if (is_ccd_grayscale (s))
|
||||||
sptr + (c * i), c);
|
gptr = rgb_to_gray (gptr, sptr, s->param->w);
|
||||||
}
|
|
||||||
memcpy (sptr, mp->linebuf, s->param->line_size);
|
|
||||||
}
|
|
||||||
sptr += s->param->line_size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ib->rend - sptr;
|
ib->rptr = mp->imgbuf;
|
||||||
|
ib->rend = (is_ccd_grayscale (s)) ? gptr : sptr;
|
||||||
|
return mp->data_left_ofs - sptr; /* # of non processed bytes */
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
|
@ -918,41 +965,43 @@ calc_shifting (pixma_t * s)
|
||||||
mp150_t *mp = (mp150_t *) s->subdriver;
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
unsigned base_shift;
|
unsigned base_shift;
|
||||||
|
|
||||||
mp->lines_shift = 0;
|
/* If color plane shift, how many pixels shift */
|
||||||
if (has_ccd_sensor (s))
|
switch (s->cfg->pid)
|
||||||
{
|
{
|
||||||
switch (s->cfg->pid)
|
case MP970_PID:
|
||||||
{
|
if (s->param->ydpi > 75)
|
||||||
case MP970_PID:
|
mp->lines_shift = s->param->ydpi / 50;
|
||||||
if (s->param->ydpi > 75)
|
break;
|
||||||
mp->lines_shift = s->param->ydpi / 50;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP800_PID:
|
case MP800_PID:
|
||||||
case MP810_PID:
|
case MP810_PID:
|
||||||
case MP830_PID:
|
case MP830_PID:
|
||||||
case MP960_PID:
|
case MP960_PID:
|
||||||
default:
|
mp->lines_shift = s->param->ydpi / 100;
|
||||||
mp->lines_shift = s->param->ydpi / 100;
|
break;
|
||||||
}
|
|
||||||
base_shift = mp->lines_shift * s->param->line_size;
|
|
||||||
switch (s->cfg->pid)
|
|
||||||
{
|
|
||||||
case MP970_PID:
|
|
||||||
mp->shift[0] = 0;
|
|
||||||
mp->shift[1] = base_shift;
|
|
||||||
mp->shift[2] = 2 * base_shift;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MP800_PID:
|
default: /* all CIS devices */
|
||||||
case MP810_PID:
|
mp->lines_shift = 0;
|
||||||
case MP830_PID:
|
}
|
||||||
case MP960_PID:
|
base_shift = get_cis_ccd_line_size (s) * mp->lines_shift;
|
||||||
default:
|
|
||||||
mp->shift[0] = 2 * base_shift;
|
/* If color plane shift, how to apply the shift */
|
||||||
mp->shift[1] = base_shift;
|
switch (s->cfg->pid)
|
||||||
mp->shift[2] = 0;
|
{
|
||||||
}
|
case MP970_PID:
|
||||||
|
mp->shift[0] = 0;
|
||||||
|
mp->shift[1] = base_shift;
|
||||||
|
mp->shift[2] = 2 * base_shift;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MP800_PID:
|
||||||
|
case MP810_PID:
|
||||||
|
case MP830_PID:
|
||||||
|
case MP960_PID:
|
||||||
|
default:
|
||||||
|
mp->shift[0] = 2 * base_shift;
|
||||||
|
mp->shift[1] = base_shift;
|
||||||
|
mp->shift[2] = 0;
|
||||||
}
|
}
|
||||||
return mp->lines_shift;
|
return mp->lines_shift;
|
||||||
}
|
}
|
||||||
|
@ -962,7 +1011,7 @@ mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
mp150_t *mp = (mp150_t *) s->subdriver;
|
mp150_t *mp = (mp150_t *) s->subdriver;
|
||||||
unsigned block_size, bytes_received, proc_buf_size;
|
unsigned block_size, bytes_received, proc_buf_size, line_size;
|
||||||
uint8_t header[16];
|
uint8_t header[16];
|
||||||
|
|
||||||
if (mp->state == state_warmup)
|
if (mp->state == state_warmup)
|
||||||
|
@ -975,13 +1024,14 @@ mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib)
|
||||||
mp->state = state_scanning;
|
mp->state = state_scanning;
|
||||||
mp->last_block = 0;
|
mp->last_block = 0;
|
||||||
|
|
||||||
proc_buf_size = (2 * calc_shifting (s) + 2) * s->param->line_size;
|
line_size = get_cis_ccd_line_size (s);
|
||||||
|
proc_buf_size = (2 * calc_shifting (s) + 2) * line_size;
|
||||||
mp->cb.buf = realloc (mp->cb.buf,
|
mp->cb.buf = realloc (mp->cb.buf,
|
||||||
CMDBUF_SIZE + IMAGE_BLOCK_SIZE + proc_buf_size);
|
CMDBUF_SIZE + IMAGE_BLOCK_SIZE + proc_buf_size);
|
||||||
if (!mp->cb.buf)
|
if (!mp->cb.buf)
|
||||||
return PIXMA_ENOMEM;
|
return PIXMA_ENOMEM;
|
||||||
mp->linebuf = mp->cb.buf + CMDBUF_SIZE;
|
mp->linebuf = mp->cb.buf + CMDBUF_SIZE;
|
||||||
mp->imgbuf = mp->data_left_ofs = mp->linebuf + s->param->line_size;
|
mp->imgbuf = mp->data_left_ofs = mp->linebuf + line_size;
|
||||||
mp->data_left_len = 0;
|
mp->data_left_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,12 +1075,9 @@ mp150_fill_buffer (pixma_t * s, pixma_imagebuf_t * ib)
|
||||||
pixma_sleep (10000);
|
pixma_sleep (10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ib->rptr = mp->imgbuf;
|
mp->data_left_ofs = mp->imgbuf + mp->data_left_len + bytes_received;
|
||||||
ib->rend = mp->data_left_ofs = mp->imgbuf + mp->data_left_len + bytes_received;
|
|
||||||
|
|
||||||
mp->data_left_len = post_process_image_data (s, ib);
|
mp->data_left_len = post_process_image_data (s, ib);
|
||||||
mp->data_left_ofs -= mp->data_left_len;
|
mp->data_left_ofs -= mp->data_left_len;
|
||||||
ib->rend -= mp->data_left_len;
|
|
||||||
}
|
}
|
||||||
while (ib->rend == ib->rptr);
|
while (ib->rend == ib->rptr);
|
||||||
|
|
||||||
|
@ -1156,7 +1203,7 @@ const pixma_config_t pixma_mp150_devices[] = {
|
||||||
DEVICE ("Canon PIXMA MX700", MX700_PID, 2400,
|
DEVICE ("Canon PIXMA MX700", MX700_PID, 2400,
|
||||||
PIXMA_CAP_CIS | PIXMA_CAP_ADF),
|
PIXMA_CAP_CIS | PIXMA_CAP_ADF),
|
||||||
DEVICE ("Canon PIXMA MX850", MX850_PID, 2400,
|
DEVICE ("Canon PIXMA MX850", MX850_PID, 2400,
|
||||||
PIXMA_CAP_CIS | PIXMA_CAP_ADF | PIXMA_CAP_ADFDUP | PIXMA_CAP_EXPERIMENT),
|
PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP | PIXMA_CAP_EXPERIMENT),
|
||||||
|
|
||||||
/* Generation 3 CCD not managed as Generation 2 */
|
/* Generation 3 CCD not managed as Generation 2 */
|
||||||
DEVICE ("Canon PIXMA MP970", MP970_PID, 4800,
|
DEVICE ("Canon PIXMA MP970", MP970_PID, 4800,
|
||||||
|
|
Ładowanie…
Reference in New Issue