summaryrefslogtreecommitdiff
path: root/backend/kodakaio.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/kodakaio.c')
-rw-r--r--backend/kodakaio.c416
1 files changed, 306 insertions, 110 deletions
diff --git a/backend/kodakaio.c b/backend/kodakaio.c
index 8c4583a..e98208f 100644
--- a/backend/kodakaio.c
+++ b/backend/kodakaio.c
@@ -1,7 +1,7 @@
/*
* kodakaio.c - SANE library for Kodak ESP Aio scanners.
*
- * Copyright (C) 2011-2013 Paul Newall
+ * Copyright (C) 2011-2015 Paul Newall
*
* Based on the Magicolor sane backend:
* Based on the epson2 sane backend:
@@ -14,19 +14,32 @@
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
- * Using avahi now 25/11/12 for net autodiscovery. Use configure option --enable-avahi
+ * Modified 30/12/14 to fix bug where network connection was broken after 30s of idle time.
+ * The connection is now made in sane_start and ended in sane_cancel.
* 01/01/13 Now with adf, the scan can be padded to make up the full page length,
* or the page can terminate at the end of the paper. This is a selectable option.
+ * 25/11/12 Using avahi now for net autodiscovery. Use configure option --enable-avahi
*/
-/* convenient lines to paste
-export SANE_DEBUG_KODAKAIO=10
+/*
+Packages to add to a clean ubuntu install
+libavahi-common-dev
+libusb-dev
+libsnmp-dev
+
+convenient lines to paste
+export SANE_DEBUG_KODAKAIO=20
for ubuntu prior to 12.10
-./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS=kodakaio
+./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS="kodakaio test"
for ubuntu 12.10
-./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS=kodakaio
+./configure --prefix=/usr --libdir=/usr/lib/i386-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS="kodakaio test"
+
+for ubuntu 14.10
+./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --sysconfdir=/etc --localstatedir=/var --enable-avahi --disable-latex BACKENDS="kodakaio test"
+
+If you want to use the test backend, for example with sane-troubleshoot, you should enable it in /etc/sane.d/dll.conf
*/
@@ -50,20 +63,14 @@ for ubuntu 12.10
*/
/* FUNCTION-TREE
sane_init
- sane_start
- k_init_parametersta
- k_lock_scanner
- k_set_scanning_parameters
- print_params
- k_start_scan
- cmd_start_scan
- print_status
- k_send
- kodakaio_txrxack
sane_open
device_detect
+ k_dev_init
+ open_scanner
+ close_scanner
sane_get_devices
init_options
+ (open_scanner - moved to sane_start 27/12/14 )
sane_control_option
getvalue
setvalue
@@ -71,6 +78,18 @@ for ubuntu 12.10
change_source
activateOption
deactivateOption
+ sane_start
+ open_scanner
+ k_init_parametersta
+ k_lock_scanner
+ k_hello
+ k_set_scanning_parameters
+ print_params
+ k_start_scan
+ cmd_start_scan
+ print_status
+ k_send
+ kodakaio_txrxack
sane_get_parameters
print_params
sane_read
@@ -78,6 +97,11 @@ for ubuntu 12.10
cmd_read_data (reads one block)
k_recv
cmp_array
+ sane_cancel
+ cmd_cancel_scan
+ close_scanner
+ sane_close
+ (close_scanner - moved to sane_cancel 27/12/14)
sane_exit
free_devices
k_recv
@@ -89,7 +113,9 @@ for ubuntu 12.10
open_scanner
sanei_kodakaio_net_open
close_scanner
- sanei_kodakaio_net_close
+ k_scan_finish
+ cmd_cancel_scan
+ sanei_kodakaio_net_close or sanei_usb_close
detect_usb
kodakaio_getNumberOfUSBProductIds
attach_one_config - (Passed to sanei_configure_attach)
@@ -126,8 +152,8 @@ for ubuntu 12.10
#define KODAKAIO_VERSION 02
-#define KODAKAIO_REVISION 4
-#define KODAKAIO_BUILD 6
+#define KODAKAIO_REVISION 7
+#define KODAKAIO_BUILD 2
/* for usb (but also used for net though it's not required). */
#define MAX_BLOCK_SIZE 32768
@@ -214,10 +240,12 @@ static int K_SNMP_Timeout = 3000; /* used for any auto detection method */
static int K_Scan_Data_Timeout = 10000;
static int K_Request_Timeout = 5000;
+static int bitposn=0; /* used to pack bits into bytes in lineart mode */
+
/* This file is used to store directly the raster returned by the scanner for debugging
If RawScanPath has no length it will not be created */
FILE *RawScan = NULL;
-/* example: unsigned char RawScanPath[] = "TestRawScan.pgm"; */
+/* example: char RawScanPath[] = "TestRawScan.pgm"; */
char RawScanPath[] = ""; /* empty path means no raw scan file is made */
/*
@@ -566,16 +594,17 @@ commandtype, max depth, pointer to depth list
* The depth variable gets updated when the bit depth is modified.
*/
+/* could be affecting what data sane delivers */
static struct mode_param mode_params[] = {
- /* {0x00, 1, 1}, // Lineart, 1 color, 1 bit */
+ {0x03, 3, 24}, /* Color, 3 colors, 24 bit */
{0x02, 1, 8}, /* Grayscale, 1 color, 8 bit */
- {0x03, 3, 24} /* Color, 3 colors, 24 bit */
+ {0x00, 1, 1} /* Lineart, 1 color, 8 bit (was 8 bit) */
};
static SANE_String_Const mode_list[] = {
- /* SANE_VALUE_SCAN_MODE_LINEART, */
- SANE_VALUE_SCAN_MODE_GRAY,
SANE_VALUE_SCAN_MODE_COLOR,
+ SANE_VALUE_SCAN_MODE_GRAY,
+ SANE_VALUE_SCAN_MODE_LINEART,
NULL
};
@@ -602,6 +631,9 @@ static SANE_String_Const source_list[] = {
NULL
};
+static const SANE_Range percent_range_fixed = {SANE_FIX(0.0), SANE_FIX(100.0), SANE_FIX(1.0)};
+static const SANE_Range percent_range_int = {0, 100, 1};
+
/* prototypes */
static SANE_Status attach_one_usb(SANE_String_Const devname);
static SANE_Status attach_one_net(SANE_String_Const devname, unsigned int device);
@@ -659,11 +691,12 @@ print_status(KodakAio_Scanner *s,int level)
/****************************************************************************
* Low-level Network communication functions ****************************************************************************/
-/* We don't have a packet wrapper, which holds packet size etc., so we
- don't have to use a *read_raw and a *_read function... */
static int
kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted,
SANE_Status * status)
+/* there seems to be a condition where this returns no error and no data without detecting a timeout
+That is probably if the scanner disconnected the network connection
+*/
{
size_t size, read = 0;
struct pollfd fds[1];
@@ -676,7 +709,7 @@ kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted,
fds[0].events = POLLIN;
fds[0].revents = 0;
if ((pollreply = poll (fds, 1, K_Request_Timeout)) <= 0) {
- if (pollreply ==0)
+ if (pollreply == 0)
DBG(1, "net poll timeout\n");
else
/* pollreply is -ve */
@@ -684,21 +717,22 @@ kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted,
*status = SANE_STATUS_IO_ERROR;
return read;
}
- else if(fds[0].revents & POLLIN) {
+ else if((fds[0].revents & POLLIN) && !(fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))) {
while (read < wanted) {
+ DBG(50, "reading: read %d, wanted %d\n",read, wanted);
size = sanei_tcp_read(s->fd, buf + read, wanted - read);
-
- if (size == 0)
- break;
-
+ if (size == 0) {
+ DBG(1, "No data read. Scanner may have disconnected\n");
+ break;
+ }
read += size;
}
-/* this error removed 28/12/12 because adf scans end with less data than wanted
- if (read < wanted)
+ if (read == 0)
*status = SANE_STATUS_IO_ERROR;
- */
+
DBG(32, "net read %d bytes:%x,%x,%x,%x,%x,%x,%x,%x\n",read,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
+
return read;
}
else
@@ -706,7 +740,7 @@ kodakaio_net_read(struct KodakAio_Scanner *s, unsigned char *buf, size_t wanted,
return read;
}
-/* kodak does not pad commands like magicolor, so there's only a write_raw function */
+
static int
sanei_kodakaio_net_write_raw(struct KodakAio_Scanner *s,
const unsigned char *buf, size_t buf_size,
@@ -832,6 +866,7 @@ k_recv(KodakAio_Scanner * s, void *buf, ssize_t buf_size,
this function called by a number of others
In USB mode, this function will wait until data is available for a maximum of SCANNER_READ_TIMEOUT seconds.
+In NET mode the timeout is in kodakaio_net_read
*/
ssize_t n = 0;
char fmt_buf[25];
@@ -847,6 +882,10 @@ In USB mode, this function will wait until data is available for a maximum of SC
DBG(min(16,DBG_READ), "[%ld] %s: net req size = %ld ", (long) time_start, __func__, (long) buf_size);
n = kodakaio_net_read(s, buf, buf_size, status);
DBG(min(16,DBG_READ), "returned %d\n", n);
+ if (*status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: err returned from kodakaio_net_read, %s\n", __func__, sane_strstatus(*status));
+ }
+
} else if (s->hw->connection == SANE_KODAKAIO_USB) {
/* Start the clock for USB timeout */
@@ -922,17 +961,30 @@ kodakaio_txrx(KodakAio_Scanner *s, unsigned char *txbuf, unsigned char *rxbuf)
/* Sends 8 byte data to scanner and returns reply and appropriate status. */
{
SANE_Status status;
+ ssize_t n = 0;
k_send(s, txbuf, 8, &status);
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s: tx err, %s\n", __func__, sane_strstatus(status));
return status;
}
- k_recv(s, rxbuf, 8, &status);
+ n = k_recv(s, rxbuf, 8, &status);
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status));
return status;
}
+ if (n == 0) {
+ DBG(1, "%s: try 1 k_recv returned 0 bytes with status %s\n", __func__, sane_strstatus(status));
+ n = k_recv(s, rxbuf, 8, &status);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: %s gave rx err, %s\n", __func__, "txvalue", sane_strstatus(status));
+ return status;
+ }
+ if (n == 0) {
+ DBG(1, "%s: try 2 k_recv returned 0 bytes with status %s\n", __func__, sane_strstatus(status));
+ return status;
+ }
+ }
return status;
}
@@ -962,7 +1014,8 @@ and returns appropriate status
s->adf_loaded = SANE_TRUE;
DBG(5, "%s: News - docs in ADF\n", __func__);
}
- else if (rxbuf[4] != 0x01 && s->adf_loaded == SANE_TRUE) {
+ else if (rxbuf[4] !=
+0x01 && s->adf_loaded == SANE_TRUE) {
s->adf_loaded = SANE_FALSE;
DBG(5, "%s: News - ADF is empty\n", __func__);
}
@@ -976,6 +1029,25 @@ and returns appropriate status
return status;
}
+static ssize_t
+kodakaio_rxflush(KodakAio_Scanner *s)
+/*
+Tries to get 64 byte reply
+and returns number of bytes read
+*/
+{
+ SANE_Status status;
+ unsigned char rxbuf[64];
+ ssize_t n = 0;
+
+ n = k_recv(s, rxbuf, 64, &status);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: %s gave rx err, %s\n", __func__, "status", sane_strstatus(status));
+ }
+ DBG(5, "%s: flushed, %d bytes\n", __func__, (int)n);
+ return n;
+}
+
/*
* high-level communication commands
*/
@@ -988,6 +1060,13 @@ k_hello (KodakAio_Scanner * s)
char fmt_buf[25];
DBG(5, "%s\n", __func__);
+
+/* check that there is nothing already in the input buffer before starting
+kodakaio_rxflush(s);
+*/
+/* preset the reply, so I can see if it gets changed */
+reply[0] = 0; reply[1] = 1; reply[2] = 2; reply[3] = 3; reply[4] = 4; reply[5] = 5; reply[6] = 6; reply[7] = 7;
+
if((status = kodakaio_txrx(s, KodakEsp_V, reply))!= SANE_STATUS_GOOD) {
DBG(1, "%s: KodakEsp_V failure, %s\n", __func__, sane_strstatus(status));
return SANE_STATUS_IO_ERROR;
@@ -998,6 +1077,8 @@ k_hello (KodakAio_Scanner * s)
DBG(1, "%s: KodakEsp_v err, got %s\n", __func__, fmt_buf);
return SANE_STATUS_IO_ERROR;
}
+
+
DBG(5, "%s: OK %s\n", __func__, sane_strstatus(status));
return status;
}
@@ -1045,12 +1126,24 @@ cmd_cancel_scan (SANE_Handle handle)
unsigned char reply[8];
/* adf added 20/2/12 should it be adf? or adf with paper in? */
if (strcmp(source_list[s->val[OPT_SOURCE].w], ADF_STR) == 0) { /* adf */
- if (kodakaio_txrxack(s, KodakEsp_F, reply)!= SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR;
- if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR;
+ if (kodakaio_txrxack(s, KodakEsp_F, reply)!= SANE_STATUS_GOOD)
+ {
+ DBG(1, "%s: KodakEsp_F command failed\n", __func__);
+ return SANE_STATUS_IO_ERROR;
+ }
+ if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD)
+ {
+ DBG(1, "%s: KodakEsp_UnLock command failed\n", __func__);
+ return SANE_STATUS_IO_ERROR;
+ }
DBG(5, "%s unlocked the scanner with adf F U\n", __func__);
}
else { /* no adf */
- if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD) return SANE_STATUS_IO_ERROR;
+ if (kodakaio_txrxack(s, KodakEsp_UnLock, reply)!= SANE_STATUS_GOOD)
+ {
+ DBG(1, "%s: KodakEsp_UnLock command failed\n", __func__);
+ return SANE_STATUS_IO_ERROR;
+ }
DBG(5, "%s unlocked the scanner U\n", __func__);
}
s->scanning = SANE_FALSE;
@@ -1084,6 +1177,7 @@ Old mc cmd read this stuff from the scanner. I don't think kodak can do that eas
return status;
}
+/* Set color curve command, low level, sends commands to the scanner*/
static SANE_Status
cmd_set_color_curve(SANE_Handle handle, unsigned char col)
{
@@ -1093,11 +1187,12 @@ cmd_set_color_curve(SANE_Handle handle, unsigned char col)
unsigned char tx_col[8];
unsigned char rx[8];
unsigned char tx_curve[256];
- unsigned char i;
+ int i; /* 7/9/14 was unsigned char and that stopped the loop that made the linear curve from going to 255 */
DBG(32, "%s: start\n", __func__);
tx_col[0]=0x1b; tx_col[1]='S'; tx_col[2]='K'; tx_col[3]=col; tx_col[4]=0; tx_col[5]=0; tx_col[6]=0; tx_col[7]=0;
/* linear curve now but could send tailor made curves in future */
- for(i=0;i<255;++i) tx_curve[i]=i;
+ for(i=0;i<=255;++i) tx_curve[i]=i; /* 7/9/14 was i<255 the missing elements caused speckles */
+
k_send(s, tx_col, 8, &status);
if (status != SANE_STATUS_GOOD) {
DBG(1, "%s: tx err, %s\n", __func__, "curve command");
@@ -1113,7 +1208,7 @@ cmd_set_color_curve(SANE_Handle handle, unsigned char col)
return status;
}
-/* Set scanning parameters command low level */
+/* Set scanning parameters command, low level, sends commands to the scanner*/
static SANE_Status
cmd_set_scanning_parameters(SANE_Handle handle,
int resolution,
@@ -1210,8 +1305,6 @@ unsigned int i;
return 0;
}
-
-
static SANE_Status
cmd_read_data (SANE_Handle handle, unsigned char *buf, size_t *len)
{
@@ -1283,11 +1376,11 @@ But it seems that the scanner takes care of that, and gives you the ack as a sep
}
}
else {
- DBG(min(1,DBG_READ), "%s: tiny read, got %d bytes of %d\n", __func__, bytecount, *len);
+ DBG(min(1,DBG_READ), "%s: tiny read, got %d bytes of %d\n", __func__, (int) bytecount, *len);
return SANE_STATUS_IO_ERROR;
}
if (*len > s->params.bytes_per_line) {
- /* store average colour as background. That's not the ideal method but it's easy to implement. */
+ /* store average colour as background. That's not the ideal method but it's easy to implement. What's it used for? */
lines = *len / s->params.bytes_per_line;
s->background[0] = 0;
s->background[1] = 0;
@@ -1545,11 +1638,11 @@ k_set_scanning_parameters(KodakAio_Scanner * s)
s->params.bytes_per_line *= 3;
/* Calculate how many bytes per line will be returned by the scanner.
- magicolor needed this because it uses padding. Scan bytes per line != image bytes per line
+ magicolor needed this because it uses padding so scan bytes per line != image bytes per line.
* The values needed for this are returned by get_scanning_parameters */
- s->scan_bytes_per_line = 3 * ceil (scan_pixels_per_line * s->params.depth / 8.0);
+ s->scan_bytes_per_line = 3 * ceil (scan_pixels_per_line); /* we always scan in colour 8 bit */
s->data_len = s->scan_bytes_per_line * floor (s->height * dpi / optres + 0.5); /* NB this is the length for a full scan */
- DBG (1, "Check: scan_bytes_per_line = %d s->params.bytes_per_line = %d \n", s->scan_bytes_per_line, s->params.bytes_per_line);
+ DBG (5, "Check: scan_bytes_per_line = %d s->params.bytes_per_line = %d \n", s->scan_bytes_per_line, s->params.bytes_per_line);
/* k_setup_block_mode at the start of each page for adf to work */
status = k_setup_block_mode (s);
@@ -1604,10 +1697,14 @@ k_copy_image_data(KodakAio_Scanner * s, SANE_Byte * data, SANE_Int max_length,
uncompressed data is RRRR...GGGG...BBBB per line */
{
SANE_Int bytes_available;
+ SANE_Int threshold;
DBG (min(18,DBG_READ), "%s: bytes_read in line: %d\n", __func__, s->bytes_read_in_line);
*length = 0;
+ threshold = 255 - (int) (SANE_UNFIX(s->val[OPT_THRESHOLD].w) * 255.0 / 100.0 + 0.5); /* 255 - for the grey scale version */
+ DBG (20, "%s: threshold: %d\n", __func__, threshold);
+
while ((max_length >= s->params.bytes_per_line) && (s->ptr < s->end)) {
SANE_Int bytes_to_copy = s->scan_bytes_per_line - s->bytes_read_in_line;
/* First, fill the line buffer for the current line: */
@@ -1635,23 +1732,36 @@ uncompressed data is RRRR...GGGG...BBBB per line */
*length += s->params.bytes_per_line;
for (i=0; i< s->params.pixels_per_line; ++i) {
+ /* different behaviour for each mode */
if (s->val[OPT_MODE].w == MODE_COLOR){
- /*interlace */
- *data++ = 255-line[0]; /*red */
- *data++ = 255-line[s->params.pixels_per_line]; /*green */
- *data++ = 255-line[2 * s->params.pixels_per_line]; /*blue */
+ /*interlace was subtracting from 255 until 6/9/14 */
+ *data++ = 255-line[0]; /*red */
+ *data++ = 255-line[s->params.pixels_per_line]; /*green */
+ *data++ = 255-line[2 * s->params.pixels_per_line]; /*blue */
+ }
+ else if (s->val[OPT_MODE].w == MODE_LINEART) { /* gives 1 bit output */
+ /*output image location*/
+ int offset = i % 8;
+ unsigned char mask = 0x80 >> offset;
+ /*set if any colour is over the threshold */
+ if (line[0] < threshold || line[s->params.pixels_per_line] < threshold || line[2 * s->params.pixels_per_line] < threshold)
+ *data &= ~mask; /* white clear the bit in mask */
+ else
+ *data |= mask; /* black set the bit in mask */
+
+ if (offset == 7 || i == s->params.pixels_per_line-1)
+ data++; /* move on a byte if the byte is full or the line is complete */
}
- else { /* grey */
- /*Average*/
- *data++ = (255-line[0]
+ else { /* greyscale - Average the 3 colours */
+ *data++ = (255-line[0]
+255-line[s->params.pixels_per_line]
+255-line[2 * s->params.pixels_per_line])
/ 3;
}
- line++;
+ line++;
}
/*debug file The same for color or grey because the scan is colour */
if (RawScan != NULL) {
@@ -1716,21 +1826,22 @@ k_init_parametersta(KodakAio_Scanner * s)
SANE_UNFIX(s->val[OPT_BR_X].w), SANE_UNFIX(s->val[OPT_BR_Y].w));
/*
- * The default color depth is stored in mode_params.depth:
+ * The default color depth is stored in mode_params.depth:‭
*/
if (mode_params[s->val[OPT_MODE].w].depth == 1)
s->params.depth = 1;
else {
- DBG(20, "%s: setting depth = s->val[OPT_BIT_DEPTH].w = %d\n", __func__,s->val[OPT_BIT_DEPTH].w);
s->params.depth = s->val[OPT_BIT_DEPTH].w;
}
+ DBG(20, "%s: bit depth = s->params.depth = %d\n", __func__,s->params.depth);
s->params.last_frame = SANE_TRUE;
s->params.bytes_per_line = 3 * ceil (s->params.depth * s->params.pixels_per_line / 8.0);
-/* kodak only scans in color and conversion to grey is done in the driver
+/* kodak only scans in color and conversion to grey or lineart is done in the driver
s->params.format = SANE_FRAME_RGB; */
- DBG(20, "%s: s->val[OPT_MODE].w = %d (color is %d)\n", __func__,s->val[OPT_MODE].w, MODE_COLOR);
+ DBG(20, "%s: s->val[OPT_MODE].w = %d (color is %d)\n", __func__,s->val[OPT_MODE].w, MODE_COLOR);
if (s->val[OPT_MODE].w == MODE_COLOR) s->params.format = SANE_FRAME_RGB;
+ else if (s->val[OPT_MODE].w == MODE_LINEART) s->params.format = SANE_FRAME_GRAY;
else s->params.format = SANE_FRAME_GRAY;
DBG(20, "%s: format=%d, bytes_per_line=%d, lines=%d\n", __func__, s->params.format, s->params.bytes_per_line, s->params.lines);
@@ -1761,19 +1872,16 @@ you don't know how many blocks there will be in advance because their size may b
SANE_Status status = SANE_STATUS_GOOD;
size_t buf_len = 0;
- /* did we passed everything we read to sane? */
+ /* have we passed everything we read to sane? */
if (s->ptr == s->end) {
-
if (s->eof)
return SANE_STATUS_EOF;
s->counter++;
-
if (s->bytes_unread >= s->block_len)
buf_len = s->block_len;
else
buf_len = s->bytes_unread;
-
DBG(min(20,DBG_READ), "%s: block %d, size %lu\n", __func__,
s->counter, (unsigned long) buf_len);
@@ -1810,9 +1918,7 @@ you don't know how many blocks there will be in advance because their size may b
return SANE_STATUS_IO_ERROR;
}
}
-
}
-
s->end = s->buf + buf_len;
s->ptr = s->buf;
}
@@ -1858,7 +1964,6 @@ get_device_from_identification (const char *ident, const char *vid, const char *
return NULL;
}
-
/*
* close_scanner()
*
@@ -2184,6 +2289,7 @@ static void resolve_callback(
AvahiLookupResultFlags flags,
AVAHI_GCC_UNUSED void* userdata) {
+ AvahiStringList *vid_pair_list = NULL, *pid_pair_list = NULL;
char *pidkey, *pidvalue;
char *vidkey, *vidvalue;
size_t valuesize;
@@ -2204,20 +2310,40 @@ static void resolve_callback(
avahi_address_snprint(a, sizeof(a), address);
/* Output short for Kodak ESP */
- DBG(min(10,DBG_AUTO), "%s:%u %s ", a,port,host_name);
- avahi_string_list_get_pair(avahi_string_list_find(txt, "vid"),
- &vidkey, &vidvalue, &valuesize);
- DBG(min(10,DBG_AUTO), "%s=%s ", vidkey, vidvalue);
- avahi_string_list_get_pair(avahi_string_list_find(txt, "pid"),
- &pidkey, &pidvalue, &valuesize);
- DBG(min(10,DBG_AUTO), "%s=%s\n", pidkey, pidvalue);
+ DBG(min(10,DBG_AUTO), "%s:%u %s\n", a,port,host_name);
+
+ vid_pair_list = avahi_string_list_find(txt, "vid");
+ if(vid_pair_list != NULL) {
+ avahi_string_list_get_pair(vid_pair_list, &vidkey, &vidvalue, &valuesize);
+ DBG(min(10,DBG_AUTO), "%s=%s ", vidkey, vidvalue);
+ }
+ else DBG(min(10,DBG_AUTO), "failed to find key vid\n");
+ pid_pair_list = avahi_string_list_find(txt, "pid");
+ if(pid_pair_list != NULL) {
+ avahi_string_list_get_pair(pid_pair_list, &pidkey, &pidvalue, &valuesize);
+ DBG(min(10,DBG_AUTO), "%s=%s\n", pidkey, pidvalue);
+ }
+ else DBG(min(10,DBG_AUTO), "failed to find key pid\n");
+
+ if(pid_pair_list != NULL && vid_pair_list != NULL) {
ProcessAvahiDevice(name, vidvalue, pidvalue, a);
- avahi_free(vidkey); avahi_free(vidvalue);
- avahi_free(pidkey); avahi_free(pidvalue);
+ }
+ else DBG(min(10,DBG_AUTO), "didn't call ProcessAvahiDevice\n");
+
+ if(vid_pair_list != NULL) {
+ avahi_free(vidkey);
+ avahi_free(vidvalue);
+ DBG(min(15,DBG_AUTO), "vidkey and vidvalue freed\n");
+ }
+ if(pid_pair_list != NULL) {
+ avahi_free(pidkey);
+ avahi_free(pidvalue);
+ DBG(min(15,DBG_AUTO), "pidkey and pidvalue freed\n");
+ }
}
}
-
+ DBG(min(10,DBG_AUTO), "ending resolve_callback\n");
avahi_service_resolver_free(r);
}
@@ -2619,8 +2745,32 @@ init_options(KodakAio_Scanner *s)
s->opt[OPT_MODE].size = max_string_size(mode_list);
s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
s->opt[OPT_MODE].constraint.string_list = mode_list;
- s->val[OPT_MODE].w = 0; /* Binary */
- DBG(20, "%s: mode_list has first entry %s\n", __func__, mode_list[0]);
+ s->val[OPT_MODE].w = MODE_COLOR; /* default */
+ DBG(20, "%s: mode_list has first entry %s, default mode is %s\n", __func__, mode_list[0],mode_list[s->val[OPT_MODE].w]);
+
+ /* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255 */
+ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
+ s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
+ s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
+ s->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
+ s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
+ s->opt[OPT_THRESHOLD].size = sizeof(SANE_Word);
+ s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_THRESHOLD].constraint.range = &percent_range_fixed;
+ s->val[OPT_THRESHOLD].w = SANE_FIX(50.0);
+ DBG(20, "%s: threshold initialised to fixed %f\n", __func__, SANE_UNFIX(s->val[OPT_THRESHOLD].w));
+
+ /* theshold the sane std says should be SANE_TYPE_FIXED 0..100 but all other backends seem to use INT 0..255
+ s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
+ s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
+ s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
+ s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT;
+ s->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
+ s->opt[OPT_THRESHOLD].size = sizeof(SANE_Word);
+ s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_THRESHOLD].constraint.range = &percent_range_int;
+ s->val[OPT_THRESHOLD].w = 51;
+ DBG(20, "%s: threshold initialised to int %d\n", __func__, s->val[OPT_THRESHOLD].w); */
/* bit depth */
s->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
@@ -2656,6 +2806,17 @@ init_options(KodakAio_Scanner *s)
s->val[OPT_RESOLUTION].w = s->hw->cap->dpi_range.min;
+ /* trial option for debugging
+ s->opt[OPT_TRIALOPT].name = "trialoption";
+ s->opt[OPT_TRIALOPT].title = "trialoption";
+ s->opt[OPT_TRIALOPT].desc = "trialoption";
+ s->opt[OPT_TRIALOPT].type = SANE_TYPE_INT;
+ s->opt[OPT_TRIALOPT].unit = SANE_UNIT_NONE;
+ s->opt[OPT_TRIALOPT].size = sizeof(SANE_Word);
+ s->opt[OPT_TRIALOPT].constraint_type = SANE_CONSTRAINT_RANGE;
+ s->opt[OPT_TRIALOPT].constraint.range = &percent_range_int;
+ s->val[OPT_TRIALOPT].w = 1; */
+
/* preview */
s->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
s->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
@@ -2831,12 +2992,13 @@ maybe we should only be rebuilding the source list here? */
*handle = (SANE_Handle) s;
+/* moving the open scanner section below to sane_start 27/12/14
status = open_scanner(s);
if (status != SANE_STATUS_GOOD) {
free(s);
return status;
}
-
+*/
return status;
}
@@ -2853,8 +3015,11 @@ sane_close(SANE_Handle handle)
s = (KodakAio_Scanner *) handle;
DBG(2, "%s: called\n", __func__);
+/* moving the close scanner section below to sane_cancel 27/12/14 */
if (s->fd != -1)
close_scanner(s);
+/* end of section */
+
if(RawScan != NULL)
fclose(RawScan);
RawScan = NULL;
@@ -2867,7 +3032,7 @@ sane_get_option_descriptor(SANE_Handle handle, SANE_Int option)
/* this may be a sane call, but it happens way too often to have DBG level 2 */
KodakAio_Scanner *s = (KodakAio_Scanner *) handle;
- DBG(20, "%s: called for option %d\n", __func__, option);
+ DBG(30, "%s: called for option %d\n", __func__, option);
if (option < 0 || option >= NUM_OPTIONS)
return NULL;
@@ -2922,7 +3087,7 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value)
case OPT_NUM_OPTS:
case OPT_BIT_DEPTH:
-/* case OPT_BRIGHTNESS: */
+ /* case OPT_TRIALOPT: */
case OPT_RESOLUTION:
case OPT_PREVIEW:
case OPT_TL_X:
@@ -2930,6 +3095,13 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value)
case OPT_BR_X:
case OPT_BR_Y:
*((SANE_Word *) value) = sval->w;
+ DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value));
+ break;
+
+ case OPT_THRESHOLD:
+ *((SANE_Word *) value) = sval->w;
+ DBG(20, "%s: got option %d as %f\n", __func__, option, SANE_UNFIX(*((SANE_Word *) value)));
+ /*DBG(20, "%s: got option %d as %d\n", __func__, option, *((SANE_Word *) value));*/
break;
case OPT_MODE:
@@ -2942,9 +3114,11 @@ getvalue(SANE_Handle handle, SANE_Int option, void *value)
break;
default:
+ DBG(20, "%s: returning inval\n", __func__);
return SANE_STATUS_INVAL;
}
+ DBG(20, "%s: returning good\n", __func__);
return SANE_STATUS_GOOD;
}
@@ -3050,18 +3224,23 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
case OPT_MODE:
{
sval->w = optindex;
- /* if binary, then disable the bit depth selection */
- if (optindex == 0) {
+ /* if binary, then disable the bit depth selection and enable threshold */
+ if (optindex == MODE_LINEART) {
+ DBG(17, "%s: binary mode setting depth to 1\n", __func__);
+ s->val[OPT_BIT_DEPTH].w = 1;
s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
+ s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
} else {
- if (s->hw->cap->depth_list[0] == 1)
- s->opt[OPT_BIT_DEPTH].cap |=
- SANE_CAP_INACTIVE;
- else {
- s->opt[OPT_BIT_DEPTH].cap &=
- ~SANE_CAP_INACTIVE;
- s->val[OPT_BIT_DEPTH].w =
- mode_params[optindex].depth;
+ if (s->hw->cap->depth_list[0] == 1) { /* only one entry in the list ? */
+ DBG(17, "%s: non-binary mode but only one depth available\n", __func__);
+ s->val[OPT_BIT_DEPTH].w = s->hw->cap->depth_list[1];
+ s->opt[OPT_BIT_DEPTH].cap |= SANE_CAP_INACTIVE;
+ s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
+ } else { /* there is a list to choose from ? */
+ DBG(17, "%s: non-binary mode and depth list available\n", __func__);
+ s->opt[OPT_BIT_DEPTH].cap &= ~SANE_CAP_INACTIVE;
+ s->val[OPT_BIT_DEPTH].w = mode_params[optindex].depth;
+ s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; /* does not work in xsane ? */
}
}
reload = SANE_TRUE;
@@ -3074,6 +3253,13 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
reload = SANE_TRUE;
break;
+ case OPT_THRESHOLD:
+ sval->w = *((SANE_Word *) value);
+ DBG(17, "setting threshold to %f\n", SANE_UNFIX(sval->w));
+ /*DBG(17, "setting threshold to %d\n", sval->w);*/
+ /*reload = SANE_TRUE; what does this do?*/
+ break;
+
case OPT_RESOLUTION:
sval->w = *((SANE_Word *) value);
DBG(17, "setting resolution to %d\n", sval->w);
@@ -3109,7 +3295,7 @@ setvalue(SANE_Handle handle, SANE_Int option, void *value, SANE_Int *info)
sval->w = *((SANE_Word *) value);
break;
-/* case OPT_BRIGHTNESS: */
+ /* case OPT_TRIALOPT: */
case OPT_PREVIEW: /* needed? */
sval->w = *((SANE_Word *) value);
break;
@@ -3131,14 +3317,14 @@ sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action,
void *value, SANE_Int *info)
{
KodakAio_Scanner *s = (KodakAio_Scanner *) handle;
- DBG(2, "%s: action = %x, option = %d %s\n", __func__, action, option, s->opt[option].name);
-
if (option < 0 || option >= NUM_OPTIONS)
{
- DBG(1, "%s: option num = %d (%s) out of range\n", __func__, option, s->opt[option].name);
+ DBG(1, "%s: option num = %d out of range (0..%d)\n", __func__, option, NUM_OPTIONS - 1);
return SANE_STATUS_INVAL;
}
+ DBG(5, "%s: action = %x, option = %d %s\n", __func__, action, option, s->opt[option].name);
+
if (info != NULL)
*info = 0;
@@ -3209,6 +3395,16 @@ sane_start(SANE_Handle handle)
* them to s->params
Only set scanning params the first time, or after a cancel
try change 22/2/12 take lock scanner out of k_set_scanning_parameters */
+
+/* moved open_scanner here 27/12/14 from sane_open */
+ status = open_scanner(s);
+ if (status != SANE_STATUS_GOOD) {
+ free(s);
+ return status;
+ }
+/* end of open scanner section */
+
+
status = k_lock_scanner(s);
if (status != SANE_STATUS_GOOD) {
DBG(1, "could not lock scanner\n");
@@ -3299,24 +3495,24 @@ sane_read(SANE_Handle handle, SANE_Byte *data, SANE_Int max_length,
return status;
}
-/*
- * void sane_cancel(SANE_Handle handle)
- *
- * Set the cancel flag to true. The next time the backend requests data
- * from the scanner the CAN message will be sent.
- */
void
sane_cancel(SANE_Handle handle)
{
+ SANE_Status status;
KodakAio_Scanner *s = (KodakAio_Scanner *) handle;
DBG(2, "%s: called\n", __func__);
-/* used to set cancelling flag to tell sane_read to cancel
-changed 20/2/12
- s->canceling = SANE_TRUE;
-*/
- cmd_cancel_scan(s);
+ status = cmd_cancel_scan(s);
+ if (status != SANE_STATUS_GOOD)
+ DBG(1, "%s: cmd_cancel_scan failed: %s\n", __func__,
+ sane_strstatus(status));
+
+/* moved from close scanner section 27/12/14 */
+ if (s->fd != -1)
+ close_scanner(s);
+/* end of section */
+
}
/*