summaryrefslogtreecommitdiff
path: root/backend/xerox_mfp.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2017-07-15 11:29:05 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2017-07-15 11:29:05 +0200
commit324a8a71bb7d9e4f8bc49b6bc47efaf9fb58282e (patch)
treebd2d48a139bfbe869f4f49359b63097931a45e7b /backend/xerox_mfp.c
parent2ca8a81bd0d99fe4d75c229d0e988d8ef710285f (diff)
parent1edb02101a9306fc711cd422ed507d18165b1691 (diff)
Merge branch 'release/experimental/1.0.27-1_experimental1'experimental/1.0.27-1_experimental1
Diffstat (limited to 'backend/xerox_mfp.c')
-rw-r--r--backend/xerox_mfp.c2236
1 files changed, 1211 insertions, 1025 deletions
diff --git a/backend/xerox_mfp.c b/backend/xerox_mfp.c
index 2ef7078..8b8c895 100644
--- a/backend/xerox_mfp.c
+++ b/backend/xerox_mfp.c
@@ -1,9 +1,12 @@
/*
- * SANE backend for Xerox Phaser 3200MFP
- * Copyright 2008 ABC <abc@telekom.ru>
+ * SANE backend for Xerox Phaser 3200MFP et al.
+ * Copyright 2008-2016 ABC <abc@telekom.ru>
*
- * Network Scanners Support
- * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org>
+ * Network Scanners Support
+ * Copyright 2010 Alexander Kuznetsov <acca(at)cpan.org>
+ *
+ * Color scanning on Samsung M2870 model and Xerox Cognac 3215 & 3225
+ * models by Laxmeesh Onkar Markod <m.laxmeesh@samsung.com>
*
* This program is licensed under GPL + SANE exception.
* More info at http://www.sane-project.org/license.html
@@ -30,6 +33,9 @@
#include "../include/sane/sanei_usb.h"
#include "../include/sane/sanei_config.h"
#include "../include/sane/sanei_backend.h"
+#ifdef HAVE_LIBJPEG
+#include <jpeglib.h>
+#endif
#include "xerox_mfp.h"
#define BACKEND_BUILD 13
@@ -46,34 +52,34 @@ transport available_transports[TRANSPORTS_MAX] = {
static int resolv_state(int state)
{
- if (state & STATE_DOCUMENT_JAM)
- return SANE_STATUS_JAMMED;
- if (state & STATE_NO_DOCUMENT)
- return SANE_STATUS_NO_DOCS;
- if (state & STATE_COVER_OPEN)
- return SANE_STATUS_COVER_OPEN;
- if (state & STATE_INVALID_AREA)
- return SANE_STATUS_INVAL; /* sane_start: implies SANE_INFO_RELOAD_OPTIONS */
- if (state & STATE_WARMING)
+ if (state & STATE_DOCUMENT_JAM)
+ return SANE_STATUS_JAMMED;
+ if (state & STATE_NO_DOCUMENT)
+ return SANE_STATUS_NO_DOCS;
+ if (state & STATE_COVER_OPEN)
+ return SANE_STATUS_COVER_OPEN;
+ if (state & STATE_INVALID_AREA)
+ return SANE_STATUS_INVAL; /* sane_start: implies SANE_INFO_RELOAD_OPTIONS */
+ if (state & STATE_WARMING)
#ifdef SANE_STATUS_WARMING_UP
- return SANE_STATUS_WARMING_UP;
+ return SANE_STATUS_WARMING_UP;
#else
- return SANE_STATUS_DEVICE_BUSY;
+ return SANE_STATUS_DEVICE_BUSY;
#endif
- if (state & STATE_LOCKING)
+ if (state & STATE_LOCKING)
#ifdef SANE_STATUS_HW_LOCKED
- return SANE_STATUS_HW_LOCKED;
+ return SANE_STATUS_HW_LOCKED;
#else
- return SANE_STATUS_JAMMED;
+ return SANE_STATUS_JAMMED;
#endif
- if (state & ~STATE_NO_ERROR)
- return SANE_STATUS_DEVICE_BUSY;
- return 0;
+ if (state & ~STATE_NO_ERROR)
+ return SANE_STATUS_DEVICE_BUSY;
+ return 0;
}
static char *str_cmd(int cmd)
{
- switch (cmd) {
+ switch (cmd) {
case CMD_ABORT: return "ABORT";
case CMD_INQUIRY: return "INQUIRY";
case CMD_RESERVE_UNIT: return "RESERVE_UNIT";
@@ -82,1262 +88,1442 @@ static char *str_cmd(int cmd)
case CMD_READ: return "READ";
case CMD_READ_IMAGE: return "READ_IMAGE";
case CMD_OBJECT_POSITION: return "OBJECT_POSITION";
- }
- return "unknown";
+ }
+ return "unknown";
}
#define MAX_DUMP 70
+const char *encTmpFileName = "/tmp/stmp_enc.tmp";
+
+static int decompress(struct device __sane_unused__ *dev,
+ const char __sane_unused__ *infilename)
+{
+#ifdef HAVE_LIBJPEG
+ int rc;
+ int row_stride, width, height, pixel_size;
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ unsigned long bmp_size = 0;
+ FILE *pInfile = NULL;
+ JSAMPARRAY buffer;
+
+ if ((pInfile = fopen(infilename, "rb")) == NULL) {
+ fprintf(stderr, "can't open %s\n", infilename);
+ return -1;
+ }
+
+ cinfo.err = jpeg_std_error(&jerr);
+
+ jpeg_create_decompress(&cinfo);
+
+ jpeg_stdio_src(&cinfo, pInfile);
+
+ rc = jpeg_read_header(&cinfo, TRUE);
+ if (rc != 1) {
+ jpeg_destroy_decompress(&cinfo);
+ fclose(pInfile);
+ return -1;
+ }
+
+ jpeg_start_decompress(&cinfo);
+
+ width = cinfo.output_width;
+ height = cinfo.output_height;
+ pixel_size = cinfo.output_components;
+ bmp_size = width * height * pixel_size;
+ dev->decDataSize = bmp_size;
+
+ row_stride = width * pixel_size;
+
+ buffer = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+
+ while (cinfo.output_scanline < cinfo.output_height) {
+ buffer[0] = dev->decData + \
+ (cinfo.output_scanline) * row_stride;
+ jpeg_read_scanlines(&cinfo, buffer, 1);
+ }
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ fclose(pInfile);
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+static int copy_decompress_data(struct device *dev, unsigned char *pDest, int maxlen, int *destLen)
+{
+ int data_size = 0;
+ size_t result = 0, retVal = 0;
+
+
+ if (0 == dev->decDataSize) {
+ *destLen = 0;
+ return retVal;
+ }
+ data_size = dev->decDataSize - dev->currentDecDataIndex;
+ if (data_size > maxlen) {
+ data_size = maxlen;
+ }
+ memcpy(pDest, dev->decData+dev->currentDecDataIndex, data_size);
+ result = data_size;
+ *destLen = result;
+ dev->currentDecDataIndex += result;
+ retVal = result;
+
+ if (dev->decDataSize == dev->currentDecDataIndex) {
+ dev->currentDecDataIndex = 0;
+ dev->decDataSize = 0;
+ }
+
+ return retVal;
+}
+
+static int decompress_tempfile(struct device *dev)
+{
+ decompress(dev, encTmpFileName);
+ remove(encTmpFileName);
+ return 0;
+}
+
+static int dump_to_tmp_file(struct device *dev)
+{
+ unsigned char *pSrc = dev->data;
+ int srcLen = dev->datalen;
+ FILE *pInfile;
+ if ((pInfile = fopen(encTmpFileName, "a")) == NULL) {
+ fprintf(stderr, "can't open %s\n", encTmpFileName);
+ return 0;
+ }
+
+ fwrite(pSrc, 1, srcLen, pInfile);
+ fclose(pInfile);
+ return srcLen;
+}
+
+static int isSupportedDevice(struct device __sane_unused__ *dev)
+{
+#ifdef HAVE_LIBJPEG
+ /* Checking device which supports JPEG Lossy compression for color scanning*/
+ if (dev->compressionTypes & (1 << 6))
+ return 1;
+ else
+ return 0;
+#else
+ return 0;
+#endif
+}
+
static void dbg_dump(struct device *dev)
{
- int i;
- char dbuf[MAX_DUMP * 3 + 1], *dptr = dbuf;
- int nzlen = dev->reslen;
- int dlen = MIN(dev->reslen, MAX_DUMP);
+ int i;
+ char dbuf[MAX_DUMP * 3 + 1], *dptr = dbuf;
+ int nzlen = dev->reslen;
+ int dlen = MIN(dev->reslen, MAX_DUMP);
- for (i = dev->reslen - 1; i >= 0; i--, nzlen--)
- if (dev->res[i] != 0)
- break;
+ for (i = dev->reslen - 1; i >= 0; i--, nzlen--)
+ if (dev->res[i] != 0)
+ break;
- dlen = MIN(dlen, nzlen + 1);
+ dlen = MIN(dlen, nzlen + 1);
- for (i = 0; i < dlen; i++, dptr += 3)
- sprintf(dptr, " %02x", dev->res[i]);
+ for (i = 0; i < dlen; i++, dptr += 3)
+ sprintf(dptr, " %02x", dev->res[i]);
- DBG (5, "[%lu]%s%s\n", (u_long)dev->reslen, dbuf,
- (dlen < (int)dev->reslen)? "..." : "");
+ DBG(5, "[%lu]%s%s\n", (u_long)dev->reslen, dbuf,
+ (dlen < (int)dev->reslen)? "..." : "");
}
/* one command to device */
/* return 0: on error, 1: success */
-static int dev_command (struct device *dev, SANE_Byte * cmd, size_t reqlen)
+static int dev_command(struct device *dev, SANE_Byte *cmd, size_t reqlen)
{
- SANE_Status status;
- size_t sendlen = cmd[3] + 4;
- SANE_Byte *res = dev->res;
-
-
- assert (reqlen <= sizeof (dev->res)); /* requested len */
- dev->reslen = sizeof (dev->res); /* doing full buffer to flush stalled commands */
-
- if (cmd[2] == CMD_SET_WINDOW) {
- /* Set Window have wrong packet length, huh. */
- sendlen = 25;
- }
-
- if (cmd[2] == CMD_READ_IMAGE) {
- /* Read Image is raw data, don't need to read response */
- res = NULL;
- }
-
- dev->state = 0;
- DBG (4, ":: dev_command(%s[%#x], %lu)\n", str_cmd(cmd[2]), cmd[2],
- (u_long)reqlen);
- status = dev->io->dev_request(dev, cmd, sendlen, res, &dev->reslen);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: dev_request: %s\n", __FUNCTION__, sane_strstatus (status));
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
- }
+ SANE_Status status;
+ size_t sendlen = cmd[3] + 4;
+ SANE_Byte *res = dev->res;
- if (!res) {
- /* if not need response just return success */
- return 1;
- }
- /* normal command reply, some sanity checking */
- if (dev->reslen < reqlen) {
- DBG (1, "%s: illegal response len %lu, need %lu\n",
- __FUNCTION__, (u_long)dev->reslen, (u_long)reqlen);
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
- } else {
- size_t pktlen; /* len specified in packet */
+ assert(reqlen <= sizeof(dev->res)); /* requested len */
+ dev->reslen = sizeof(dev->res); /* doing full buffer to flush stalled commands */
- if (DBG_LEVEL > 3)
- dbg_dump(dev);
+ if (cmd[2] == CMD_SET_WINDOW) {
+ /* Set Window have wrong packet length, huh. */
+ sendlen = 25;
+ }
- if (dev->res[0] != RES_CODE) {
- DBG (2, "%s: illegal data header %02x\n", __FUNCTION__, dev->res[0]);
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
+ if (cmd[2] == CMD_READ_IMAGE) {
+ /* Read Image is raw data, don't need to read response */
+ res = NULL;
}
- pktlen = dev->res[2] + 3;
- if (dev->reslen != pktlen) {
- DBG (2, "%s: illegal response len %lu, should be %lu\n",
- __FUNCTION__, (u_long)pktlen, (u_long)dev->reslen);
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
+
+ dev->state = 0;
+ DBG(4, ":: dev_command(%s[%#x], %lu)\n", str_cmd(cmd[2]), cmd[2],
+ (u_long)reqlen);
+ status = dev->io->dev_request(dev, cmd, sendlen, res, &dev->reslen);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: dev_request: %s\n", __func__, sane_strstatus(status));
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
}
- if (dev->reslen > reqlen)
- DBG (2, "%s: too big packet len %lu, need %lu\n",
- __FUNCTION__, (u_long)dev->reslen, (u_long)reqlen);
- }
-
- dev->state = 0;
- if (cmd[2] == CMD_SET_WINDOW ||
- cmd[2] == CMD_OBJECT_POSITION ||
- cmd[2] == CMD_READ ||
- cmd[2] == CMD_RESERVE_UNIT) {
- if (dev->res[1] == STATUS_BUSY)
- dev->state = SANE_STATUS_DEVICE_BUSY;
- else if (dev->res[1] == STATUS_CANCEL)
- dev->state = SANE_STATUS_CANCELLED;
- else if (dev->res[1] == STATUS_CHECK)
- dev->state = resolv_state((cmd[2] == CMD_READ)?
- (dev->res[12] << 8 | dev->res[13]) :
- (dev->res[4] << 8 | dev->res[5]));
-
- if (dev->state)
- DBG (3, "%s(%s[%#x]): => %d: %s\n",
- __FUNCTION__, str_cmd(cmd[2]), cmd[2],
- dev->state, sane_strstatus(dev->state));
- }
-
- return 1;
+
+ if (!res) {
+ /* if not need response just return success */
+ return 1;
+ }
+
+ /* normal command reply, some sanity checking */
+ if (dev->reslen < reqlen) {
+ DBG(1, "%s: illegal response len %lu, need %lu\n",
+ __func__, (u_long)dev->reslen, (u_long)reqlen);
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ } else {
+ size_t pktlen; /* len specified in packet */
+
+ if (DBG_LEVEL > 3)
+ dbg_dump(dev);
+
+ if (dev->res[0] != RES_CODE) {
+ DBG(2, "%s: illegal data header %02x\n", __func__, dev->res[0]);
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ }
+ pktlen = dev->res[2] + 3;
+ if (dev->reslen != pktlen) {
+ DBG(2, "%s: illegal response len %lu, should be %lu\n",
+ __func__, (u_long)pktlen, (u_long)dev->reslen);
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ }
+ if (dev->reslen > reqlen)
+ DBG(2, "%s: too big packet len %lu, need %lu\n",
+ __func__, (u_long)dev->reslen, (u_long)reqlen);
+ }
+
+ dev->state = 0;
+ if (cmd[2] == CMD_SET_WINDOW ||
+ cmd[2] == CMD_OBJECT_POSITION ||
+ cmd[2] == CMD_READ ||
+ cmd[2] == CMD_RESERVE_UNIT) {
+ if (dev->res[1] == STATUS_BUSY)
+ dev->state = SANE_STATUS_DEVICE_BUSY;
+ else if (dev->res[1] == STATUS_CANCEL)
+ dev->state = SANE_STATUS_CANCELLED;
+ else if (dev->res[1] == STATUS_CHECK)
+ dev->state = resolv_state((cmd[2] == CMD_READ)?
+ (dev->res[12] << 8 | dev->res[13]) :
+ (dev->res[4] << 8 | dev->res[5]));
+
+ if (dev->state)
+ DBG(3, "%s(%s[%#x]): => %d: %s\n",
+ __func__, str_cmd(cmd[2]), cmd[2],
+ dev->state, sane_strstatus(dev->state));
+ }
+
+ return 1;
}
/* one short command to device */
-static int dev_cmd (struct device *dev, SANE_Byte command)
+static int dev_cmd(struct device *dev, SANE_Byte command)
{
- SANE_Byte cmd[4] = { REQ_CODE_A, REQ_CODE_B };
- cmd[2] = command;
- return dev_command (dev, cmd, (command == CMD_INQUIRY)? 70 : 32);
+ SANE_Byte cmd[4] = { REQ_CODE_A, REQ_CODE_B };
+ cmd[2] = command;
+ return dev_command(dev, cmd, (command == CMD_INQUIRY)? 70 : 32);
}
/* stop scanning operation. return previous status */
static SANE_Status dev_stop(struct device *dev)
{
- int state = dev->state;
-
- DBG (3, "%s: %p, scanning %d, reserved %d\n", __FUNCTION__,
- (void *)dev, dev->scanning, dev->reserved);
- dev->scanning = 0;
-
- /* release */
- if (!dev->reserved)
- return state;
- dev->reserved = 0;
- dev_cmd(dev, CMD_RELEASE_UNIT);
- DBG (3, "total image %d*%d size %d (win %d*%d), %d*%d %d data: %d, out %d bytes\n",
- dev->para.pixels_per_line, dev->para.lines,
- dev->total_img_size,
- dev->win_width, dev->win_len,
- dev->pixels_per_line, dev->ulines, dev->blocks,
- dev->total_data_size, dev->total_out_size);
- dev->state = state;
- return state;
+ int state = dev->state;
+
+ DBG(3, "%s: %p, scanning %d, reserved %d\n", __func__,
+ (void *)dev, dev->scanning, dev->reserved);
+ dev->scanning = 0;
+
+ /* release */
+ if (!dev->reserved)
+ return state;
+ dev->reserved = 0;
+ dev_cmd(dev, CMD_RELEASE_UNIT);
+ DBG(3, "total image %d*%d size %d (win %d*%d), %d*%d %d data: %d, out %d bytes\n",
+ dev->para.pixels_per_line, dev->para.lines,
+ dev->total_img_size,
+ dev->win_width, dev->win_len,
+ dev->pixels_per_line, dev->ulines, dev->blocks,
+ dev->total_data_size, dev->total_out_size);
+ dev->state = state;
+ return state;
}
SANE_Status ret_cancel(struct device *dev, SANE_Status ret)
{
- dev_cmd(dev, CMD_ABORT);
- if (dev->scanning) {
- dev_stop(dev);
- dev->state = SANE_STATUS_CANCELLED;
- }
- return ret;
+ dev_cmd(dev, CMD_ABORT);
+ if (dev->scanning) {
+ dev_stop(dev);
+ dev->state = SANE_STATUS_CANCELLED;
+ }
+ return ret;
}
static int cancelled(struct device *dev)
{
- if (dev->cancel)
- return ret_cancel(dev, 1);
- return 0;
+ if (dev->cancel)
+ return ret_cancel(dev, 1);
+ return 0;
}
/* issue command and wait until scanner is not busy */
/* return 0 on error/blocking, 1 is ok and ready */
static int dev_cmd_wait(struct device *dev, int cmd)
{
- int sleeptime = 10;
-
- do {
- if (cancelled(dev))
- return 0;
- if (!dev_cmd(dev, cmd)) {
- dev->state = SANE_STATUS_IO_ERROR;
- return 0;
- } else if (dev->state) {
- if (dev->state != SANE_STATUS_DEVICE_BUSY)
- return 0;
- else {
- if (dev->non_blocking) {
- dev->state = SANE_STATUS_GOOD;
- return 0;
- } else {
- if (sleeptime > 1000)
- sleeptime = 1000;
- DBG (4, "(%s) sleeping(%d ms).. [%x %x]\n",
- str_cmd(cmd), sleeptime, dev->res[4], dev->res[5]);
- usleep(sleeptime * 1000);
- if (sleeptime < 1000)
- sleeptime *= (sleeptime < 100)? 10 : 2;
- }
- } /* BUSY */
- }
- } while (dev->state == SANE_STATUS_DEVICE_BUSY);
+ int sleeptime = 10;
+
+ do {
+ if (cancelled(dev))
+ return 0;
+ if (!dev_cmd(dev, cmd)) {
+ dev->state = SANE_STATUS_IO_ERROR;
+ return 0;
+ } else if (dev->state) {
+ if (dev->state != SANE_STATUS_DEVICE_BUSY)
+ return 0;
+ else {
+ if (dev->non_blocking) {
+ dev->state = SANE_STATUS_GOOD;
+ return 0;
+ } else {
+ if (sleeptime > 1000)
+ sleeptime = 1000;
+ DBG(4, "(%s) sleeping(%d ms).. [%x %x]\n",
+ str_cmd(cmd), sleeptime, dev->res[4], dev->res[5]);
+ usleep(sleeptime * 1000);
+ if (sleeptime < 1000)
+ sleeptime *= (sleeptime < 100)? 10 : 2;
+ }
+ } /* BUSY */
+ }
+ } while (dev->state == SANE_STATUS_DEVICE_BUSY);
- return 1;
+ return 1;
}
static int inq_dpi_bits[] = {
- 75, 150, 0, 0,
- 200, 300, 0, 0,
- 600, 0, 0, 1200,
- 100, 0, 0, 2400,
- 0, 4800, 0, 9600
+ 75, 150, 0, 0,
+ 200, 300, 0, 0,
+ 600, 0, 0, 1200,
+ 100, 0, 0, 2400,
+ 0, 4800, 0, 9600
};
static int res_dpi_codes[] = {
- 75, 0, 150, 0,
- 0, 300, 0, 600,
- 1200, 200, 100, 2400,
- 4800, 9600
+ 75, 0, 150, 0,
+ 0, 300, 0, 600,
+ 1200, 200, 100, 2400,
+ 4800, 9600
};
-static int SANE_Word_sort(const void * a, const void * b)
+static int SANE_Word_sort(const void *a, const void *b)
{
- return *(const SANE_Word *)a - *(const SANE_Word *)b;
+ return *(const SANE_Word *)a - *(const SANE_Word *)b;
}
/* resolve inquired dpi list to dpi_list array */
static void resolv_inq_dpi(struct device *dev)
{
- unsigned int i;
- int res = dev->resolutions;
-
- assert(sizeof(inq_dpi_bits) < sizeof(dev->dpi_list));
- for (i = 0; i < sizeof(inq_dpi_bits) / sizeof(int); i++)
- if (inq_dpi_bits[i] && (res & (1 << i)))
- dev->dpi_list[++dev->dpi_list[0]] = inq_dpi_bits[i];
- qsort(&dev->dpi_list[1], dev->dpi_list[0], sizeof(SANE_Word), SANE_Word_sort);
+ unsigned int i;
+ int res = dev->resolutions;
+
+ assert(sizeof(inq_dpi_bits) < sizeof(dev->dpi_list));
+ for (i = 0; i < sizeof(inq_dpi_bits) / sizeof(int); i++)
+ if (inq_dpi_bits[i] && (res & (1 << i)))
+ dev->dpi_list[++dev->dpi_list[0]] = inq_dpi_bits[i];
+ qsort(&dev->dpi_list[1], dev->dpi_list[0], sizeof(SANE_Word), SANE_Word_sort);
}
static unsigned int dpi_to_code(int dpi)
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; i < sizeof(res_dpi_codes) / sizeof(int); i++) {
- if (dpi == res_dpi_codes[i])
- return i;
- }
- return 0;
+ for (i = 0; i < sizeof(res_dpi_codes) / sizeof(int); i++) {
+ if (dpi == res_dpi_codes[i])
+ return i;
+ }
+ return 0;
}
static int string_match_index(const SANE_String_Const s[], SANE_String m)
{
- int i;
-
- for (i = 0; *s; i++) {
- SANE_String_Const x = *s++;
- if (strcasecmp(x, m) == 0)
- return i;
- }
- return 0;
+ int i;
+
+ for (i = 0; *s; i++) {
+ SANE_String_Const x = *s++;
+ if (strcasecmp(x, m) == 0)
+ return i;
+ }
+ return 0;
}
static SANE_String string_match(const SANE_String_Const s[], SANE_String m)
{
- return UNCONST(s[string_match_index(s, m)]);
+ return UNCONST(s[string_match_index(s, m)]);
}
-static size_t max_string_size (SANE_String_Const s[])
+static size_t max_string_size(SANE_String_Const s[])
{
- size_t max = 0;
-
- while (*s) {
- size_t size = strlen(*s++) + 1;
- if (size > max)
- max = size;
- }
- return max;
+ size_t max = 0;
+
+ while (*s) {
+ size_t size = strlen(*s++) + 1;
+ if (size > max)
+ max = size;
+ }
+ return max;
}
static SANE_String_Const doc_sources[] = {
- "Flatbed", "ADF", "Auto", NULL
+ "Flatbed", "ADF", "Auto", NULL
};
static int doc_source_to_code[] = {
- 0x40, 0x20, 0x80
+ 0x40, 0x20, 0x80
};
static SANE_String_Const scan_modes[] = {
- SANE_VALUE_SCAN_MODE_LINEART,
- SANE_VALUE_SCAN_MODE_HALFTONE,
- SANE_VALUE_SCAN_MODE_GRAY,
- SANE_VALUE_SCAN_MODE_COLOR,
- NULL
+ SANE_VALUE_SCAN_MODE_LINEART,
+ SANE_VALUE_SCAN_MODE_HALFTONE,
+ SANE_VALUE_SCAN_MODE_GRAY,
+ SANE_VALUE_SCAN_MODE_COLOR,
+ NULL
};
static int scan_mode_to_code[] = {
- 0x00, 0x01, 0x03, 0x05
+ 0x00, 0x01, 0x03, 0x05
};
static SANE_Range threshold = {
- SANE_FIX(30), SANE_FIX(70), SANE_FIX(10)
+ SANE_FIX(30), SANE_FIX(70), SANE_FIX(10)
};
static void reset_options(struct device *dev)
{
- dev->val[OPT_RESOLUTION].w = 150;
- dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR);
-
- /* if docs loaded in adf use it as default source, flatbed oterwise */
- dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]);
-
- dev->val[OPT_THRESHOLD].w = SANE_FIX(50);
-
- /* this is reported maximum window size, will be fixed later */
- dev->win_x_range.min = SANE_FIX(0);
- dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM);
- dev->win_x_range.quant = SANE_FIX(1);
- dev->win_y_range.min = SANE_FIX(0);
- dev->win_y_range.max = SANE_FIX((double)dev->max_win_len / PNT_PER_MM);
- dev->win_y_range.quant = SANE_FIX(1);
- dev->val[OPT_SCAN_TL_X].w = dev->win_x_range.min;
- dev->val[OPT_SCAN_TL_Y].w = dev->win_y_range.min;
- dev->val[OPT_SCAN_BR_X].w = dev->win_x_range.max;
- dev->val[OPT_SCAN_BR_Y].w = dev->win_y_range.max;
+ dev->val[OPT_RESOLUTION].w = 150;
+ dev->val[OPT_MODE].s = string_match(scan_modes, SANE_VALUE_SCAN_MODE_COLOR);
+
+ /* if docs loaded in adf use it as default source, flatbed oterwise */
+ dev->val[OPT_SOURCE].s = UNCONST(doc_sources[(dev->doc_loaded)? 1 : 0]);
+
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(50);
+
+ /* this is reported maximum window size, will be fixed later */
+ dev->win_x_range.min = SANE_FIX(0);
+ dev->win_x_range.max = SANE_FIX((double)dev->max_win_width / PNT_PER_MM);
+ dev->win_x_range.quant = SANE_FIX(1);
+ dev->win_y_range.min = SANE_FIX(0);
+ dev->win_y_range.max = SANE_FIX((double)dev->max_win_len / PNT_PER_MM);
+ dev->win_y_range.quant = SANE_FIX(1);
+ dev->val[OPT_SCAN_TL_X].w = dev->win_x_range.min;
+ dev->val[OPT_SCAN_TL_Y].w = dev->win_y_range.min;
+ dev->val[OPT_SCAN_BR_X].w = dev->win_x_range.max;
+ dev->val[OPT_SCAN_BR_Y].w = dev->win_y_range.max;
}
static void init_options(struct device *dev)
{
- int i;
-
- for (i = 0; i < NUM_OPTIONS; i++) {
- dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
- dev->opt[i].size = sizeof(SANE_Word);
- dev->opt[i].type = SANE_TYPE_FIXED;
- dev->val[i].s = NULL;
- }
-
- dev->opt[OPT_NUMOPTIONS].name = SANE_NAME_NUM_OPTIONS;
- dev->opt[OPT_NUMOPTIONS].title = SANE_TITLE_NUM_OPTIONS;
- dev->opt[OPT_NUMOPTIONS].desc = SANE_DESC_NUM_OPTIONS;
- dev->opt[OPT_NUMOPTIONS].type = SANE_TYPE_INT;
- dev->opt[OPT_NUMOPTIONS].cap = SANE_CAP_SOFT_DETECT;
- dev->val[OPT_NUMOPTIONS].w = NUM_OPTIONS;
-
- dev->opt[OPT_GROUP_STD].name = SANE_NAME_STANDARD;
- dev->opt[OPT_GROUP_STD].title = SANE_TITLE_STANDARD;
- dev->opt[OPT_GROUP_STD].desc = SANE_DESC_STANDARD;
- dev->opt[OPT_GROUP_STD].type = SANE_TYPE_GROUP;
- dev->opt[OPT_GROUP_STD].cap = 0;
-
- dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
- dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
- dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
- dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
- dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
- dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
- dev->opt[OPT_RESOLUTION].constraint.word_list = dev->dpi_list;
-
- dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
- dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
- dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
- dev->opt[OPT_MODE].type = SANE_TYPE_STRING;
- dev->opt[OPT_MODE].size = max_string_size(scan_modes);
- dev->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
- dev->opt[OPT_MODE].constraint.string_list = scan_modes;
-
- dev->opt[OPT_THRESHOLD].name = SANE_NAME_HIGHLIGHT;
- dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
- dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
- dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
- dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_THRESHOLD].constraint.range = &threshold;
-
- dev->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
- dev->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
- dev->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
- dev->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
- dev->opt[OPT_SOURCE].size = max_string_size(doc_sources);
- dev->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- dev->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
- dev->opt[OPT_SOURCE].constraint.string_list = doc_sources;
-
- dev->opt[OPT_GROUP_GEO].name = SANE_NAME_GEOMETRY;
- dev->opt[OPT_GROUP_GEO].title = SANE_TITLE_GEOMETRY;
- dev->opt[OPT_GROUP_GEO].desc = SANE_DESC_GEOMETRY;
- dev->opt[OPT_GROUP_GEO].type = SANE_TYPE_GROUP;
- dev->opt[OPT_GROUP_GEO].cap = 0;
-
- dev->opt[OPT_SCAN_TL_X].name = SANE_NAME_SCAN_TL_X;
- dev->opt[OPT_SCAN_TL_X].title = SANE_TITLE_SCAN_TL_X;
- dev->opt[OPT_SCAN_TL_X].desc = SANE_DESC_SCAN_TL_X;
- dev->opt[OPT_SCAN_TL_X].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_TL_X].constraint.range = &dev->win_x_range;
-
- dev->opt[OPT_SCAN_TL_Y].name = SANE_NAME_SCAN_TL_Y;
- dev->opt[OPT_SCAN_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
- dev->opt[OPT_SCAN_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
- dev->opt[OPT_SCAN_TL_Y].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_TL_Y].constraint.range = &dev->win_y_range;
-
- dev->opt[OPT_SCAN_BR_X].name = SANE_NAME_SCAN_BR_X;
- dev->opt[OPT_SCAN_BR_X].title = SANE_TITLE_SCAN_BR_X;
- dev->opt[OPT_SCAN_BR_X].desc = SANE_DESC_SCAN_BR_X;
- dev->opt[OPT_SCAN_BR_X].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_BR_X].constraint.range = &dev->win_x_range;
-
- dev->opt[OPT_SCAN_BR_Y].name = SANE_NAME_SCAN_BR_Y;
- dev->opt[OPT_SCAN_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
- dev->opt[OPT_SCAN_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
- dev->opt[OPT_SCAN_BR_Y].unit = SANE_UNIT_MM;
- dev->opt[OPT_SCAN_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
- dev->opt[OPT_SCAN_BR_Y].constraint.range = &dev->win_y_range;
+ int i;
+
+ for (i = 0; i < NUM_OPTIONS; i++) {
+ dev->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
+ dev->opt[i].size = sizeof(SANE_Word);
+ dev->opt[i].type = SANE_TYPE_FIXED;
+ dev->val[i].s = NULL;
+ }
+
+ dev->opt[OPT_NUMOPTIONS].name = SANE_NAME_NUM_OPTIONS;
+ dev->opt[OPT_NUMOPTIONS].title = SANE_TITLE_NUM_OPTIONS;
+ dev->opt[OPT_NUMOPTIONS].desc = SANE_DESC_NUM_OPTIONS;
+ dev->opt[OPT_NUMOPTIONS].type = SANE_TYPE_INT;
+ dev->opt[OPT_NUMOPTIONS].cap = SANE_CAP_SOFT_DETECT;
+ dev->val[OPT_NUMOPTIONS].w = NUM_OPTIONS;
+
+ dev->opt[OPT_GROUP_STD].name = SANE_NAME_STANDARD;
+ dev->opt[OPT_GROUP_STD].title = SANE_TITLE_STANDARD;
+ dev->opt[OPT_GROUP_STD].desc = SANE_DESC_STANDARD;
+ dev->opt[OPT_GROUP_STD].type = SANE_TYPE_GROUP;
+ dev->opt[OPT_GROUP_STD].cap = 0;
+
+ dev->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
+ dev->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
+ dev->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
+ dev->opt[OPT_RESOLUTION].type = SANE_TYPE_INT;
+ dev->opt[OPT_RESOLUTION].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
+ dev->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_WORD_LIST;
+ dev->opt[OPT_RESOLUTION].constraint.word_list = dev->dpi_list;
+
+ dev->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
+ dev->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
+ dev->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
+ dev->opt[OPT_MODE].type = SANE_TYPE_STRING;
+ dev->opt[OPT_MODE].size = max_string_size(scan_modes);
+ dev->opt[OPT_MODE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ dev->opt[OPT_MODE].constraint.string_list = scan_modes;
+
+ dev->opt[OPT_THRESHOLD].name = SANE_NAME_HIGHLIGHT;
+ dev->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
+ dev->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
+ dev->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
+ dev->opt[OPT_THRESHOLD].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_THRESHOLD].constraint.range = &threshold;
+
+ dev->opt[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
+ dev->opt[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
+ dev->opt[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
+ dev->opt[OPT_SOURCE].type = SANE_TYPE_STRING;
+ dev->opt[OPT_SOURCE].size = max_string_size(doc_sources);
+ dev->opt[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
+ dev->opt[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
+ dev->opt[OPT_SOURCE].constraint.string_list = doc_sources;
+
+ dev->opt[OPT_GROUP_GEO].name = SANE_NAME_GEOMETRY;
+ dev->opt[OPT_GROUP_GEO].title = SANE_TITLE_GEOMETRY;
+ dev->opt[OPT_GROUP_GEO].desc = SANE_DESC_GEOMETRY;
+ dev->opt[OPT_GROUP_GEO].type = SANE_TYPE_GROUP;
+ dev->opt[OPT_GROUP_GEO].cap = 0;
+
+ dev->opt[OPT_SCAN_TL_X].name = SANE_NAME_SCAN_TL_X;
+ dev->opt[OPT_SCAN_TL_X].title = SANE_TITLE_SCAN_TL_X;
+ dev->opt[OPT_SCAN_TL_X].desc = SANE_DESC_SCAN_TL_X;
+ dev->opt[OPT_SCAN_TL_X].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_TL_X].constraint.range = &dev->win_x_range;
+
+ dev->opt[OPT_SCAN_TL_Y].name = SANE_NAME_SCAN_TL_Y;
+ dev->opt[OPT_SCAN_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
+ dev->opt[OPT_SCAN_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
+ dev->opt[OPT_SCAN_TL_Y].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_TL_Y].constraint.range = &dev->win_y_range;
+
+ dev->opt[OPT_SCAN_BR_X].name = SANE_NAME_SCAN_BR_X;
+ dev->opt[OPT_SCAN_BR_X].title = SANE_TITLE_SCAN_BR_X;
+ dev->opt[OPT_SCAN_BR_X].desc = SANE_DESC_SCAN_BR_X;
+ dev->opt[OPT_SCAN_BR_X].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_BR_X].constraint.range = &dev->win_x_range;
+
+ dev->opt[OPT_SCAN_BR_Y].name = SANE_NAME_SCAN_BR_Y;
+ dev->opt[OPT_SCAN_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
+ dev->opt[OPT_SCAN_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
+ dev->opt[OPT_SCAN_BR_Y].unit = SANE_UNIT_MM;
+ dev->opt[OPT_SCAN_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
+ dev->opt[OPT_SCAN_BR_Y].constraint.range = &dev->win_y_range;
}
/* fill parameters from options */
static void set_parameters(struct device *dev)
{
- double px_to_len;
+ double px_to_len;
- dev->para.last_frame = SANE_TRUE;
- dev->para.lines = -1;
- px_to_len = 1200.0 / dev->val[OPT_RESOLUTION].w;
+ dev->para.last_frame = SANE_TRUE;
+ dev->para.lines = -1;
+ px_to_len = 1200.0 / dev->val[OPT_RESOLUTION].w;
#define BETTER_BASEDPI 1
- /* tests prove that 1200dpi base is very inexact
- * so I calculated better values for each axis */
-#if BETTER_BASEDPI
- px_to_len = 1180.0 / dev->val[OPT_RESOLUTION].w;
-#endif
- dev->para.pixels_per_line = dev->win_width / px_to_len;
- dev->para.bytes_per_line = dev->para.pixels_per_line;
+ /* tests prove that 1200dpi base is very inexact
+ * so I calculated better values for each axis */
#if BETTER_BASEDPI
- px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w;
+ px_to_len = 1180.0 / dev->val[OPT_RESOLUTION].w;
#endif
- dev->para.lines = dev->win_len / px_to_len;
- if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE) {
- dev->para.format = SANE_FRAME_GRAY;
- dev->para.depth = 1;
- dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
- } else if (dev->composition == MODE_GRAY8) {
- dev->para.format = SANE_FRAME_GRAY;
- dev->para.depth = 8;
+ dev->para.pixels_per_line = dev->win_width / px_to_len;
dev->para.bytes_per_line = dev->para.pixels_per_line;
- } else if (dev->composition == MODE_RGB24) {
- dev->para.format = SANE_FRAME_RGB;
- dev->para.depth = 8;
- dev->para.bytes_per_line *= 3;
- } else {
- /* this will never happen */
- DBG (1, "%s: impossible image composition %d\n",
- __FUNCTION__, dev->composition);
- dev->para.format = SANE_FRAME_GRAY;
- dev->para.depth = 8;
- }
+
+ if (!isSupportedDevice(dev)) {
+#if BETTER_BASEDPI
+ px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w;
+#endif
+ }
+ dev->para.lines = dev->win_len / px_to_len;
+ if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE) {
+ dev->para.format = SANE_FRAME_GRAY;
+ dev->para.depth = 1;
+ dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
+ } else if (dev->composition == MODE_GRAY8) {
+ dev->para.format = SANE_FRAME_GRAY;
+ dev->para.depth = 8;
+ dev->para.bytes_per_line = dev->para.pixels_per_line;
+ } else if (dev->composition == MODE_RGB24) {
+ dev->para.format = SANE_FRAME_RGB;
+ dev->para.depth = 8;
+ dev->para.bytes_per_line *= 3;
+ } else {
+ /* this will never happen */
+ DBG(1, "%s: impossible image composition %d\n",
+ __func__, dev->composition);
+ dev->para.format = SANE_FRAME_GRAY;
+ dev->para.depth = 8;
+ }
}
/* resolve all options related to scan window */
/* called after option changed and in set_window */
static int fix_window(struct device *dev)
{
- double win_width_mm, win_len_mm;
- int i;
- int threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
-
- dev->resolution = dpi_to_code(dev->val[OPT_RESOLUTION].w);
- dev->composition = scan_mode_to_code[string_match_index(scan_modes, dev->val[OPT_MODE].s)];
-
- if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE) {
- dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
- } else {
- dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
- }
- if (threshold < 30) {
- dev->val[OPT_THRESHOLD].w = SANE_FIX(30);
- } else if (threshold > 70) {
- dev->val[OPT_THRESHOLD].w = SANE_FIX(70);
- }
- threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
- dev->threshold = (threshold - 30) / 10;
- dev->val[OPT_THRESHOLD].w = SANE_FIX(dev->threshold * 10 + 30);
-
- dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)];
-
- /* max window len is dependent of document source */
- if (dev->doc_source == DOC_FLATBED ||
- (dev->doc_source == DOC_AUTO && !dev->doc_loaded))
- dev->max_len = dev->max_len_fb;
- else
- dev->max_len = dev->max_len_adf;
-
- /* parameters */
- dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM);
-
- /* window sanity checking */
- for (i = OPT_SCAN_TL_X; i <= OPT_SCAN_BR_Y; i++) {
- if (dev->val[i].w < dev->opt[i].constraint.range->min)
- dev->val[i].w = dev->opt[i].constraint.range->min;
- if (dev->val[i].w > dev->opt[i].constraint.range->max)
- dev->val[i].w = dev->opt[i].constraint.range->max;
- }
-
- if (dev->val[OPT_SCAN_TL_X].w > dev->val[OPT_SCAN_BR_X].w)
- SWAP_Word(dev->val[OPT_SCAN_TL_X].w, dev->val[OPT_SCAN_BR_X].w);
- if (dev->val[OPT_SCAN_TL_Y].w > dev->val[OPT_SCAN_BR_Y].w)
- SWAP_Word(dev->val[OPT_SCAN_TL_Y].w, dev->val[OPT_SCAN_BR_Y].w);
-
- /* recalculate millimeters to inches */
- dev->win_off_x = SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w) / MM_PER_INCH;
- dev->win_off_y = SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w) / MM_PER_INCH;
-
- /* calc win size in mm */
- win_width_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_X].w) -
- SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w);
- win_len_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_Y].w) -
- SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w);
- /* convert mm to 1200 dpi points */
- dev->win_width = (int)(win_width_mm * PNT_PER_MM);
- dev->win_len = (int)(win_len_mm * PNT_PER_MM);
-
- /* don't scan if window is zero size */
- if (!dev->win_width || !dev->win_len) {
- /* "The scan cannot be started with the current set of options." */
- dev->state = SANE_STATUS_INVAL;
- return 0;
- }
+ double win_width_mm, win_len_mm;
+ int i;
+ int threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
- return 1;
-}
+ dev->resolution = dpi_to_code(dev->val[OPT_RESOLUTION].w);
+ dev->composition = scan_mode_to_code[string_match_index(scan_modes, dev->val[OPT_MODE].s)];
-static int dev_set_window (struct device *dev)
-{
- SANE_Byte cmd[0x19] = {
- REQ_CODE_A, REQ_CODE_B, CMD_SET_WINDOW, 0x13, MSG_SCANNING_PARAM
- };
+ if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE) {
+ dev->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
+ } else {
+ dev->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
+ }
+ if (threshold < 30) {
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(30);
+ } else if (threshold > 70) {
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(70);
+ }
+ threshold = SANE_UNFIX(dev->val[OPT_THRESHOLD].w);
+ dev->threshold = (threshold - 30) / 10;
+ dev->val[OPT_THRESHOLD].w = SANE_FIX(dev->threshold * 10 + 30);
- if (!fix_window(dev))
- return 0;
+ dev->doc_source = doc_source_to_code[string_match_index(doc_sources, dev->val[OPT_SOURCE].s)];
+
+ /* max window len is dependent of document source */
+ if (dev->doc_source == DOC_FLATBED ||
+ (dev->doc_source == DOC_AUTO && !dev->doc_loaded))
+ dev->max_len = dev->max_len_fb;
+ else
+ dev->max_len = dev->max_len_adf;
+
+ /* parameters */
+ dev->win_y_range.max = SANE_FIX((double)dev->max_len / PNT_PER_MM);
+
+ /* window sanity checking */
+ for (i = OPT_SCAN_TL_X; i <= OPT_SCAN_BR_Y; i++) {
+ if (dev->val[i].w < dev->opt[i].constraint.range->min)
+ dev->val[i].w = dev->opt[i].constraint.range->min;
+ if (dev->val[i].w > dev->opt[i].constraint.range->max)
+ dev->val[i].w = dev->opt[i].constraint.range->max;
+ }
+
+ if (dev->val[OPT_SCAN_TL_X].w > dev->val[OPT_SCAN_BR_X].w)
+ SWAP_Word(dev->val[OPT_SCAN_TL_X].w, dev->val[OPT_SCAN_BR_X].w);
+ if (dev->val[OPT_SCAN_TL_Y].w > dev->val[OPT_SCAN_BR_Y].w)
+ SWAP_Word(dev->val[OPT_SCAN_TL_Y].w, dev->val[OPT_SCAN_BR_Y].w);
+
+ /* recalculate millimeters to inches */
+ dev->win_off_x = SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w) / MM_PER_INCH;
+ dev->win_off_y = SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w) / MM_PER_INCH;
+
+ /* calc win size in mm */
+ win_width_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_X].w) -
+ SANE_UNFIX(dev->val[OPT_SCAN_TL_X].w);
+ win_len_mm = SANE_UNFIX(dev->val[OPT_SCAN_BR_Y].w) -
+ SANE_UNFIX(dev->val[OPT_SCAN_TL_Y].w);
+ /* convert mm to 1200 dpi points */
+ dev->win_width = (int)(win_width_mm * PNT_PER_MM);
+ dev->win_len = (int)(win_len_mm * PNT_PER_MM);
+
+ /* don't scan if window is zero size */
+ if (!dev->win_width || !dev->win_len) {
+ /* "The scan cannot be started with the current set of options." */
+ dev->state = SANE_STATUS_INVAL;
+ return 0;
+ }
- cmd[0x05] = dev->win_width >> 24;
- cmd[0x06] = dev->win_width >> 16;
- cmd[0x07] = dev->win_width >> 8;
- cmd[0x08] = dev->win_width;
- cmd[0x09] = dev->win_len >> 24;
- cmd[0x0a] = dev->win_len >> 16;
- cmd[0x0b] = dev->win_len >> 8;
- cmd[0x0c] = dev->win_len;
- cmd[0x0d] = dev->resolution; /* x */
- cmd[0x0e] = dev->resolution; /* y */
- cmd[0x0f] = (SANE_Byte)floor(dev->win_off_x);
- cmd[0x10] = (SANE_Byte)((dev->win_off_x - floor(dev->win_off_x)) * 100);
- cmd[0x11] = (SANE_Byte)floor(dev->win_off_y);
- cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100);
- cmd[0x13] = dev->composition;
- cmd[0x16] = dev->threshold;
- cmd[0x17] = dev->doc_source;
-
- DBG (5, "OFF xi: %02x%02x yi: %02x%02x,"
- " WIN xp: %02x%02x%02x%02x yp %02x%02x%02x%02x,"
- " MAX %08x %08x\n",
- cmd[0x0f], cmd[0x10], cmd[0x11], cmd[0x12],
- cmd[0x05], cmd[0x06], cmd[0x07], cmd[0x08],
- cmd[0x09], cmd[0x0a], cmd[0x0b], cmd[0x0c],
- dev->max_win_width, dev->max_win_len);
-
- return dev_command (dev, cmd, 32);
+ return 1;
+}
+
+static int dev_set_window(struct device *dev)
+{
+ SANE_Byte cmd[0x19] = {
+ REQ_CODE_A, REQ_CODE_B, CMD_SET_WINDOW, 0x13, MSG_SCANNING_PARAM
+ };
+
+ if (!fix_window(dev))
+ return 0;
+
+ cmd[0x05] = dev->win_width >> 24;
+ cmd[0x06] = dev->win_width >> 16;
+ cmd[0x07] = dev->win_width >> 8;
+ cmd[0x08] = dev->win_width;
+ cmd[0x09] = dev->win_len >> 24;
+ cmd[0x0a] = dev->win_len >> 16;
+ cmd[0x0b] = dev->win_len >> 8;
+ cmd[0x0c] = dev->win_len;
+ cmd[0x0d] = dev->resolution; /* x */
+ cmd[0x0e] = dev->resolution; /* y */
+ cmd[0x0f] = (SANE_Byte)floor(dev->win_off_x);
+ cmd[0x10] = (SANE_Byte)((dev->win_off_x - floor(dev->win_off_x)) * 100);
+ cmd[0x11] = (SANE_Byte)floor(dev->win_off_y);
+ cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100);
+ cmd[0x13] = dev->composition;
+ /* Set to JPEG Lossy Compression, if mode is color (only for supported model)...
+ * else go with Uncompressed (For backard compatibility with old models )*/
+ if (dev->composition == MODE_RGB24) {
+ if (isSupportedDevice(dev)) {
+ cmd[0x14] = 0x6;
+ }
+ }
+ cmd[0x16] = dev->threshold;
+ cmd[0x17] = dev->doc_source;
+
+ DBG(5, "OFF xi: %02x%02x yi: %02x%02x,"
+ " WIN xp: %02x%02x%02x%02x yp %02x%02x%02x%02x,"
+ " MAX %08x %08x\n",
+ cmd[0x0f], cmd[0x10], cmd[0x11], cmd[0x12],
+ cmd[0x05], cmd[0x06], cmd[0x07], cmd[0x08],
+ cmd[0x09], cmd[0x0a], cmd[0x0b], cmd[0x0c],
+ dev->max_win_width, dev->max_win_len);
+
+ return dev_command(dev, cmd, 32);
}
static SANE_Status
-dev_inquiry (struct device *dev)
+dev_inquiry(struct device *dev)
{
- SANE_Byte *ptr;
- SANE_Char *optr, *xptr;
-
- if (!dev_cmd (dev, CMD_INQUIRY))
- return SANE_STATUS_IO_ERROR;
- ptr = dev->res;
- if (ptr[3] != MSG_PRODUCT_INFO) {
- DBG (1, "%s: illegal INQUIRY response %02x\n", __FUNCTION__, ptr[3]);
- return SANE_STATUS_IO_ERROR;
- }
-
- /* parse reported manufacturer/product names */
- dev->sane.vendor = optr = (SANE_Char *) malloc (33);
- for (ptr += 4; ptr < &dev->res[0x24] && *ptr && *ptr != ' ';)
- *optr++ = *ptr++;
- *optr++ = 0;
-
- for (; ptr < &dev->res[0x24] && (!*ptr || *ptr == ' '); ptr++)
- /* skip spaces */;
-
- dev->sane.model = optr = (SANE_Char *) malloc (33);
- xptr = optr; /* is last non space character + 1 */
- for (; ptr < &dev->res[0x24] && *ptr;) {
- if (*ptr != ' ')
- xptr = optr + 1;
- *optr++ = *ptr++;
- }
- *optr++ = 0;
- *xptr = 0;
-
- DBG (1, "%s: found %s/%s\n", __FUNCTION__, dev->sane.vendor, dev->sane.model);
- dev->sane.type = strdup ("multi-function peripheral");
-
- dev->resolutions = dev->res[0x37] << 16 |
- dev->res[0x24] << 8 |
- dev->res[0x25];
- dev->compositions = dev->res[0x27];
- dev->max_win_width = dev->res[0x28] << 24 |
- dev->res[0x29] << 16 |
- dev->res[0x2a] << 8 |
- dev->res[0x2b];
- dev->max_win_len = dev->res[0x2c] << 24 |
- dev->res[0x2d] << 16 |
- dev->res[0x2e] << 8 |
- dev->res[0x2f];
- dev->max_len_adf = dev->res[0x38] << 24 |
- dev->res[0x39] << 16 |
- dev->res[0x3a] << 8 |
- dev->res[0x3b];
- dev->max_len_fb = dev->res[0x3c] << 24 |
- dev->res[0x3d] << 16 |
- dev->res[0x3e] << 8 |
- dev->res[0x3f];
- dev->line_order = dev->res[0x31];
- dev->doc_loaded = (dev->res[0x35] == 0x02) &&
- (dev->res[0x26] & 0x03);
-
- init_options(dev);
- reset_options(dev);
- fix_window(dev);
- set_parameters(dev);
- resolv_inq_dpi(dev);
-
- return SANE_STATUS_GOOD;
+ SANE_Byte *ptr;
+ SANE_Char *optr, *xptr;
+
+ if (!dev_cmd(dev, CMD_INQUIRY))
+ return SANE_STATUS_IO_ERROR;
+ ptr = dev->res;
+ if (ptr[3] != MSG_PRODUCT_INFO) {
+ DBG(1, "%s: illegal INQUIRY response %02x\n", __func__, ptr[3]);
+ return SANE_STATUS_IO_ERROR;
+ }
+
+ /* parse reported manufacturer/product names */
+ dev->sane.vendor = optr = (SANE_Char *) malloc(33);
+ for (ptr += 4; ptr < &dev->res[0x24] && *ptr && *ptr != ' ';)
+ *optr++ = *ptr++;
+ *optr++ = 0;
+
+ for (; ptr < &dev->res[0x24] && (!*ptr || *ptr == ' '); ptr++)
+ /* skip spaces */;
+
+ dev->sane.model = optr = (SANE_Char *) malloc(33);
+ xptr = optr; /* is last non space character + 1 */
+ for (; ptr < &dev->res[0x24] && *ptr;) {
+ if (*ptr != ' ')
+ xptr = optr + 1;
+ *optr++ = *ptr++;
+ }
+ *optr++ = 0;
+ *xptr = 0;
+
+ DBG(1, "%s: found %s/%s\n", __func__, dev->sane.vendor, dev->sane.model);
+ dev->sane.type = strdup("multi-function peripheral");
+
+ dev->resolutions = dev->res[0x37] << 16 |
+ dev->res[0x24] << 8 |
+ dev->res[0x25];
+ dev->compositions = dev->res[0x27];
+ dev->max_win_width = dev->res[0x28] << 24 |
+ dev->res[0x29] << 16 |
+ dev->res[0x2a] << 8 |
+ dev->res[0x2b];
+ dev->max_win_len = dev->res[0x2c] << 24 |
+ dev->res[0x2d] << 16 |
+ dev->res[0x2e] << 8 |
+ dev->res[0x2f];
+ dev->max_len_adf = dev->res[0x38] << 24 |
+ dev->res[0x39] << 16 |
+ dev->res[0x3a] << 8 |
+ dev->res[0x3b];
+ dev->max_len_fb = dev->res[0x3c] << 24 |
+ dev->res[0x3d] << 16 |
+ dev->res[0x3e] << 8 |
+ dev->res[0x3f];
+ dev->line_order = dev->res[0x31];
+ dev->compressionTypes = dev->res[0x32];
+ dev->doc_loaded = (dev->res[0x35] == 0x02) &&
+ (dev->res[0x26] & 0x03);
+
+ init_options(dev);
+ reset_options(dev);
+ fix_window(dev);
+ set_parameters(dev);
+ resolv_inq_dpi(dev);
+
+ return SANE_STATUS_GOOD;
}
const SANE_Option_Descriptor *
-sane_get_option_descriptor (SANE_Handle h, SANE_Int opt)
+sane_get_option_descriptor(SANE_Handle h, SANE_Int opt)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p, %d\n", __FUNCTION__, h, opt);
- if (opt >= NUM_OPTIONS || opt < 0)
- return NULL;
- return &dev->opt[opt];
+ DBG(3, "%s: %p, %d\n", __func__, h, opt);
+ if (opt >= NUM_OPTIONS || opt < 0)
+ return NULL;
+ return &dev->opt[opt];
}
SANE_Status
-sane_control_option (SANE_Handle h, SANE_Int opt, SANE_Action act,
- void *val, SANE_Word * info)
+sane_control_option(SANE_Handle h, SANE_Int opt, SANE_Action act,
+ void *val, SANE_Word *info)
{
- struct device *dev = h;
-
- DBG (3, "%s: %p, %d, <%d>, %p, %p\n", __FUNCTION__, h, opt, act, val, (void *)info);
- if (!dev || opt >= NUM_OPTIONS || opt < 0)
- return SANE_STATUS_INVAL;
-
- if (info)
- *info = 0;
-
- if (act == SANE_ACTION_GET_VALUE) { /* GET */
- if (dev->opt[opt].type == SANE_TYPE_STRING)
- strcpy(val, dev->val[opt].s);
- else
- *(SANE_Word *)val = dev->val[opt].w;
- } else if (act == SANE_ACTION_SET_VALUE) { /* SET */
- SANE_Parameters xpara = dev->para;
- SANE_Option_Descriptor xopt[NUM_OPTIONS];
- Option_Value xval[NUM_OPTIONS];
- int i;
-
- if (dev->opt[opt].constraint_type == SANE_CONSTRAINT_STRING_LIST) {
- dev->val[opt].s = string_match(dev->opt[opt].constraint.string_list, val);
- if (info && strcasecmp(dev->val[opt].s, val))
- *info |= SANE_INFO_INEXACT;
- } else if (opt == OPT_RESOLUTION)
- dev->val[opt].w = res_dpi_codes[dpi_to_code(*(SANE_Word *)val)];
- else
- dev->val[opt].w = *(SANE_Word *)val;
-
- memcpy(&xopt, &dev->opt, sizeof(xopt));
- memcpy(&xval, &dev->val, sizeof(xval));
- fix_window(dev);
- set_parameters(dev);
-
- /* check for side effects */
- if (info) {
- if (memcmp(&xpara, &dev->para, sizeof(xpara)))
- *info |= SANE_INFO_RELOAD_PARAMS;
- if (memcmp(&xopt, &dev->opt, sizeof(xopt)))
- *info |= SANE_INFO_RELOAD_OPTIONS;
- for (i = 0; i < NUM_OPTIONS; i++)
- if (xval[i].w != dev->val[i].w) {
- if (i == opt)
- *info |= SANE_INFO_INEXACT;
- else
- *info |= SANE_INFO_RELOAD_OPTIONS;
- }
+ struct device *dev = h;
+
+ DBG(3, "%s: %p, %d, <%d>, %p, %p\n", __func__, h, opt, act, val, (void *)info);
+ if (!dev || opt >= NUM_OPTIONS || opt < 0)
+ return SANE_STATUS_INVAL;
+
+ if (info)
+ *info = 0;
+
+ if (act == SANE_ACTION_GET_VALUE) { /* GET */
+ if (dev->opt[opt].type == SANE_TYPE_STRING)
+ strcpy(val, dev->val[opt].s);
+ else
+ *(SANE_Word *)val = dev->val[opt].w;
+ } else if (act == SANE_ACTION_SET_VALUE) { /* SET */
+ SANE_Parameters xpara = dev->para;
+ SANE_Option_Descriptor xopt[NUM_OPTIONS];
+ Option_Value xval[NUM_OPTIONS];
+ int i;
+
+ if (dev->opt[opt].constraint_type == SANE_CONSTRAINT_STRING_LIST) {
+ dev->val[opt].s = string_match(dev->opt[opt].constraint.string_list, val);
+ if (info && strcasecmp(dev->val[opt].s, val))
+ *info |= SANE_INFO_INEXACT;
+ } else if (opt == OPT_RESOLUTION)
+ dev->val[opt].w = res_dpi_codes[dpi_to_code(*(SANE_Word *)val)];
+ else
+ dev->val[opt].w = *(SANE_Word *)val;
+
+ memcpy(&xopt, &dev->opt, sizeof(xopt));
+ memcpy(&xval, &dev->val, sizeof(xval));
+ fix_window(dev);
+ set_parameters(dev);
+
+ /* check for side effects */
+ if (info) {
+ if (memcmp(&xpara, &dev->para, sizeof(xpara)))
+ *info |= SANE_INFO_RELOAD_PARAMS;
+ if (memcmp(&xopt, &dev->opt, sizeof(xopt)))
+ *info |= SANE_INFO_RELOAD_OPTIONS;
+ for (i = 0; i < NUM_OPTIONS; i++)
+ if (xval[i].w != dev->val[i].w) {
+ if (i == opt)
+ *info |= SANE_INFO_INEXACT;
+ else
+ *info |= SANE_INFO_RELOAD_OPTIONS;
+ }
+ }
}
- }
- DBG (4, "%s: %d, <%d> => %08x, %x\n", __FUNCTION__, opt, act,
- val? *(SANE_Word *)val : 0, info? *info : 0);
- return SANE_STATUS_GOOD;
+ DBG(4, "%s: %d, <%d> => %08x, %x\n", __func__, opt, act,
+ val? *(SANE_Word *)val : 0, info? *info : 0);
+ return SANE_STATUS_GOOD;
}
static void
-dev_free (struct device *dev)
+dev_free(struct device *dev)
{
- if (!dev)
- return;
-
- if (dev->sane.name)
- free (UNCONST(dev->sane.name));
- if (dev->sane.vendor)
- free (UNCONST(dev->sane.vendor));
- if (dev->sane.model)
- free (UNCONST(dev->sane.model));
- if (dev->sane.type)
- free (UNCONST(dev->sane.type));
- if (dev->data)
- free(dev->data);
- memset (dev, 0, sizeof (*dev));
- free (dev);
+ if (!dev)
+ return;
+
+ if (dev->sane.name)
+ free(UNCONST(dev->sane.name));
+ if (dev->sane.vendor)
+ free(UNCONST(dev->sane.vendor));
+ if (dev->sane.model)
+ free(UNCONST(dev->sane.model));
+ if (dev->sane.type)
+ free(UNCONST(dev->sane.type));
+ if (dev->data)
+ free(dev->data);
+ if (dev->decData) {
+ free(dev->decData);
+ dev->decData = NULL;
+ }
+ memset(dev, 0, sizeof(*dev));
+ free(dev);
}
static void
-free_devices (void)
+free_devices(void)
{
- int i;
- struct device *next;
- struct device *dev;
-
- if (devlist) {
- free (devlist);
- devlist = NULL;
- }
- for (i = 0, dev = devices_head; dev; dev = next) {
- next = dev->next;
- dev_free (dev);
- }
- devices_head = NULL;
+ struct device *next;
+ struct device *dev;
+
+ if (devlist) {
+ free(devlist);
+ devlist = NULL;
+ }
+ for (dev = devices_head; dev; dev = next) {
+ next = dev->next;
+ dev_free(dev);
+ }
+ devices_head = NULL;
}
static transport *tr_from_devname(SANE_String_Const devname)
{
- if (strncmp("tcp", devname, 3) == 0)
- return &available_transports[TRANSPORT_TCP];
- return &available_transports[TRANSPORT_USB];
+ if (strncmp("tcp", devname, 3) == 0)
+ return &available_transports[TRANSPORT_TCP];
+ return &available_transports[TRANSPORT_USB];
}
static SANE_Status
-list_one_device (SANE_String_Const devname)
+list_one_device(SANE_String_Const devname)
{
- struct device *dev;
- SANE_Status status;
- transport *tr;
-
- DBG (4, "%s: %s\n", __FUNCTION__, devname);
-
- for (dev = devices_head; dev; dev = dev->next) {
- if (strcmp (dev->sane.name, devname) == 0)
- return SANE_STATUS_GOOD;
- }
-
- tr = tr_from_devname(devname);
-
- dev = calloc (1, sizeof (struct device));
- if (dev == NULL)
- return SANE_STATUS_NO_MEM;
-
- dev->sane.name = strdup (devname);
- dev->io = tr;
- status = tr->dev_open (dev);
- if (status != SANE_STATUS_GOOD) {
- dev_free (dev);
- return status;
- }
-
-/* status = dev_cmd (dev, CMD_ABORT);*/
- status = dev_inquiry (dev);
- tr->dev_close (dev);
- if (status != SANE_STATUS_GOOD) {
- DBG (1, "%s: dev_inquiry(%s): %s\n", __FUNCTION__,
- dev->sane.name, sane_strstatus (status));
- dev_free (dev);
- return status;
- }
-
- /* good device, add it to list */
- dev->next = devices_head;
- devices_head = dev;
- return SANE_STATUS_GOOD;
+ struct device *dev;
+ SANE_Status status;
+ transport *tr;
+
+ DBG(4, "%s: %s\n", __func__, devname);
+
+ for (dev = devices_head; dev; dev = dev->next) {
+ if (strcmp(dev->sane.name, devname) == 0)
+ return SANE_STATUS_GOOD;
+ }
+
+ tr = tr_from_devname(devname);
+
+ dev = calloc(1, sizeof(struct device));
+ if (dev == NULL)
+ return SANE_STATUS_NO_MEM;
+
+ dev->sane.name = strdup(devname);
+ dev->io = tr;
+ status = tr->dev_open(dev);
+ if (status != SANE_STATUS_GOOD) {
+ dev_free(dev);
+ return status;
+ }
+
+ /* status = dev_cmd (dev, CMD_ABORT);*/
+ status = dev_inquiry(dev);
+ tr->dev_close(dev);
+ if (status != SANE_STATUS_GOOD) {
+ DBG(1, "%s: dev_inquiry(%s): %s\n", __func__,
+ dev->sane.name, sane_strstatus(status));
+ dev_free(dev);
+ return status;
+ }
+
+ /* good device, add it to list */
+ dev->next = devices_head;
+ devices_head = dev;
+ return SANE_STATUS_GOOD;
}
/* SANE API ignores return code of this callback */
static SANE_Status
-list_conf_devices (UNUSED (SANEI_Config * config), const char *devname)
+list_conf_devices(UNUSED(SANEI_Config *config), const char *devname)
{
- return tr_from_devname(devname)->configure_device(devname, list_one_device);
+ return tr_from_devname(devname)->configure_device(devname, list_one_device);
}
SANE_Status
-sane_init (SANE_Int * version_code, SANE_Auth_Callback cb)
+sane_init(SANE_Int *version_code, SANE_Auth_Callback cb)
{
- DBG_INIT ();
- DBG (2, "sane_init: Xerox backend (build %d), version %s null, authorize %s null\n", BACKEND_BUILD,
- (version_code) ? "!=" : "==", (cb) ? "!=" : "==");
+ DBG_INIT();
+ DBG(2, "sane_init: Xerox backend (build %d), version %s null, authorize %s null\n", BACKEND_BUILD,
+ (version_code) ? "!=" : "==", (cb) ? "!=" : "==");
- if (version_code)
- *version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR, BACKEND_BUILD);
+ if (version_code)
+ *version_code = SANE_VERSION_CODE(V_MAJOR, V_MINOR, BACKEND_BUILD);
- sanei_usb_init ();
- return SANE_STATUS_GOOD;
+ sanei_usb_init();
+ return SANE_STATUS_GOOD;
}
void
-sane_exit (void)
+sane_exit(void)
{
- struct device *dev;
+ struct device *dev;
+
+ for (dev = devices_head; dev; dev = dev->next)
+ if (dev->dn != -1)
+ sane_close(dev); /* implies flush */
- for (dev = devices_head; dev; dev = dev->next)
- if (dev->dn != -1)
- sane_close(dev); /* implies flush */
-
- free_devices ();
+ free_devices();
}
SANE_Status
-sane_get_devices (const SANE_Device *** device_list, SANE_Bool local)
+sane_get_devices(const SANE_Device *** device_list, SANE_Bool local)
{
- SANEI_Config config;
- struct device *dev;
- int dev_count;
- int i;
+ SANEI_Config config;
+ struct device *dev;
+ int dev_count;
+ int i;
- DBG (3, "%s: %p, %d\n", __FUNCTION__, (const void *)device_list, local);
+ DBG(3, "%s: %p, %d\n", __func__, (const void *)device_list, local);
- if (devlist) {
- if (device_list)
- *device_list = devlist;
- return SANE_STATUS_GOOD;
- }
+ if (devlist) {
+ if (device_list)
+ *device_list = devlist;
+ return SANE_STATUS_GOOD;
+ }
- free_devices ();
+ free_devices();
- config.count = 0;
- config.descriptors = NULL;
- config.values = NULL;
- sanei_configure_attach (XEROX_CONFIG_FILE, &config, list_conf_devices);
+ config.count = 0;
+ config.descriptors = NULL;
+ config.values = NULL;
+ sanei_configure_attach(XEROX_CONFIG_FILE, &config, list_conf_devices);
- for (dev_count = 0, dev = devices_head; dev; dev = dev->next)
- dev_count++;
+ for (dev_count = 0, dev = devices_head; dev; dev = dev->next)
+ dev_count++;
- devlist = malloc ((dev_count + 1) * sizeof (*devlist));
- if (!devlist)
- {
- DBG (1, "%s: malloc: no memory\n", __FUNCTION__);
- return SANE_STATUS_NO_MEM;
+ devlist = malloc((dev_count + 1) * sizeof(*devlist));
+ if (!devlist) {
+ DBG(1, "%s: malloc: no memory\n", __func__);
+ return SANE_STATUS_NO_MEM;
}
- for (i = 0, dev = devices_head; dev; dev = dev->next)
- devlist[i++] = &dev->sane;
- devlist[i++] = NULL;
+ for (i = 0, dev = devices_head; dev; dev = dev->next)
+ devlist[i++] = &dev->sane;
+ devlist[i++] = NULL;
- if (device_list)
- *device_list = devlist;
- return SANE_STATUS_GOOD;
+ if (device_list)
+ *device_list = devlist;
+ return SANE_STATUS_GOOD;
}
void
-sane_close (SANE_Handle h)
+sane_close(SANE_Handle h)
{
- struct device *dev = h;
+ struct device *dev = h;
- if (!dev)
- return;
+ if (!dev)
+ return;
- DBG (3, "%s: %p (%s)\n", __FUNCTION__, (void *)dev, dev->sane.name);
- dev->io->dev_close(dev);
+ DBG(3, "%s: %p (%s)\n", __func__, (void *)dev, dev->sane.name);
+ dev->io->dev_close(dev);
}
SANE_Status
-sane_open (SANE_String_Const name, SANE_Handle * h)
+sane_open(SANE_String_Const name, SANE_Handle *h)
{
- struct device *dev;
-
- DBG (3, "%s: '%s'\n", __FUNCTION__, name);
-
- if (!devlist)
- sane_get_devices (NULL, SANE_TRUE);
-
- if (!name || !*name) {
- /* special case of empty name: open first available device */
- for (dev = devices_head; dev; dev = dev->next) {
- if (dev->dn != -1) {
- if (sane_open (dev->sane.name, h) == SANE_STATUS_GOOD)
- return SANE_STATUS_GOOD;
- }
+ struct device *dev;
+
+ DBG(3, "%s: '%s'\n", __func__, name);
+
+ if (!devlist)
+ sane_get_devices(NULL, SANE_TRUE);
+
+ if (!name || !*name) {
+ /* special case of empty name: open first available device */
+ for (dev = devices_head; dev; dev = dev->next) {
+ if (dev->dn != -1) {
+ if (sane_open(dev->sane.name, h) == SANE_STATUS_GOOD)
+ return SANE_STATUS_GOOD;
+ }
+ }
+ } else {
+ for (dev = devices_head; dev; dev = dev->next) {
+ if (strcmp(name, dev->sane.name) == 0) {
+ *h = dev;
+ return dev->io->dev_open(dev);
+ }
+ }
}
- } else {
- for (dev = devices_head; dev; dev = dev->next) {
- if (strcmp(name, dev->sane.name) == 0) {
- *h = dev;
- return dev->io->dev_open(dev);
- }
- }
- }
- return SANE_STATUS_INVAL;
+ return SANE_STATUS_INVAL;
}
SANE_Status
-sane_get_parameters (SANE_Handle h, SANE_Parameters * para)
+sane_get_parameters(SANE_Handle h, SANE_Parameters *para)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p, %p\n", __FUNCTION__, h, (void *)para);
- if (!para)
- return SANE_STATUS_INVAL;
+ DBG(3, "%s: %p, %p\n", __func__, h, (void *)para);
+ if (!para)
+ return SANE_STATUS_INVAL;
- *para = dev->para;
- return SANE_STATUS_GOOD;
+ *para = dev->para;
+ return SANE_STATUS_GOOD;
}
/* check if image data is ready, and wait if not */
/* 1: image is acquired, 0: error or non_blocking mode */
static int dev_acquire(struct device *dev)
{
- if (!dev_cmd_wait(dev, CMD_READ))
- return dev->state;
-
- dev->state = SANE_STATUS_GOOD;
- dev->vertical = dev->res[0x08] << 8 | dev->res[0x09];
- dev->horizontal = dev->res[0x0a] << 8 | dev->res[0x0b];
- dev->blocklen = dev->res[4] << 24 |
- dev->res[5] << 16 |
- dev->res[6] << 8 |
- dev->res[7];
- dev->final_block = (dev->res[3] == MSG_END_BLOCK)? 1 : 0;
-
- dev->pixels_per_line = dev->horizontal;
- dev->bytes_per_line = dev->horizontal;
-
- if (dev->composition == MODE_RGB24)
- dev->bytes_per_line *= 3;
- else if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE)
- dev->pixels_per_line *= 8;
-
- DBG (4, "acquiring, size per band v: %d, h: %d, %sblock: %d, slack: %d\n",
- dev->vertical, dev->horizontal, dev->final_block? "last " : "",
- dev->blocklen, dev->blocklen - (dev->vertical * dev->bytes_per_line));
-
- if (dev->bytes_per_line > DATASIZE) {
- DBG (1, "%s: unsupported line size: %d bytes > %d\n",
- __FUNCTION__, dev->bytes_per_line, DATASIZE);
- return ret_cancel(dev, SANE_STATUS_NO_MEM);
- }
-
- dev->reading = 0; /* need to issue READ_IMAGE */
-
- dev->dataindex = 0;
- dev->datalen = 0;
- dev->dataoff = 0;
-
- return 1;
+ if (!dev_cmd_wait(dev, CMD_READ))
+ return dev->state;
+
+ dev->state = SANE_STATUS_GOOD;
+ dev->vertical = dev->res[0x08] << 8 | dev->res[0x09];
+ dev->horizontal = dev->res[0x0a] << 8 | dev->res[0x0b];
+ dev->blocklen = dev->res[4] << 24 |
+ dev->res[5] << 16 |
+ dev->res[6] << 8 |
+ dev->res[7];
+ dev->final_block = (dev->res[3] == MSG_END_BLOCK)? 1 : 0;
+
+ dev->pixels_per_line = dev->horizontal;
+ dev->bytes_per_line = dev->horizontal;
+
+ if (dev->composition == MODE_RGB24)
+ dev->bytes_per_line *= 3;
+ else if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE)
+ dev->pixels_per_line *= 8;
+
+ DBG(4, "acquiring, size per band v: %d, h: %d, %sblock: %d, slack: %d\n",
+ dev->vertical, dev->horizontal, dev->final_block? "last " : "",
+ dev->blocklen, dev->blocklen - (dev->vertical * dev->bytes_per_line));
+
+ if (dev->bytes_per_line > DATASIZE) {
+ DBG(1, "%s: unsupported line size: %d bytes > %d\n",
+ __func__, dev->bytes_per_line, DATASIZE);
+ return ret_cancel(dev, SANE_STATUS_NO_MEM);
+ }
+
+ dev->reading = 0; /* need to issue READ_IMAGE */
+
+ dev->dataindex = 0;
+ dev->datalen = 0;
+ dev->dataoff = 0;
+
+ return 1;
}
static int fill_slack(struct device *dev, SANE_Byte *buf, int maxlen)
{
- const int slack = dev->total_img_size - dev->total_out_size;
- const int havelen = MIN(slack, maxlen);
- int j;
-
- if (havelen <= 0)
- return 0;
- for (j = 0; j < havelen; j++)
- buf[j] = 255;
- return havelen;
+ const int slack = dev->total_img_size - dev->total_out_size;
+ const int havelen = MIN(slack, maxlen);
+ int j;
+
+ if (havelen <= 0)
+ return 0;
+ for (j = 0; j < havelen; j++)
+ buf[j] = 255;
+ return havelen;
}
static int copy_plain_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp)
{
- int j;
- const int linesize = dev->bytes_per_line;
- int k = dev->dataindex;
- *olenp = 0;
- for (j = 0; j < dev->datalen && *olenp < maxlen; j++, k++) {
- const int x = k % linesize;
- const int y = k / linesize;
- if (y >= dev->vertical)
- break; /* slack */
- if (x < dev->para.bytes_per_line &&
- (y + dev->y_off) < dev->para.lines) {
- *buf++ = dev->data[(dev->dataoff + j) & DATAMASK];
- (*olenp)++;
+ int j;
+ const int linesize = dev->bytes_per_line;
+ int k = dev->dataindex;
+ *olenp = 0;
+ for (j = 0; j < dev->datalen && *olenp < maxlen; j++, k++) {
+ const int x = k % linesize;
+ const int y = k / linesize;
+ if (y >= dev->vertical)
+ break; /* slack */
+ if (x < dev->para.bytes_per_line &&
+ (y + dev->y_off) < dev->para.lines) {
+ *buf++ = dev->data[(dev->dataoff + j) & DATAMASK];
+ (*olenp)++;
+ }
}
- }
- dev->dataindex = k;
- return j;
+ dev->dataindex = k;
+ return j;
}
/* return: how much data could be freed from cyclic buffer */
/* convert from RRGGBB to RGBRGB */
-static int copy_mix_bands_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp) {
- int j;
+static int copy_mix_bands_trim(struct device *dev, SANE_Byte *buf, int maxlen, int *olenp)
+{
+ int j;
- const int linesize = dev->bytes_per_line; /* caching real line size */
+ const int linesize = dev->bytes_per_line; /* caching real line size */
- /* line number of the head of input buffer,
- * input buffer is always aligned to whole line */
- const int y_off = dev->dataindex / linesize;
+ /* line number of the head of input buffer,
+ * input buffer is always aligned to whole line */
+ const int y_off = dev->dataindex / linesize;
- int k = dev->dataindex; /* caching current index of input buffer */
+ int k = dev->dataindex; /* caching current index of input buffer */
- /* can only copy as much as full lines we have */
- int havelen = dev->datalen / linesize * linesize - k % linesize;
+ /* can only copy as much as full lines we have */
+ int havelen = dev->datalen / linesize * linesize - k % linesize;
- const int bands = 3;
- *olenp = 0;
+ const int bands = 3;
+ *olenp = 0;
- /* while we have data && they can receive */
- for (j = 0; j < havelen && *olenp < maxlen; j++, k++) {
- const int band = (k % bands) * dev->horizontal;
- const int x = k % linesize / bands;
- const int y = k / linesize - y_off; /* y relative to buffer head */
- const int y_rly = y + y_off + dev->y_off; /* global y */
+ /* while we have data && they can receive */
+ for (j = 0; j < havelen && *olenp < maxlen; j++, k++) {
+ const int band = (k % bands) * dev->horizontal;
+ const int x = k % linesize / bands;
+ const int y = k / linesize - y_off; /* y relative to buffer head */
+ const int y_rly = y + y_off + dev->y_off; /* global y */
- if (x < dev->para.pixels_per_line &&
- y_rly < dev->para.lines) {
- *buf++ = dev->data[(dev->dataoff + band + x + y * linesize) & DATAMASK];
- (*olenp)++;
+ if (x < dev->para.pixels_per_line &&
+ y_rly < dev->para.lines) {
+ *buf++ = dev->data[(dev->dataoff + band + x + y * linesize) & DATAMASK];
+ (*olenp)++;
+ }
}
- }
- dev->dataindex = k;
+ dev->dataindex = k;
- /* how much full lines are finished */
- return (k / linesize - y_off) * linesize;
+ /* how much full lines are finished */
+ return (k / linesize - y_off) * linesize;
}
SANE_Status
-sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp)
+sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *lenp)
{
- SANE_Status status;
- struct device *dev = h;
+ SANE_Status status;
+ struct device *dev = h;
+
+ DBG(3, "%s: %p, %p, %d, %p\n", __func__, h, buf, maxlen, (void *)lenp);
+
+ if (lenp)
+ *lenp = 0;
+ if (!dev)
+ return SANE_STATUS_INVAL;
+
+ if (!dev->scanning)
+ return SANE_STATUS_EOF;
+
+ /* if there is no data to read or output from buffer */
+ if (!dev->blocklen && dev->datalen <= PADDING_SIZE) {
+
+ /* copying uncompressed data */
+ if (dev->composition == MODE_RGB24 &&
+ isSupportedDevice(dev) &&
+ dev->decDataSize > 0) {
+ int diff = dev->total_img_size - dev->total_out_size;
+ int bufLen = (diff < maxlen) ? diff : maxlen;
+ if (0 < diff &&
+ 0 < copy_decompress_data(dev, buf, bufLen, lenp)) {
+ dev->total_out_size += *lenp;
+ return SANE_STATUS_GOOD;
+ }
+ }
+
+ /* and we don't need to acquire next block */
+ if (dev->final_block) {
+ int slack = dev->total_img_size - dev->total_out_size;
+
+ /* but we may need to fill slack */
+ if (buf && lenp && slack > 0) {
+ *lenp = fill_slack(dev, buf, maxlen);
+ dev->total_out_size += *lenp;
+ DBG(9, "<> slack: %d, filled: %d, maxlen %d\n",
+ slack, *lenp, maxlen);
+ return SANE_STATUS_GOOD;
+ } else if (slack < 0) {
+ /* this will never happen */
+ DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size);
+ }
+ if (isSupportedDevice(dev) &&
+ dev->composition == MODE_RGB24) {
+ remove(encTmpFileName);
+ }
+ /* that's all */
+ dev_stop(dev);
+ return SANE_STATUS_EOF;
+ }
+
+ /* queue next image block */
+ if (!dev_acquire(dev))
+ return dev->state;
+ }
+
+ if (!dev->reading) {
+ if (cancelled(dev))
+ return dev->state;
+ DBG(5, "READ_IMAGE\n");
+ if (!dev_cmd(dev, CMD_READ_IMAGE))
+ return SANE_STATUS_IO_ERROR;
+ dev->reading++;
+ dev->ulines += dev->vertical;
+ dev->y_off = dev->ulines - dev->vertical;
+ dev->total_data_size += dev->blocklen;
+ dev->blocks++;
+ }
- DBG (3, "%s: %p, %p, %d, %p\n", __FUNCTION__, h, buf, maxlen, (void *)lenp);
+ do {
+ size_t datalen;
+ int clrlen; /* cleared lines len */
+ int olen; /* output len */
+
+ /* read as much data into the buffer */
+ datalen = DATAROOM(dev) & USB_BLOCK_MASK;
+ while (datalen && dev->blocklen) {
+ SANE_Byte *rbuf = dev->data + DATATAIL(dev);
+
+ DBG(9, "<> request len: %lu, [%d, %d; %d]\n",
+ (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
+ if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) !=
+ SANE_STATUS_GOOD)
+ return status;
+ dev->datalen += datalen;
+ dev->blocklen -= datalen;
+ DBG(9, "<> got %lu, [%d, %d; %d]\n",
+ (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
+ if (dev->blocklen < 0)
+ return ret_cancel(dev, SANE_STATUS_IO_ERROR);
+
+ datalen = DATAROOM(dev) & USB_BLOCK_MASK;
+ }
+
+ if (buf && lenp) { /* read mode */
+ /* copy will do minimal of valid data */
+ if (dev->para.format == SANE_FRAME_RGB && dev->line_order) {
+ if (isSupportedDevice(dev)) {
+ clrlen = dump_to_tmp_file(dev);
+ /* decompress after reading entire block data*/
+ if (0 == dev->blocklen) {
+ decompress_tempfile(dev);
+ }
+ copy_decompress_data(dev, buf, maxlen, &olen);
+ } else {
+ clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen);
+ }
+ } else
+ clrlen = copy_plain_trim(dev, buf, maxlen, &olen);
+
+ dev->datalen -= clrlen;
+ dev->dataoff = (dev->dataoff + clrlen) & DATAMASK;
+ buf += olen;
+ maxlen -= olen;
+ *lenp += olen;
+ dev->total_out_size += olen;
+
+ DBG(9, "<> olen: %d, clrlen: %d, blocklen: %d/%d, maxlen %d (%d %d %d)\n",
+ olen, clrlen, dev->blocklen, dev->datalen, maxlen,
+ dev->dataindex / dev->bytes_per_line + dev->y_off,
+ dev->y_off, dev->para.lines);
+
+ /* slack beyond last line */
+ if (dev->dataindex / dev->bytes_per_line + dev->y_off >= dev->para.lines) {
+ dev->datalen = 0;
+ dev->dataoff = 0;
+ }
+
+ if (!clrlen || maxlen <= 0)
+ break;
+ } else { /* flush mode */
+ dev->datalen = 0;
+ dev->dataoff = 0;
+ }
+
+ } while (dev->blocklen);
+
+ if (lenp)
+ DBG(9, " ==> %d\n", *lenp);
- if (lenp)
- *lenp = 0;
- if (!dev)
- return SANE_STATUS_INVAL;
+ return SANE_STATUS_GOOD;
+}
- if (!dev->scanning)
- return SANE_STATUS_EOF;
-
- /* if there is no data to read or output from buffer */
- if (!dev->blocklen && dev->datalen <= PADDING_SIZE) {
-
- /* and we don't need to acquire next block */
- if (dev->final_block) {
- int slack = dev->total_img_size - dev->total_out_size;
-
- /* but we may need to fill slack */
- if (buf && lenp && slack > 0) {
- *lenp = fill_slack(dev, buf, maxlen);
- dev->total_out_size += *lenp;
- DBG (9, "<> slack: %d, filled: %d, maxlen %d\n",
- slack, *lenp, maxlen);
- return SANE_STATUS_GOOD;
- } else if (slack < 0) {
- /* this will never happen */
- DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size);
- }
-
- /* that's all */
- dev_stop(dev);
- return SANE_STATUS_EOF;
+SANE_Status
+sane_start(SANE_Handle h)
+{
+ struct device *dev = h;
+
+ DBG(3, "%s: %p\n", __func__, h);
+
+ dev->cancel = 0;
+ dev->scanning = 0;
+ dev->total_img_size = 0;
+ dev->total_out_size = 0;
+ dev->total_data_size = 0;
+ dev->blocks = 0;
+
+ if (!dev->reserved) {
+ if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT))
+ return dev->state;
+ dev->reserved++;
}
- /* queue next image block */
+ if (!dev_set_window(dev) ||
+ (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
+ return dev_stop(dev);
+
+ if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION))
+ return dev_stop(dev);
+
+ if (!dev_cmd(dev, CMD_READ) ||
+ (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
+ return dev_stop(dev);
+
+ dev->scanning = 1;
+ dev->final_block = 0;
+ dev->blocklen = 0;
+ dev->pixels_per_line = 0;
+ dev->bytes_per_line = 0;
+ dev->ulines = 0;
+
+ set_parameters(dev);
+
+ if (!dev->data && !(dev->data = malloc(DATASIZE)))
+ return ret_cancel(dev, SANE_STATUS_NO_MEM);
+
+ if (!dev->decData && !(dev->decData = malloc(POST_DATASIZE)))
+ return ret_cancel(dev, SANE_STATUS_NO_MEM);
+
if (!dev_acquire(dev))
- return dev->state;
- }
-
- if (!dev->reading) {
- if (cancelled(dev))
- return dev->state;
- DBG (5, "READ_IMAGE\n");
- if (!dev_cmd(dev, CMD_READ_IMAGE))
- return SANE_STATUS_IO_ERROR;
- dev->reading++;
- dev->ulines += dev->vertical;
- dev->y_off = dev->ulines - dev->vertical;
- dev->total_data_size += dev->blocklen;
- dev->blocks++;
- }
-
- do {
- size_t datalen;
- int clrlen; /* cleared lines len */
- int olen; /* output len */
-
- /* read as much data into the buffer */
- datalen = DATAROOM(dev) & USB_BLOCK_MASK;
- while (datalen && dev->blocklen) {
- SANE_Byte *rbuf = dev->data + DATATAIL(dev);
-
- DBG (9, "<> request len: %lu, [%d, %d; %d]\n",
- (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
- if ((status = dev->io->dev_request(dev, NULL, 0, rbuf, &datalen)) !=
- SANE_STATUS_GOOD)
- return status;
- dev->datalen += datalen;
- dev->blocklen -= datalen;
- DBG (9, "<> got %lu, [%d, %d; %d]\n",
- (u_long)datalen, dev->dataoff, DATATAIL(dev), dev->datalen);
- if (dev->blocklen < 0)
- return ret_cancel(dev, SANE_STATUS_IO_ERROR);
-
- datalen = DATAROOM(dev) & USB_BLOCK_MASK;
- }
+ return dev->state;
- if (buf && lenp) { /* read mode */
- /* copy will do minimal of valid data */
- if (dev->para.format == SANE_FRAME_RGB && dev->line_order)
- clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen);
- else
- clrlen = copy_plain_trim(dev, buf, maxlen, &olen);
-
- dev->datalen -= clrlen;
- dev->dataoff = (dev->dataoff + clrlen) & DATAMASK;
- buf += olen;
- maxlen -= olen;
- *lenp += olen;
- dev->total_out_size += olen;
-
- DBG (9, "<> olen: %d, clrlen: %d, blocklen: %d/%d, maxlen %d (%d %d %d)\n",
- olen, clrlen, dev->blocklen, dev->datalen, maxlen,
- dev->dataindex / dev->bytes_per_line + dev->y_off,
- dev->y_off, dev->para.lines);
-
- /* slack beyond last line */
- if (dev->dataindex / dev->bytes_per_line + dev->y_off >= dev->para.lines) {
- dev->datalen = 0;
- dev->dataoff = 0;
- }
-
- if (!clrlen || maxlen <= 0)
- break;
- } else { /* flush mode */
- dev->datalen = 0;
- dev->dataoff = 0;
+ /* make sure to have dev->para <= of real size */
+ if (dev->para.pixels_per_line > dev->pixels_per_line) {
+ dev->para.pixels_per_line = dev->pixels_per_line;
+ dev->para.bytes_per_line = dev->pixels_per_line;
}
- } while (dev->blocklen);
-
- if (lenp)
- DBG (9, " ==> %d\n", *lenp);
+ if (dev->composition == MODE_RGB24)
+ dev->para.bytes_per_line = dev->para.pixels_per_line * 3;
+ else if (dev->composition == MODE_LINEART ||
+ dev->composition == MODE_HALFTONE) {
+ dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
+ dev->para.pixels_per_line = dev->para.bytes_per_line * 8;
+ } else {
+ dev->para.bytes_per_line = dev->para.pixels_per_line;
+ }
- return SANE_STATUS_GOOD;
-}
+ dev->total_img_size = dev->para.bytes_per_line * dev->para.lines;
-SANE_Status
-sane_start (SANE_Handle h)
-{
- struct device *dev = h;
-
- DBG (3, "%s: %p\n", __FUNCTION__, h);
-
- dev->cancel = 0;
- dev->scanning = 0;
- dev->total_img_size = 0;
- dev->total_out_size = 0;
- dev->total_data_size = 0;
- dev->blocks = 0;
-
- if (!dev->reserved) {
- if (!dev_cmd_wait(dev, CMD_RESERVE_UNIT))
- return dev->state;
- dev->reserved++;
- }
-
- if (!dev_set_window(dev) ||
- (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
- return dev_stop(dev);
-
- if (!dev_cmd_wait(dev, CMD_OBJECT_POSITION))
- return dev_stop(dev);
-
- if (!dev_cmd(dev, CMD_READ) ||
- (dev->state && dev->state != SANE_STATUS_DEVICE_BUSY))
- return dev_stop(dev);
-
- dev->scanning = 1;
- dev->final_block = 0;
- dev->blocklen = 0;
- dev->pixels_per_line = 0;
- dev->bytes_per_line = 0;
- dev->ulines = 0;
-
- set_parameters(dev);
-
- if (!dev->data && !(dev->data = malloc(DATASIZE)))
- return ret_cancel(dev, SANE_STATUS_NO_MEM);
-
- if (!dev_acquire(dev))
- return dev->state;
-
- /* make sure to have dev->para <= of real size */
- if (dev->para.pixels_per_line > dev->pixels_per_line) {
- dev->para.pixels_per_line = dev->pixels_per_line;
- dev->para.bytes_per_line = dev->pixels_per_line;
- }
-
- if (dev->composition == MODE_RGB24)
- dev->para.bytes_per_line = dev->para.pixels_per_line * 3;
- else if (dev->composition == MODE_LINEART ||
- dev->composition == MODE_HALFTONE) {
- dev->para.bytes_per_line = (dev->para.pixels_per_line + 7) / 8;
- dev->para.pixels_per_line = dev->para.bytes_per_line * 8;
- } else {
- dev->para.bytes_per_line = dev->para.pixels_per_line;
- }
+ if (isSupportedDevice(dev) &&
+ dev->composition == MODE_RGB24) {
+ int fd;
+ remove(encTmpFileName);
- dev->total_img_size = dev->para.bytes_per_line * dev->para.lines;
+ /* Precreate temporary file in exclusive mode. */
+ fd = open(encTmpFileName, O_CREAT|O_EXCL, 0600);
+ if (fd == -1) {
+ DBG(3, "%s: %p, can't create temporary file %s: %s\n", __func__,
+ (void *)dev, encTmpFileName, strerror(errno));
+ return ret_cancel(dev, SANE_STATUS_ACCESS_DENIED);
+ }
+ close(fd);
+ }
+ dev->currentDecDataIndex = 0;
- return SANE_STATUS_GOOD;
+ return SANE_STATUS_GOOD;
}
-SANE_Status sane_set_io_mode (SANE_Handle h, SANE_Bool non_blocking)
+SANE_Status sane_set_io_mode(SANE_Handle h, SANE_Bool non_blocking)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p, %d\n", __FUNCTION__, h, non_blocking);
+ DBG(3, "%s: %p, %d\n", __func__, h, non_blocking);
- if (non_blocking)
- return SANE_STATUS_UNSUPPORTED;
+ if (non_blocking)
+ return SANE_STATUS_UNSUPPORTED;
- dev->non_blocking = non_blocking;
- return SANE_STATUS_GOOD;
+ dev->non_blocking = non_blocking;
+ return SANE_STATUS_GOOD;
}
-SANE_Status sane_get_select_fd (SANE_Handle h, SANE_Int * fdp)
+SANE_Status sane_get_select_fd(SANE_Handle h, SANE_Int *fdp)
{
- DBG (3, "%s: %p, %p\n", __FUNCTION__, h, (void *)fdp);
- /* supporting of this will require thread creation */
- return SANE_STATUS_UNSUPPORTED;
+ DBG(3, "%s: %p, %p\n", __func__, h, (void *)fdp);
+ /* supporting of this will require thread creation */
+ return SANE_STATUS_UNSUPPORTED;
}
-void sane_cancel (SANE_Handle h)
+void sane_cancel(SANE_Handle h)
{
- struct device *dev = h;
+ struct device *dev = h;
- DBG (3, "%s: %p\n", __FUNCTION__, h);
- dev->cancel = 1;
+ DBG(3, "%s: %p\n", __func__, h);
+ dev->cancel = 1;
}
/* xerox_mfp.c */