kopia lustrzana https://gitlab.com/sane-project/backends
Added support for FB620P to canon_pp backend.
rodzic
1fd72c6c6d
commit
f0722f0d5c
|
@ -40,13 +40,12 @@
|
|||
|
||||
-----
|
||||
|
||||
This file is part of the canon_pp backend, supporting Canon FBX30P
|
||||
and NX40P scanners and also distributed as part of the stand-alone
|
||||
driver.
|
||||
This file is part of the canon_pp backend, supporting Canon CanoScan
|
||||
Parallel scanners and also distributed as part of the stand-alone driver.
|
||||
|
||||
canon_pp-io.c: $Revision$
|
||||
|
||||
Low Level Function library for Canon FB330/FB630P Scanners by
|
||||
Low Level Function library for Canon CanoScan Parallel Scanners by
|
||||
Simon Krix <kinsei@users.sourceforge.net>
|
||||
*/
|
||||
|
||||
|
@ -89,17 +88,17 @@ static void DBG(int level, const char *format, ...)
|
|||
static int ieee_mode = M1284_NIBBLE;
|
||||
|
||||
/* For super-verbose debugging */
|
||||
/* #define DUMP_PACKETS 0; */
|
||||
/* #define DUMP_PACKETS 1 */
|
||||
|
||||
/* Unknown command 1 */
|
||||
static unsigned char command_1[10] = { 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
/* Some sort of initialisation command */
|
||||
static unsigned char cmd_init[10] = { 0xec, 0x20, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/************* Local Prototypes ******************/
|
||||
|
||||
/* Used by wake_scanner */
|
||||
static int scanner_reset(struct parport *port);
|
||||
static void scanner_chessboard_control(struct parport *port);
|
||||
static void scanner_chessboard_data(struct parport *port);
|
||||
static void scanner_chessboard_data(struct parport *port, int mode);
|
||||
|
||||
/* Used by read_data */
|
||||
static int ieee_negotiation(struct parport *port, int e);
|
||||
|
@ -129,21 +128,35 @@ int sanei_canon_pp_wake_scanner(struct parport *port)
|
|||
/* The scanner tristates the printer's control lines
|
||||
(essentially disabling the passthrough port) and exits
|
||||
from Transparent Mode ready for communication. */
|
||||
int count1 = 0;
|
||||
int i = 0;
|
||||
int tmp;
|
||||
int max_cycles = 3;
|
||||
|
||||
tmp = readstatus(port);
|
||||
|
||||
if (readstatus(port) != READY)
|
||||
if ((tmp != READY))
|
||||
{
|
||||
DBG(40, "Scanner not ready. Attempting to reset...\n");
|
||||
DBG(40, "Scanner not ready (0x%x). Attempting to reset...\n",
|
||||
tmp);
|
||||
scanner_reset(port);
|
||||
/* give it more of a chance to reset in this case */
|
||||
max_cycles = 5;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
count1++;
|
||||
/* Initial line check? */
|
||||
i++;
|
||||
|
||||
/* Send the wakeup sequence */
|
||||
scanner_chessboard_control(port);
|
||||
scanner_chessboard_data(port);
|
||||
expect(port, "Exit Transparent Mode", 0x03, 0x1f, 1000000);
|
||||
scanner_chessboard_data(port, 1);
|
||||
|
||||
if (expect(port, NULL, 0x03, 0x1f, 800000))
|
||||
{
|
||||
/* 630 Style init failed, try 620 style */
|
||||
scanner_chessboard_control(port);
|
||||
scanner_chessboard_data(port, 0);
|
||||
}
|
||||
|
||||
if (expect(port, "Scanner wakeup reply 1", 0x03, 0x1f, 50000))
|
||||
{
|
||||
|
@ -153,18 +166,29 @@ int sanei_canon_pp_wake_scanner(struct parport *port)
|
|||
usleep(100000);
|
||||
}
|
||||
|
||||
} while ((count1 < 3) && (!expect(port, "Scanner wakeup reply 2",
|
||||
} while ((i < max_cycles) && (!expect(port,"Scanner wakeup reply 2",
|
||||
0x03, 0x1f, 100000) == 0));
|
||||
|
||||
/* Block just after chessboarding
|
||||
Reply 1 (S3 and S4 on, S5 and S7 off) */
|
||||
outcont(port, 0, HOSTBUSY); /* C1 off */
|
||||
/* Reply 2 */
|
||||
expect(port, "Reply 2", 12, 0x1f, 800000);
|
||||
/* Reply 2 - If it ain't happening by now, it ain't gonna happen. */
|
||||
if (expect(port, "Reply 2", 0xc, 0x1f, 800000))
|
||||
return -1;
|
||||
outcont(port, HOSTBUSY, HOSTBUSY); /* C1 on */
|
||||
expect(port, "Reply 3", 0x0b, 0x1f, 800000);
|
||||
if (expect(port, "Reply 3", 0x0b, 0x1f, 800000))
|
||||
return -1;
|
||||
outboth(port, 0, NSELECTIN | NINIT | HOSTCLK); /* Clear D, C3+, C1- */
|
||||
|
||||
/* If we had to try the wakeup cycle more than once, we should wait
|
||||
* here for 10 seconds to let the scanner pull itself together -
|
||||
* it can actually take longer, but I can't wait that long! */
|
||||
if (i > 1)
|
||||
{
|
||||
DBG(10, "Had to reset scanner, waiting for the "
|
||||
"head to get back.\n");
|
||||
usleep(10000000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -176,7 +200,7 @@ int sanei_canon_pp_write(struct parport *port, int length, unsigned char *data)
|
|||
#ifdef DUMP_PACKETS
|
||||
ssize_t count;
|
||||
|
||||
DBG(10,"Sent: ");
|
||||
DBG(10,"Sending: ");
|
||||
for (count = 0; count < length; count++)
|
||||
{
|
||||
DBG(10,"%02x ", data[count]);
|
||||
|
@ -204,6 +228,8 @@ int sanei_canon_pp_write(struct parport *port, int length, unsigned char *data)
|
|||
break;
|
||||
}
|
||||
|
||||
DBG(100, "<< write");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -253,7 +279,12 @@ int sanei_canon_pp_read(struct parport *port, int length, unsigned char *data)
|
|||
|
||||
offset = 0;
|
||||
|
||||
DBG(100, "-> ieee_transfer(%d) *\n", length);
|
||||
count = ieee_transfer(port, length, data);
|
||||
DBG(100, "<- (%d)\n", count);
|
||||
/* Early-out if it was not implemented */
|
||||
if (count == E1284_NOTIMPL)
|
||||
return 2;
|
||||
|
||||
length -= count;
|
||||
offset+= count;
|
||||
|
@ -270,7 +301,9 @@ int sanei_canon_pp_read(struct parport *port, int length, unsigned char *data)
|
|||
return 1;
|
||||
}
|
||||
|
||||
DBG(100, "-> ieee_transfer(%d)\n", length);
|
||||
count = ieee_transfer(port, length, data+offset);
|
||||
DBG(100, "<- (%d)\n", count);
|
||||
length-=count;
|
||||
offset+= count;
|
||||
|
||||
|
@ -300,12 +333,13 @@ int sanei_canon_pp_read(struct parport *port, int length, unsigned char *data)
|
|||
|
||||
}
|
||||
|
||||
/* IEEE 1284 defines many values for e,
|
||||
but the FB630P only supports 2: nibble and ECP modes.
|
||||
And no data compression either (argh!)
|
||||
0 = Nibble-mode reverse channel transfer
|
||||
16 = ECP-mode
|
||||
*/
|
||||
/*
|
||||
* IEEE 1284 defines many values for e,
|
||||
* but these scanners only support 2: nibble and ECP modes.
|
||||
* And no data compression either (argh!)
|
||||
* 0 = Nibble-mode reverse channel transfer
|
||||
* 16 = ECP-mode
|
||||
*/
|
||||
static int ieee_negotiation(struct parport *port, int e)
|
||||
{
|
||||
int temp;
|
||||
|
@ -323,18 +357,25 @@ static int ieee_transfer(struct parport *port, int length, unsigned char *data)
|
|||
{
|
||||
int result = 0;
|
||||
|
||||
DBG(200, "IEEE transfer (%i bytes)\n", length);
|
||||
DBG(100, "IEEE transfer (%i bytes)\n", length);
|
||||
|
||||
switch (ieee_mode)
|
||||
{
|
||||
case M1284_BECP:
|
||||
case M1284_ECP:
|
||||
case M1284_ECPRLE:
|
||||
case M1284_ECPSWE:
|
||||
result = ieee1284_ecp_read_data(port, 0, (char *)data,
|
||||
length);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case M1284_NIBBLE:
|
||||
result = ieee1284_nibble_read(port, 0, (char *)data,
|
||||
length);
|
||||
break;
|
||||
default:
|
||||
DBG(1, "Internal error: Wrong mode for transfer.\n"
|
||||
"Please email stauff1@users.sourceforge.net\n"
|
||||
"or kinsei@users.sourceforge.net\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -370,6 +411,11 @@ int sanei_canon_pp_check_status(struct parport *port)
|
|||
DBG(1, "!! Invalid Command - 0x1515\n");
|
||||
return 2;
|
||||
break;
|
||||
case 0x0000:
|
||||
DBG(200, "Nothing - 0x0000");
|
||||
return 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG(1, "!! Unknown status - %04x\n", status);
|
||||
return 100;
|
||||
|
@ -428,13 +474,21 @@ static void scanner_chessboard_control(struct parport *port)
|
|||
usleep(10);
|
||||
}
|
||||
|
||||
static void scanner_chessboard_data(struct parport *port)
|
||||
static void scanner_chessboard_data(struct parport *port, int mode)
|
||||
{
|
||||
int count;
|
||||
|
||||
/* initial weirdness here for 620P - seems to go quite fast,
|
||||
* just ignore it! */
|
||||
|
||||
for (count = 0; count < 2; count++)
|
||||
{
|
||||
/* Wiggle data lines (4 times) while strobing C1 */
|
||||
outdata(port, 0x33);
|
||||
/* 33 here for *30P, 55 for *20P */
|
||||
if (mode)
|
||||
outdata(port, 0x33);
|
||||
else
|
||||
outdata(port, 0x55);
|
||||
outcont(port, HOSTBUSY, HOSTBUSY);
|
||||
usleep(10);
|
||||
outcont(port, 0, HOSTBUSY);
|
||||
|
@ -442,7 +496,10 @@ static void scanner_chessboard_data(struct parport *port)
|
|||
outcont(port, HOSTBUSY, HOSTBUSY);
|
||||
usleep(10);
|
||||
|
||||
outdata(port, 0xcc);
|
||||
if (mode)
|
||||
outdata(port, 0xcc);
|
||||
else
|
||||
outdata(port, 0xaa);
|
||||
outcont(port, HOSTBUSY, HOSTBUSY);
|
||||
usleep(10);
|
||||
outcont(port, 0, HOSTBUSY);
|
||||
|
@ -456,6 +513,7 @@ static void scanner_chessboard_data(struct parport *port)
|
|||
static int scanner_reset(struct parport *port)
|
||||
{
|
||||
|
||||
/* Resetting only works for the *30Ps, sorry */
|
||||
if (readstatus(port) == 0x0b)
|
||||
{
|
||||
/* Init Block 1 - composed of a 0-byte IEEE read */
|
||||
|
@ -463,74 +521,54 @@ static int scanner_reset(struct parport *port)
|
|||
ieee1284_terminate(port);
|
||||
ieee_negotiation(port, 0x0);
|
||||
ieee1284_terminate(port);
|
||||
scanner_chessboard_data(port);
|
||||
scanner_chessboard_data(port);
|
||||
scanner_chessboard_data(port);
|
||||
scanner_chessboard_data(port);
|
||||
scanner_chessboard_data(port);
|
||||
scanner_chessboard_data(port, 1);
|
||||
scanner_chessboard_data(port, 1);
|
||||
scanner_chessboard_data(port, 1);
|
||||
scanner_chessboard_data(port, 1);
|
||||
|
||||
/* Reset Block 2 =============== */
|
||||
outboth(port, 0x04, 0x0d);
|
||||
|
||||
/* Specifically, we want this: 00111 on S */
|
||||
if (expect(port, "Reset 2 response 1", 0x7, 0x1f, 500000))
|
||||
return 1;
|
||||
|
||||
outcont(port, 0, HOSTCLK);
|
||||
usleep(5);
|
||||
outcont(port, 0x0f, 0xf); /* All lines must be 1. */
|
||||
|
||||
/* All lines 1 */
|
||||
if (expect(port, "Reset 2 response 2 (READY)",
|
||||
0x1f, 0x1f, 500000))
|
||||
return 1;
|
||||
|
||||
outcont(port, 0, HOSTBUSY);
|
||||
usleep(100000); /* a short pause */
|
||||
outcont(port, HOSTBUSY, HOSTBUSY | NSELECTIN);
|
||||
scanner_chessboard_data(port, 0);
|
||||
scanner_chessboard_data(port, 0);
|
||||
scanner_chessboard_data(port, 0);
|
||||
scanner_chessboard_data(port, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
outboth(port, 0x04, 0x0d);
|
||||
|
||||
/* Specifically, we want this: 00111 on S */
|
||||
if (expect(port, "Reset 2 response 1", 0x7, 0x1f, 500000))
|
||||
return 1;
|
||||
/* Reset Block 2 =============== */
|
||||
outboth(port, 0x04, 0x0d);
|
||||
|
||||
outcont(port, 0, HOSTCLK);
|
||||
usleep(5);
|
||||
outcont(port, 0x0f, 0xf); /* All lines must be 1. */
|
||||
/* Specifically, we want this: 00111 on S */
|
||||
if (expect(port, "Reset 2 response 1", 0x7, 0x1f, 500000))
|
||||
return 1;
|
||||
|
||||
/* All lines 1 */
|
||||
if (expect(port, "Reset 2 response 2 (READY)",
|
||||
0x1f, 0x1f, 500000))
|
||||
return 1;
|
||||
outcont(port, 0, HOSTCLK);
|
||||
usleep(5);
|
||||
outcont(port, 0x0f, 0xf); /* All lines must be 1. */
|
||||
|
||||
outcont(port, 0, HOSTBUSY);
|
||||
usleep(100000); /* a short pause */
|
||||
outcont(port, HOSTBUSY, HOSTBUSY | NSELECTIN);
|
||||
}
|
||||
/* All lines 1 */
|
||||
if (expect(port, "Reset 2 response 2 (READY)",
|
||||
0x1f, 0x1f, 500000))
|
||||
return 1;
|
||||
|
||||
outcont(port, 0, HOSTBUSY);
|
||||
usleep(100000); /* a short pause */
|
||||
outcont(port, HOSTBUSY, HOSTBUSY | NSELECTIN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A timed version of expect, which will wait for delay before erroring
|
||||
This is the one and only one we should be using */
|
||||
static int expect(struct parport *port, const char *step, int s,
|
||||
static int expect(struct parport *port, const char *msg, int s,
|
||||
int mask, unsigned int delay)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
/*remove warnings*/
|
||||
step=step;
|
||||
|
||||
tv.tv_sec = delay / 1000000;
|
||||
tv.tv_usec = delay % 1000000;
|
||||
|
||||
if (ieee1284_wait_status(port, mask << 3, s << 3, &tv))
|
||||
{
|
||||
DBG(10, "Timeout: %s (0x%02x in 0x%02x) - Status = "
|
||||
"0x%02x\n", step, s, mask, readstatus(port));
|
||||
if (msg) DBG(10, "Timeout: %s (0x%02x in 0x%02x) - Status "
|
||||
"= 0x%02x\n", msg, s, mask, readstatus(port));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -550,25 +588,27 @@ int sanei_canon_pp_scanner_init(struct parport *port)
|
|||
scanner_endtransfer(port);
|
||||
|
||||
/* In Windows, this is always ECP (or an attempt at it) */
|
||||
sanei_canon_pp_write(port, 10, command_1);
|
||||
if (sanei_canon_pp_write(port, 10, cmd_init))
|
||||
return -1;
|
||||
/* Note that we don't really mind what the status was as long as it
|
||||
* wasn't a read error (returns -1) */
|
||||
/* In fact, the 620P gives an error on that last command, but they
|
||||
* keep going anyway */
|
||||
if (sanei_canon_pp_check_status(port) < 0)
|
||||
return -1;
|
||||
|
||||
/* Try until it's ready */
|
||||
sanei_canon_pp_write(port, 10, command_1);
|
||||
sanei_canon_pp_write(port, 10, cmd_init);
|
||||
while ((tries < 3) && (tmp = sanei_canon_pp_check_status(port)))
|
||||
{
|
||||
if (tmp < 0)
|
||||
return -1;
|
||||
DBG(10, "scanner_init: Giving the scanner a snooze "
|
||||
"(sleeping for 4 seconds)\n");
|
||||
usleep(4000000);
|
||||
DBG(10, "scanner_init: Giving the scanner a snooze...\n");
|
||||
usleep(500000);
|
||||
|
||||
tries++;
|
||||
|
||||
sanei_canon_pp_write(port, 10, command_1);
|
||||
sanei_canon_pp_write(port, 10, cmd_init);
|
||||
}
|
||||
|
||||
if (tries == 3) return 1;
|
||||
|
|
|
@ -111,8 +111,8 @@ static const SANE_String_Const cmodes[] = { "Greyscale", "Colour", NULL };
|
|||
/* bit depths */
|
||||
static const SANE_String_Const depths[] = { "8", "12", NULL };
|
||||
/* resolutions */
|
||||
static const SANE_Int res330[] = {3, 75, 150, 300};
|
||||
static const SANE_Int res630[] = {4, 75, 150, 300, 600};
|
||||
static const SANE_Int res300[] = {3, 75, 150, 300};
|
||||
static const SANE_Int res600[] = {4, 75, 150, 300, 600};
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -571,9 +571,9 @@ sane_open (SANE_String_Const name, SANE_Handle *h)
|
|||
/* Resolution - determined by magic number */
|
||||
|
||||
if (cs->params.scanheadwidth == 2552)
|
||||
cs->opt[OPT_RESOLUTION].constraint.word_list = res330;
|
||||
cs->opt[OPT_RESOLUTION].constraint.word_list = res300;
|
||||
else
|
||||
cs->opt[OPT_RESOLUTION].constraint.word_list = res630;
|
||||
cs->opt[OPT_RESOLUTION].constraint.word_list = res600;
|
||||
|
||||
|
||||
/* TL-X */
|
||||
|
@ -593,7 +593,7 @@ sane_open (SANE_String_Const name, SANE_Handle *h)
|
|||
/* BR-X */
|
||||
if(!(tmp_range = malloc(sizeof(*tmp_range))))
|
||||
return SANE_STATUS_NO_MEM;
|
||||
(*tmp_range).min = 22;
|
||||
(*tmp_range).min = 3;
|
||||
(*tmp_range).max = 216;
|
||||
cs->opt[OPT_BR_X].constraint.range = tmp_range;
|
||||
|
||||
|
@ -714,7 +714,7 @@ sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act,
|
|||
depths[cs->vals[opt]]);
|
||||
break;
|
||||
case OPT_RESOLUTION:
|
||||
*((int *)val) = res630[cs->vals[opt]];
|
||||
*((int *)val) = res600[cs->vals[opt]];
|
||||
break;
|
||||
default:
|
||||
*((int *)val) = cs->vals[opt];
|
||||
|
@ -736,13 +736,13 @@ sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act,
|
|||
constraint.word_list[0];
|
||||
|
||||
while ((cs->vals[opt] <= maxresi) &&
|
||||
(res630[cs->vals[opt]]
|
||||
(res600[cs->vals[opt]]
|
||||
< *((int *)val)))
|
||||
{
|
||||
cs->vals[opt] += 1;
|
||||
}
|
||||
|
||||
if (res630[cs->vals[opt]] !=
|
||||
if (res600[cs->vals[opt]] !=
|
||||
*((int *)val))
|
||||
{
|
||||
if (info != NULL) *info |=
|
||||
|
@ -866,9 +866,9 @@ sane_get_parameters (SANE_Handle h, SANE_Parameters *params)
|
|||
return SANE_STATUS_INVAL;
|
||||
}
|
||||
|
||||
/* We use 630 res list here because the 330 res list is just a shorter
|
||||
/* We use 600 res list here because the 300 res list is just a shorter
|
||||
* version, so this will always work. */
|
||||
res = res630[cs->vals[OPT_RESOLUTION]];
|
||||
res = res600[cs->vals[OPT_RESOLUTION]];
|
||||
|
||||
/*
|
||||
* These don't change whether we're scanning or not
|
||||
|
@ -889,8 +889,8 @@ sane_get_parameters (SANE_Handle h, SANE_Parameters *params)
|
|||
/* x values have to be divisible by 4 (round down) */
|
||||
params->pixels_per_line -= (params->pixels_per_line%4);
|
||||
|
||||
/* Can't scan nothing */
|
||||
if (!(params->pixels_per_line)) params->pixels_per_line = 4;
|
||||
/* Can't scan less than 64 */
|
||||
if (params->pixels_per_line < 64) params->pixels_per_line = 64;
|
||||
|
||||
max_width = cs->params.scanheadwidth / (max_res / res);
|
||||
|
||||
|
@ -966,9 +966,9 @@ sane_start (SANE_Handle h)
|
|||
}
|
||||
|
||||
|
||||
/* We use 630 res list here because the 330 res list is just a shorter
|
||||
/* We use 600 res list here because the 300 res list is just a shorter
|
||||
* version, so this will always work. */
|
||||
res = res630[cs->vals[OPT_RESOLUTION]];
|
||||
res = res600[cs->vals[OPT_RESOLUTION]];
|
||||
|
||||
/* Copy the options stored in the vals into the scaninfo */
|
||||
cs->scan.width = ((cs->vals[OPT_BR_X] - cs->vals[OPT_TL_X]) * res)
|
||||
|
@ -993,16 +993,18 @@ sane_start (SANE_Handle h)
|
|||
cs->scan.width -= (cs->scan.width%4);
|
||||
cs->scan.xoffset -= (cs->scan.xoffset%4);
|
||||
|
||||
/* Can't scan nothing */
|
||||
if (!(cs->scan.width)) cs->scan.width = 4;
|
||||
/* Can't scan less than 64 */
|
||||
if (cs->scan.width < 64) cs->scan.width = 64;
|
||||
|
||||
max_width = cs->params.scanheadwidth / (max_res / res);
|
||||
|
||||
max_height = (cs->params.scanheadwidth == 2552 ? 3508 : 7016) /
|
||||
(max_res / res);
|
||||
|
||||
if(cs->scan.width > max_width) cs->scan.width = max_width;
|
||||
if(cs->scan.height > max_height) cs->scan.height = max_height;
|
||||
if (cs->scan.width > max_width) cs->scan.width = max_width;
|
||||
if (cs->scan.width + cs->scan.xoffset > max_width) cs->scan.xoffset =
|
||||
max_width - cs->scan.width;
|
||||
if (cs->scan.height > max_height) cs->scan.height = max_height;
|
||||
|
||||
/* We pass a value to init_scan which is the power of 2 that 75
|
||||
* is multiplied by for the resolution. ie:
|
||||
|
@ -1355,7 +1357,7 @@ sane_cancel (SANE_Handle h)
|
|||
cs->lines_scanned = 0;
|
||||
cs->bytes_sent = 0;
|
||||
DBG(2, "sane_cancel: >> abort_scan\n");
|
||||
tmp = sanei_canon_pp_abort_scan(&(cs->params), &(cs->scan));
|
||||
tmp = sanei_canon_pp_abort_scan(&(cs->params));
|
||||
DBG(2, "sane_cancel: << abort_scan\n");
|
||||
if (tmp != 0) {
|
||||
DBG(1, "sane_cancel: WARNING: abort_scan returned %d!", tmp);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
:backend "canon_pp" ; name of backend
|
||||
:manpage "sane-canon_pp"
|
||||
:version "0.3" ; version of backend
|
||||
:version "0.2" ; version of backend
|
||||
:status :alpha ; :alpha, :beta, :stable, :new
|
||||
|
||||
:url "http://canon-fb330p.sourceforge.net" ; backend home page
|
||||
|
@ -19,6 +19,9 @@
|
|||
|
||||
:mfg "Canon" ; name a manufacturer
|
||||
:url "http://www.canon.com/"
|
||||
:model "CanoScan FB620P" ; name models for above-specified mfg.
|
||||
:interface "Parport (ECP)"
|
||||
:comment "newly added support"
|
||||
:model "CanoScan FB330P" ; name models for above-specified mfg.
|
||||
:interface "Parport (ECP)"
|
||||
:comment "1 pass; flatbed scanner"
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
.TH sane-canon_pp 5 "7 April 2002"
|
||||
.TH sane-canon_pp 5 "1 September 2002"
|
||||
.IX sane-canon_pp
|
||||
.SH NAME
|
||||
sane-canon_pp - SANE backend for Canon Parallel Port flatbed scanners
|
||||
sane-canon_pp - SANE backend for Canon CanoScan Parallel Port flatbed scanners
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.B sane-canon_pp
|
||||
library implements a SANE (Scanner Access Now Easy) backend that
|
||||
provides access to the following Canon flatbed scanners:
|
||||
library implements a SANE (Scanner Access Now Easy) backend that provides
|
||||
access to the following Canon flatbed scanners:
|
||||
.PP
|
||||
.RS
|
||||
CanoScan FB620P
|
||||
.br
|
||||
CanoScan FB330P
|
||||
.br
|
||||
CanoScan FB630P
|
||||
|
@ -21,12 +23,12 @@ CanoScan N640P ex
|
|||
.br
|
||||
.RE
|
||||
.PP
|
||||
No USB scanners are supported and there are no plans to support them in
|
||||
the future. Other projects are working on support for USB scanners. See the
|
||||
No USB scanners are supported and there are no plans to support them in the
|
||||
future. Other projects are working on support for USB scanners. See the
|
||||
.B PROJECTS
|
||||
file for more detail. We cannot add support for the FB310P or FB320P at the
|
||||
moment, but contact us if you have one of these scanners and would really like
|
||||
to help.
|
||||
file for more detail. The FB320P may also work, let us know if it does. We
|
||||
cannot add support for the FB310P and FB610P at the moment, but contact us if
|
||||
you have one of these scanners and would really like to help.
|
||||
.PP
|
||||
IMPORTANT: this is alpha code. While we have made every effort to make it as
|
||||
reliable as possible, it will not always work as expected. Feedback is still
|
||||
|
@ -38,7 +40,8 @@ below).
|
|||
.
|
||||
.PP
|
||||
.SH "DEVICE NAMES"
|
||||
This backend expects device names of the form presented by libieee1284. These names are highly dependant on operating system and version.
|
||||
This backend expects device names of the form presented by libieee1284. These
|
||||
names are highly dependant on operating system and version.
|
||||
|
||||
On Linux 2.4 kernels this will be of the form
|
||||
.I "parport0"
|
||||
|
@ -48,8 +51,8 @@ or older (2.2 and before) kernels may produce names like
|
|||
.IR "0"
|
||||
depending on your module configuration. Check the contents of
|
||||
.I /proc/parport
|
||||
if it exists. If you don't want to specify a default port (or don't know
|
||||
its name), the backend should be able to detect which port your scanner is on.
|
||||
if it exists. If you don't want to specify a default port (or don't know its
|
||||
name), the backend should be able to detect which port your scanner is on.
|
||||
|
||||
.SH CONFIGURATION
|
||||
The contents of the
|
||||
|
@ -82,16 +85,17 @@ character is acceptable and will be expaned to the value of the HOME environment
|
|||
|
||||
Option
|
||||
.B force_nibble
|
||||
forces the driver to use nibble mode even if ECP mode is reported to work
|
||||
by libieee1284. This works-around the rare issue of ECP mode being reported to
|
||||
forces the driver to use nibble mode even if ECP mode is reported to work by
|
||||
libieee1284. This works-around the rare issue of ECP mode being reported to
|
||||
work by the library, then not working.
|
||||
|
||||
.SH TIPS
|
||||
.PP
|
||||
Hit the "Calibrate" button before scanning. It vastly improves the quality
|
||||
of scans.
|
||||
Hit the "Calibrate" button before scanning. It vastly improves the quality of
|
||||
scans.
|
||||
.PP
|
||||
To enable automatic detection of your scanner, uncomment the "canon_pp" line from
|
||||
To enable automatic detection of your scanner, uncomment the "canon_pp" line
|
||||
from
|
||||
.I @CONFIGDIR@/dll.conf
|
||||
.PP
|
||||
.SH FILES
|
||||
|
@ -105,28 +109,27 @@ below).
|
|||
The static library implementing this backend.
|
||||
.TP
|
||||
.I @LIBDIR@/libsane-canon_pp.so
|
||||
The shared library implementing this backend (present on systems that
|
||||
support dynamic loading).
|
||||
The shared library implementing this backend (present on systems that support
|
||||
dynamic loading).
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B SANE_CONFIG_DIR
|
||||
This environment variable specifies the list of directories that may
|
||||
contain the configuration file. Under UNIX, the directories are
|
||||
separated by a colon (`:'), under OS/2, they are separated by a
|
||||
semi-colon (`;'). If this variable is not set, the configuration file
|
||||
is searched in two default directories: first, the current working
|
||||
directory (".") and then in @CONFIGDIR@. If the value of the
|
||||
environment variable ends with the directory separator character, then
|
||||
the default directories are searched after the explicitly specified
|
||||
This environment variable specifies the list of directories that may contain
|
||||
the configuration file. Under UNIX, the directories are separated by a colon
|
||||
(`:'), under OS/2, they are separated by a semi-colon (`;'). If this variable
|
||||
is not set, the configuration file is searched in two default directories:
|
||||
first, the current working directory (".") and then in @CONFIGDIR@. If the
|
||||
value of the environment variable ends with the directory separator character,
|
||||
then the default directories are searched after the explicitly specified
|
||||
directories. For example, setting
|
||||
.B SANE_CONFIG_DIR
|
||||
to "/tmp/config:" would result in directories "tmp/config", ".", and
|
||||
"@CONFIGDIR@" being searched (in this order).
|
||||
.TP
|
||||
.B SANE_DEBUG_CANON_PP
|
||||
If the library was compiled with debug support enabled, this
|
||||
environment variable controls the debug level for this backend. Higher
|
||||
debug levels increase the verbosity of the output.
|
||||
If the library was compiled with debug support enabled, this environment
|
||||
variable controls the debug level for this backend. Higher debug levels
|
||||
increase the verbosity of the output.
|
||||
|
||||
Example:
|
||||
export SANE_DEBUG_CANON_PP=4
|
||||
|
@ -134,14 +137,14 @@ export SANE_DEBUG_CANON_PP=4
|
|||
.B Features available in the Windows interface
|
||||
.TP
|
||||
.B Brightness and Contrast
|
||||
These are not implemented, and probably never will be. These
|
||||
appear to be implented entirely in software. Use GIMP or a similar program if
|
||||
you need these features.
|
||||
These are not implemented, and probably never will be. These appear to be
|
||||
implented entirely in software. Use GIMP or a similar program if you need
|
||||
these features.
|
||||
.TP
|
||||
.B Descreen Mode
|
||||
This appears on our first analysis to be just oversampling with an
|
||||
anti-aliasing filter. Again, it seems to be implemeneted entirely in
|
||||
software, so GIMP is your best bet for now.
|
||||
anti-aliasing filter. Again, it seems to be implemeneted entirely in software,
|
||||
so GIMP is your best bet for now.
|
||||
.TP
|
||||
.B Gamma Tables
|
||||
This is under investigation, but for now only a simple gamma profile (ie: the
|
||||
|
@ -171,18 +174,18 @@ Sometimes at high resolutions (ie. 600dpi) you will notice lines which appear
|
|||
twice. These lines correspond to points where the scanner head has stopped
|
||||
during the scan (it stops every time the internal 64kb buffer is full).
|
||||
Basically it's a mechanical problem inside the scanner, that the tolerance of
|
||||
movement for a start/stop event is greater than 1/600 inches. I've never
|
||||
tried the windows driver so I'm not sure how (or if) it works around
|
||||
this problem, but as we don't know how to rewind the scanner head to do these
|
||||
bits again, there's currently no nice way to deal with the problem.
|
||||
movement for a start/stop event is greater than 1/600 inches. I've never tried
|
||||
the windows driver so I'm not sure how (or if) it works around this problem,
|
||||
but as we don't know how to rewind the scanner head to do these bits again,
|
||||
there's currently no nice way to deal with the problem.
|
||||
.PP
|
||||
.B Greyscale Scans
|
||||
.PP
|
||||
Be aware that the scanner uses the green LEDs to read greyscale scans,
|
||||
meaning green coloured things will appear lighter than normal, and red
|
||||
and blue coloured items will appear darker than normal. For high-accuracy
|
||||
greyscale scans of colour items, it's best just to scan in colour and convert
|
||||
to greyscale in graphics software such as the GIMP.
|
||||
Be aware that the scanner uses the green LEDs to read greyscale scans, meaning
|
||||
green coloured things will appear lighter than normal, and red and blue
|
||||
coloured items will appear darker than normal. For high-accuracy greyscale
|
||||
scans of colour items, it's best just to scan in colour and convert to
|
||||
greyscale in graphics software such as the GIMP.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
sane(7), sane-dll(5)
|
||||
|
|
Ładowanie…
Reference in New Issue