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