summaryrefslogtreecommitdiff
path: root/backend/pixma
diff options
context:
space:
mode:
Diffstat (limited to 'backend/pixma')
-rw-r--r--backend/pixma/.gitignore1
-rw-r--r--backend/pixma/pixma.c179
-rw-r--r--backend/pixma/pixma.h28
-rw-r--r--backend/pixma/pixma_bjnp.c201
-rw-r--r--backend/pixma/pixma_bjnp_private.h10
-rw-r--r--backend/pixma/pixma_common.c175
-rw-r--r--backend/pixma/pixma_common.h3
-rw-r--r--backend/pixma/pixma_imageclass.c10
-rw-r--r--backend/pixma/pixma_io_sanei.c2
-rw-r--r--backend/pixma/pixma_mp150.c192
-rw-r--r--backend/pixma/pixma_mp730.c4
-rw-r--r--backend/pixma/pixma_mp750.c4
-rw-r--r--backend/pixma/pixma_mp800.c135
-rw-r--r--backend/pixma/pixma_sane_options.c362
-rw-r--r--backend/pixma/pixma_sane_options.h51
-rwxr-xr-xbackend/pixma/scripts/pixma_gen_options.py102
16 files changed, 721 insertions, 738 deletions
diff --git a/backend/pixma/.gitignore b/backend/pixma/.gitignore
new file mode 100644
index 0000000..fe87a57
--- /dev/null
+++ b/backend/pixma/.gitignore
@@ -0,0 +1 @@
+pixma_sane_options.[ch]
diff --git a/backend/pixma/pixma.c b/backend/pixma/pixma.c
index f763496..c32907c 100644
--- a/backend/pixma/pixma.c
+++ b/backend/pixma/pixma.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -67,6 +67,7 @@
# include "../include/sane/sanei_backend.h"
# include "../include/sane/sanei_config.h"
# include "../include/sane/sanei_jpeg.h"
+# include "../include/sane/sanei_usb.h"
#ifdef NDEBUG
# define PDBG(x)
@@ -91,7 +92,7 @@
*/
#include "pixma_sane_options.h"
-#define BUTTON_GROUP_SIZE ( opt_scan_resolution - opt_button_1 + 1 )
+#define BUTTON_GROUP_SIZE ( opt_adf_orientation - opt_button_1 + 1 )
#define BUTTON_GROUP_INDEX(x) ( x - opt_button_1 )
typedef struct pixma_sane_t
@@ -317,6 +318,9 @@ update_button_state (pixma_sane_t * ss, SANE_Int * info)
OVAL (opt_original).w = GET_EV_ORIGINAL(ev);
OVAL (opt_target).w = GET_EV_TARGET(ev);
OVAL (opt_scan_resolution).w = GET_EV_DPI(ev);
+ OVAL (opt_document_type).w = GET_EV_DOC(ev);
+ OVAL (opt_adf_status).w = GET_EV_STAT(ev);
+ OVAL (opt_adf_orientation).w = GET_EV_ORIENT(ev);
}
mark_all_button_options_cached(ss);
}
@@ -469,7 +473,7 @@ create_dpi_list (pixma_sane_t * ss)
|| ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_GRAY_16))
{ /* 48 bits flatbed */
/*PDBG (pixma_dbg (4, "*create_dpi_list***** 48 bits flatbed mode\n"));*/
- min_dpi = 150;
+ min_dpi = (cfg->min_xdpi_16) ? cfg->min_xdpi_16 : 75;
}
/* set j for min. dpi
@@ -541,6 +545,8 @@ control_scalar_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v,
option_descriptor_t *opt = &(OPT_IN_CTX[n]);
SANE_Word val;
+ /* PDBG (pixma_dbg (4, "*control_scalar_option***** n = %u, a = %u\n", n, a)); */
+
switch (a)
{
case SANE_ACTION_GET_VALUE:
@@ -604,6 +610,8 @@ control_string_option (pixma_sane_t * ss, SANE_Int n, SANE_Action a, void *v,
const SANE_String_Const *slist = opt->sod.constraint.string_list;
SANE_String str = (SANE_String) v;
+ /* PDBG (pixma_dbg (4, "*control_string_option***** n = %u, a = %u\n", n, a)); */
+
if (opt->sod.constraint_type == SANE_CONSTRAINT_NONE)
{
switch (a)
@@ -656,6 +664,7 @@ static SANE_Status
control_option (pixma_sane_t * ss, SANE_Int n,
SANE_Action a, void *v, SANE_Int * info)
{
+ SANE_Option_Descriptor *sod = &SOD (n);
int result, i;
const pixma_config_t *cfg;
SANE_Int dummy;
@@ -673,25 +682,59 @@ control_option (pixma_sane_t * ss, SANE_Int n,
switch (n)
{
case opt_gamma_table:
- switch (a)
- {
- case SANE_ACTION_SET_VALUE:
- clamp_value (ss, n, v, info);
- for (i = 0; i != 4096; i++)
- ss->gamma_table[i] = *((SANE_Int *) v + i);
- break;
- case SANE_ACTION_GET_VALUE:
- for (i = 0; i != 4096; i++)
- *((SANE_Int *) v + i) = ss->gamma_table[i];
- break;
- case SANE_ACTION_SET_AUTO:
- pixma_fill_gamma_table (AUTO_GAMMA, ss->gamma_table,
- sizeof (ss->gamma_table));
- break;
- default:
- return SANE_STATUS_UNSUPPORTED;
- }
- return SANE_STATUS_GOOD;
+ {
+ int table_size = sod->size / sizeof (SANE_Word);
+ int byte_cnt = table_size == 1024 ? 2 : 1;
+
+ switch (a)
+ {
+ case SANE_ACTION_SET_VALUE:
+ PDBG (pixma_dbg (4, "*control_option***** opt_gamma_table: SANE_ACTION_SET_VALUE with %d values ***** \n", table_size));
+ clamp_value (ss, n, v, info);
+ if (byte_cnt == 1)
+ {
+ for (i = 0; i < table_size; i++)
+ ss->gamma_table[i] = *((SANE_Int *) v + i);
+ }
+ else
+ {
+ for (i = 0; i < table_size; i++)
+ {
+ ss->gamma_table[i * 2] = *((SANE_Int *) v + i);
+ ss->gamma_table[i * 2 + 1] = *((uint8_t *)((SANE_Int *) v + i) + 1);
+ }
+ }
+ /* PDBG (pixma_hexdump (4, (uint8_t *)v, table_size * 4)); */
+ /* PDBG (pixma_hexdump (4, ss->gamma_table, table_size * byte_cnt)); */
+ break;
+ case SANE_ACTION_GET_VALUE:
+ PDBG (pixma_dbg (4, "*control_option***** opt_gamma_table: SANE_ACTION_GET_VALUE ***** \n"));
+ if (byte_cnt == 1)
+ {
+ for (i = 0; i < table_size; i++)
+ *((SANE_Int *) v + i) = ss->gamma_table[i];
+ }
+ else
+ {
+ for (i = 0; i < table_size; i++)
+ {
+ *((SANE_Int *) v + i) = ss->gamma_table[i * 2];
+ *((uint8_t *)((SANE_Int *) v + i) + 1) = ss->gamma_table[i * 2 + 1];
+ }
+ }
+ break;
+ case SANE_ACTION_SET_AUTO:
+ PDBG (pixma_dbg (4, "*control_option***** opt_gamma_table: SANE_ACTION_SET_AUTO with gamma=%f ***** \n",
+ SANE_UNFIX (OVAL (opt_gamma).w)));
+ pixma_fill_gamma_table (SANE_UNFIX (OVAL (opt_gamma).w),
+ ss->gamma_table, table_size);
+ /* PDBG (pixma_hexdump (4, ss->gamma_table, table_size * byte_cnt)); */
+ break;
+ default:
+ return SANE_STATUS_UNSUPPORTED;
+ }
+ return SANE_STATUS_GOOD;
+ }
case opt_button_update:
if (a == SANE_ACTION_SET_VALUE)
@@ -709,6 +752,9 @@ control_option (pixma_sane_t * ss, SANE_Int n,
case opt_original:
case opt_target:
case opt_scan_resolution:
+ case opt_document_type:
+ case opt_adf_status:
+ case opt_adf_orientation:
/* poll scanner if option is not cached */
if (! ss->button_option_is_cached[ BUTTON_GROUP_INDEX(n) ] )
update_button_state (ss, info);
@@ -744,15 +790,24 @@ control_option (pixma_sane_t * ss, SANE_Int n,
{
if (enable_option (ss, opt_gamma_table, OVAL (opt_custom_gamma).b))
*info |= SANE_INFO_RELOAD_OPTIONS;
+ if (OVAL (opt_custom_gamma).b)
+ sane_control_option (ss, opt_gamma_table, SANE_ACTION_SET_AUTO,
+ NULL, NULL);
+
}
break;
case opt_gamma:
if (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO)
{
- /* PDBG (pixma_dbg (4, "*control_option***** gamma = %f *\n",
- SANE_UNFIX (OVAL (opt_gamma).w))); */
+ int table_size = SOD (opt_gamma_table).size / sizeof(SANE_Word);
+ PDBG (pixma_dbg (4, "*control_option***** gamma = %f *\n",
+ SANE_UNFIX (OVAL (opt_gamma).w)));
+ PDBG (pixma_dbg (4, "*control_option***** table size = %d *\n",
+ (int)(SOD (opt_gamma_table).size / sizeof (SANE_Word))));
pixma_fill_gamma_table (SANE_UNFIX (OVAL (opt_gamma).w),
- ss->gamma_table, sizeof (ss->gamma_table));
+ ss->gamma_table, table_size);
+ /* PDBG (pixma_hexdump (4, ss->gamma_table,
+ table_size == 1024 ? 2048 : table_size)); */
}
break;
case opt_mode:
@@ -826,8 +881,8 @@ print_scan_param (int level, const pixma_scan_param_t * sp)
sp->line_size, sp->image_size, sp->channels, sp->depth);
pixma_dbg (level, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n",
sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h);
- pixma_dbg (level, " gamma_table=%p source=%d\n", sp->gamma_table,
- sp->source);
+ pixma_dbg (level, " gamma=%f gamma_table=%p source=%d\n", sp->gamma,
+ sp->gamma_table, sp->source);
pixma_dbg (level, " adf-wait=%d\n", sp->adf_wait);
}
#endif
@@ -872,7 +927,8 @@ calc_scan_param (pixma_sane_t * ss, pixma_scan_param_t * sp)
sp->h = 1;
sp->tpu_offset_added = 0;
- sp->gamma_table = (OVAL (opt_custom_gamma).b) ? ss->gamma_table : NULL;
+ sp->gamma = SANE_UNFIX (OVAL (opt_gamma).w);
+ sp->gamma_table = ss->gamma_table;
sp->source = ss->source_map[OVAL (opt_source).w];
sp->mode = ss->mode_map[OVAL (opt_mode).w];
sp->adf_pageid = ss->page_count;
@@ -897,6 +953,8 @@ init_option_descriptors (pixma_sane_t * ss)
cfg = pixma_get_config (ss->s);
+ /* PDBG (pixma_dbg (4, "*init_option_descriptors*****\n")); */
+
/* setup range for the scan area. */
ss->xrange.min = SANE_FIX (0);
ss->xrange.max = SANE_FIX (cfg->width / 75.0 * 25.4);
@@ -944,11 +1002,32 @@ init_option_descriptors (pixma_sane_t * ss)
/* Enable options that are available only in some scanners. */
if (cfg->cap & PIXMA_CAP_GAMMA_TABLE)
{
+ SANE_Option_Descriptor *sod = &SOD (opt_gamma_table);
+
+ /* some scanners have a large gamma table with 4096 entries */
+ if (cfg->cap & PIXMA_CAP_GT_4096)
+ {
+ static const SANE_Range constraint_gamma_table_4096 = { 0,0xff,0 };
+ sod->desc = SANE_I18N("Gamma-correction table with 4096 entries. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).");
+ sod->size = 4096 * sizeof(SANE_Word);
+ sod->constraint.range = &constraint_gamma_table_4096;
+ }
+
+ /* PDBG (pixma_dbg (4, "*%s***** PIXMA_CAP_GAMMA_TABLE ***** \n",
+ __func__)); */
+ /* PDBG (pixma_dbg (4, "%s: gamma_table_contraint.max = %d\n",
+ __func__, sod->constraint.range->max)); */
+ /* PDBG (pixma_dbg (4, "%s: gamma_table_size = %d\n",
+ __func__, sod->size / sizeof(SANE_Word))); */
+
+ /* activate option gamma */
enable_option (ss, opt_gamma, SANE_TRUE);
+ sane_control_option (ss, opt_gamma, SANE_ACTION_SET_AUTO,
+ NULL, NULL);
+ /* activate option custom gamma table */
enable_option (ss, opt_custom_gamma, SANE_TRUE);
sane_control_option (ss, opt_custom_gamma, SANE_ACTION_SET_AUTO,
- NULL, NULL);
- pixma_fill_gamma_table (AUTO_GAMMA, ss->gamma_table, 4096);
+ NULL, NULL);
}
enable_option (ss, opt_button_controlled,
((cfg->cap & PIXMA_CAP_EVENTS) != 0));
@@ -1597,6 +1676,7 @@ sane_exit (void)
sane_close (first_scanner);
cleanup_device_list ();
pixma_cleanup ();
+ sanei_usb_exit ();
}
SANE_Status
@@ -1624,7 +1704,11 @@ sane_open (SANE_String_Const name, SANE_Handle * h)
nscanners = pixma_find_scanners (conf_devices, SANE_FALSE);
if (nscanners == 0)
return SANE_STATUS_INVAL;
- if (name[0] == '\0')
+
+ /* also get device id if we replay a xml file
+ * otherwise name contains the xml filename
+ * and further replay will fail */
+ if (name[0] == '\0' || strstr (name, ".xml"))
name = pixma_get_device_id (0);
/* Have we already opened the scanner? */
@@ -1995,7 +2079,13 @@ sane_get_select_fd (SANE_Handle h, SANE_Int * fd)
return SANE_STATUS_GOOD;
}
-/*
+/* CAUTION!
+ * Remove generated files pixma_sane_options.[ch] after editing SANE option
+ * descriptors below OR do a 'make clean' OR manually generate them as described
+ * below.
+ * However, make drops the circular dependency and the files won't be generated
+ * again (see merge request sane-project/backends!491).
+
BEGIN SANE_Option_Descriptor
rem -------------------------------------------
@@ -2037,15 +2127,15 @@ type group
title Gamma
type bool custom-gamma
- default SANE_TRUE
+ default SANE_FALSE
title @SANE_TITLE_CUSTOM_GAMMA
desc @SANE_DESC_CUSTOM_GAMMA
cap soft_select soft_detect automatic inactive
-type int gamma-table[4096]
- constraint (0,255,0)
+type int gamma-table[1024]
+ constraint (0,0xffff,0)
title @SANE_TITLE_GAMMA_VECTOR
- desc @SANE_DESC_GAMMA_VECTOR
+ desc Gamma-correction table with 1024 entries. In color mode this option equally affects the red, green, and blue channels simultaneously (i.e., it is an intensity gamma table).
cap soft_select soft_detect automatic inactive
type fixed gamma
@@ -2128,6 +2218,21 @@ type int scan-resolution
title Scan resolution
cap soft_detect advanced
+type int document-type
+ default 0
+ title Document type
+ cap soft_detect advanced
+
+type int adf-status
+ default 0
+ title ADF status
+ cap soft_detect advanced
+
+type int adf-orientation
+ default 0
+ title ADF orientation
+ cap soft_detect advanced
+
rem -------------------------------------------
type group
title Extras
@@ -2150,7 +2255,7 @@ type int adf-wait
default 0
constraint (0,3600,1)
title ADF Waiting Time
- desc When set, the scanner searches the waiting time in seconds for a new document inserted into the automatic document feeder.
+ desc When set, the scanner waits upto the specified time in seconds for a new document inserted into the automatic document feeder.
cap soft_select soft_detect automatic inactive
rem -------------------------------------------
diff --git a/backend/pixma/pixma.h b/backend/pixma/pixma.h
index c2df3cc..c9026a7 100644
--- a/backend/pixma/pixma.h
+++ b/backend/pixma/pixma.h
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -119,8 +119,8 @@ typedef uint32_t uint32_t;
/** \name Version of the driver */
/**@{*/
#define PIXMA_VERSION_MAJOR 0
-#define PIXMA_VERSION_MINOR 27
-#define PIXMA_VERSION_BUILD 0
+#define PIXMA_VERSION_MINOR 28
+#define PIXMA_VERSION_BUILD 5
/**@}*/
/** \name Error codes */
@@ -158,6 +158,10 @@ typedef uint32_t uint32_t;
#define PIXMA_CAP_TPUIR ((1 << 11) | PIXMA_CAP_TPU)
#define PIXMA_CAP_ADF_WAIT (1 << 12)
#define PIXMA_CAP_ADF_JPEG (1 << 13)
+#define PIXMA_CAP_GT_4096 (1 << 14) /* gamma table has 4096 8-bit values
+ * only generation 1 scanners
+ * usually gamma table has 1024 16-bit values
+ */
#define PIXMA_CAP_EXPERIMENT (1 << 31)
/**@}*/
@@ -167,13 +171,19 @@ typedef uint32_t uint32_t;
#define PIXMA_EV_ACTION_MASK (0xffffff)
#define PIXMA_EV_BUTTON1 (1 << 24)
#define PIXMA_EV_BUTTON2 (2 << 24)
-#define PIXMA_EV_TARGET_MASK (0xff)
-#define PIXMA_EV_ORIGINAL_MASK (0xff00)
-#define PIXMA_EV_DPI_MASK (0xff0000)
+#define PIXMA_EV_TARGET_MASK (0x0f)
+#define PIXMA_EV_ORIGINAL_MASK (0x0f00)
+#define PIXMA_EV_DPI_MASK (0x0f0000)
+#define PIXMA_EV_DOC_MASK (0xf000)
+#define PIXMA_EV_STAT_MASK (0xf00000)
+#define PIXMA_EV_ORIENT_MASK (0xf0)
#define GET_EV_TARGET(x) (x & PIXMA_EV_TARGET_MASK)
#define GET_EV_ORIGINAL(x) ( (x & PIXMA_EV_ORIGINAL_MASK) >> 8 )
#define GET_EV_DPI(x) ( (x & PIXMA_EV_DPI_MASK) >> 16 )
+#define GET_EV_DOC(x) ( (x & PIXMA_EV_DOC_MASK) >> 12 )
+#define GET_EV_STAT(x) ( (x & PIXMA_EV_STAT_MASK) >> 20 )
+#define GET_EV_ORIENT(x) ( (x & PIXMA_EV_ORIENT_MASK) >> 4 )
/**@}*/
/** @} end of API group */
@@ -340,6 +350,9 @@ struct pixma_scan_param_t
* specified by subdriver will be used. */
const uint8_t *gamma_table;
+ /** value for auto generated gamma table */
+ double gamma;
+
/** \see #pixma_paper_source_t */
pixma_paper_source_t source;
@@ -365,7 +378,8 @@ struct pixma_config_t
uint16_t pid; /**< USB Product ID */
unsigned iface; /**< USB Interface number */
const pixma_scan_ops_t *ops; /**< Subdriver ops */
- unsigned min_xdpi; /**< Minimum horizontal resolution[DPI] */
+ unsigned min_xdpi; /**< Minimum horizontal resolution[DPI] */
+ unsigned min_xdpi_16;/**< Minimum horizontal resolution[DPI] for 16-bit scans */
unsigned xdpi; /**< Maximum horizontal resolution[DPI] */
unsigned ydpi; /**< Maximum vertical resolution[DPI] */
unsigned adftpu_min_dpi; /**< Maximum horizontal resolution[DPI] for adf/tpu
diff --git a/backend/pixma/pixma_bjnp.c b/backend/pixma/pixma_bjnp.c
index 34ba918..4e83714 100644
--- a/backend/pixma/pixma_bjnp.c
+++ b/backend/pixma/pixma_bjnp.c
@@ -109,6 +109,13 @@
#ifndef SSIZE_MAX
# define SSIZE_MAX LONG_MAX
#endif
+#ifndef HOST_NAME_MAX
+# ifdef _POSIX_HOST_NAME_MAX
+# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
+# else
+# define HOST_NAME_MAX 255
+# endif
+#endif
/* static data */
static bjnp_device_t device[BJNP_NO_DEVICES];
@@ -454,69 +461,6 @@ determine_scanner_serial (const char *hostname, const char * mac_address, char *
}
static int
-bjnp_open_tcp (int devno)
-{
- int sock;
- int val;
- bjnp_sockaddr_t *addr = device[devno].addr;
- char host[BJNP_HOST_MAX];
- int port;
- int connect_timeout = BJNP_TIMEOUT_TCP_CONNECT;
-
- get_address_info( addr, host, &port);
- PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_open_tcp: Setting up a TCP socket, dest: %s port %d\n",
- host, port ) );
-
- if ((sock = socket (get_protocol_family( addr ) , SOCK_STREAM, 0)) < 0)
- {
- PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not create socket: %s\n",
- strerror (errno)));
- return -1;
- }
-
- val = 1;
- setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
-
-#if 0
- val = 1;
- setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof (val));
-
- val = 1;
-#endif
-
- /*
- * Using TCP_NODELAY improves responsiveness, especially on systems
- * with a slow loopback interface...
- */
-
- val = 1;
- setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
-
-/*
- * Close this socket when starting another process...
- */
-
- fcntl (sock, F_SETFD, FD_CLOEXEC);
-
- while (connect_timeout > 0)
- {
- if (connect
- (sock, &(addr->addr), sa_size(device[devno].addr)) == 0)
- {
- device[devno].tcp_socket = sock;
- return 0;
- }
- PDBG (bjnp_dbg( LOG_INFO, "bjnp_open_tcp: INFO - Can not yet connect over TCP to scanner: %s, retrying\n",
- strerror(errno)));
- usleep(BJNP_TCP_CONNECT_INTERVAL * BJNP_USLEEP_MS);
- connect_timeout = connect_timeout - BJNP_TCP_CONNECT_INTERVAL;
- }
- PDBG (bjnp_dbg
- (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not connect to scanner, giving up!"));
- return -1;
-}
-
-static int
split_uri (const char *devname, char *method, char *host, char *port,
char *args)
{
@@ -1565,6 +1509,7 @@ bjnp_init_device_structure(int dn, bjnp_sockaddr_t *sa, bjnp_protocol_defs_t *pr
#endif
device[dn].protocol = protocol_defs->protocol_version;
device[dn].protocol_string = protocol_defs->proto_string;
+ device[dn].single_tcp_session = protocol_defs->single_tcp_session;
device[dn].tcp_socket = -1;
device[dn].addr = (bjnp_sockaddr_t *) malloc(sizeof ( bjnp_sockaddr_t) );
@@ -1694,6 +1639,98 @@ bjnp_recv_data (int devno, SANE_Byte * buffer, size_t start_pos, size_t * len)
return SANE_STATUS_GOOD;
}
+static int
+bjnp_open_tcp (int devno)
+{
+ int sock;
+ int val;
+ char my_hostname[HOST_NAME_MAX];
+ char pid_str[64];
+ bjnp_sockaddr_t *addr = device[devno].addr;
+ char host[BJNP_HOST_MAX];
+ int port;
+ int connect_timeout = BJNP_TIMEOUT_TCP_CONNECT;
+
+ if (device[devno].tcp_socket != -1)
+ {
+ PDBG (bjnp_dbg( LOG_DEBUG, "bjnp_open_tcp: socket alreeady opened, nothing to do\n"));
+ return 0;
+ }
+ get_address_info( addr, host, &port);
+ PDBG (bjnp_dbg (LOG_DEBUG, "bjnp_open_tcp: Setting up a TCP socket, dest: %s port %d\n",
+ host, port ) );
+
+ gethostname (my_hostname, HOST_NAME_MAX);
+ my_hostname[HOST_NAME_MAX - 1] = '\0';
+ sprintf (pid_str, "Process ID = %d", getpid ());
+ bjnp_send_job_details (devno, my_hostname, getusername (), pid_str);
+
+ if ((sock = socket (get_protocol_family( addr ) , SOCK_STREAM, 0)) < 0)
+ {
+ PDBG (bjnp_dbg (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not create socket: %s\n",
+ strerror (errno)));
+ return -1;
+ }
+
+ val = 1;
+ setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val));
+
+#if 0
+ val = 1;
+ setsockopt (sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof (val));
+
+ val = 1;
+#endif
+
+ /*
+ * Using TCP_NODELAY improves responsiveness, especially on systems
+ * with a slow loopback interface...
+ */
+
+ val = 1;
+ setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &val, sizeof (val));
+
+/*
+ * Close this socket when starting another process...
+ */
+
+ fcntl (sock, F_SETFD, FD_CLOEXEC);
+
+ while (connect_timeout > 0)
+ {
+ if (connect
+ (sock, &(addr->addr), sa_size(device[devno].addr)) == 0)
+ {
+ device[devno].tcp_socket = sock;
+ PDBG( bjnp_dbg(LOG_INFO, "bjnp_open_tcp: created socket %d\n", sock));
+ return 0;
+ }
+ PDBG (bjnp_dbg( LOG_INFO, "bjnp_open_tcp: INFO - Can not yet connect over TCP to scanner: %s, retrying\n",
+ strerror(errno)));
+ usleep(BJNP_TCP_CONNECT_INTERVAL * BJNP_USLEEP_MS);
+ connect_timeout = connect_timeout - BJNP_TCP_CONNECT_INTERVAL;
+ }
+ PDBG (bjnp_dbg
+ (LOG_CRIT, "bjnp_open_tcp: ERROR - Can not connect to scanner, giving up!"));
+ return -1;
+}
+
+static void bjnp_close_tcp(int devno)
+{
+ if ( device[devno].tcp_socket != -1)
+ {
+ PDBG( bjnp_dbg( LOG_INFO, "bjnp_close_tcp - closing tcp-socket %d\n", device[devno].tcp_socket));
+ bjnp_finish_job (devno);
+ close (device[devno].tcp_socket);
+ device[devno].tcp_socket = -1;
+ }
+ else
+ {
+ PDBG( bjnp_dbg( LOG_INFO, "bjnp_close_tcp: socket not open, nothing to do.\n"));
+ }
+ device[devno].open = 0;
+}
+
static BJNP_Status
bjnp_allocate_device (SANE_String_Const devname,
SANE_Int * dn, char *resulting_host)
@@ -1762,7 +1799,7 @@ bjnp_allocate_device (SANE_String_Const devname,
if (result != 0 )
{
PDBG (bjnp_dbg (LOG_CRIT, "bjnp_allocate_device: ERROR - Cannot resolve host: %s port %s\n", host, port));
- return SANE_STATUS_INVAL;
+ return BJNP_STATUS_INVAL;
}
/* Check if a device number is already allocated to any of the scanner's addresses */
@@ -2273,6 +2310,13 @@ sanei_bjnp_open (SANE_String_Const devname, SANE_Int * dn)
if ( (result != BJNP_STATUS_GOOD) && (result != BJNP_STATUS_ALREADY_ALLOCATED ) ) {
return SANE_STATUS_INVAL;
}
+
+ if (device[*dn].single_tcp_session && bjnp_open_tcp (*dn) != 0)
+ {
+ PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_opening TCP connection failed.\n\n"));
+ return SANE_STATUS_INVAL;
+ }
+ PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_open done.\n\n"));
return SANE_STATUS_GOOD;
}
@@ -2286,8 +2330,8 @@ sanei_bjnp_close (SANE_Int dn)
{
PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_close(%d):\n", dn));
- device[dn].open = 0;
- sanei_bjnp_deactivate(dn);
+ bjnp_close_tcp( dn );
+ PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_close done.\n\n"));
}
/** Activate BJNP device connection
@@ -2298,21 +2342,13 @@ sanei_bjnp_close (SANE_Int dn)
SANE_Status
sanei_bjnp_activate (SANE_Int dn)
{
- char hostname[256];
- char pid_str[64];
-
PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_activate (%d)\n", dn));
- gethostname (hostname, 256);
- hostname[255] = '\0';
- sprintf (pid_str, "Process ID = %d", getpid ());
-
- bjnp_send_job_details (dn, hostname, getusername (), pid_str);
-
- if (bjnp_open_tcp (dn) != 0)
+ if (!(device[dn].single_tcp_session) && bjnp_open_tcp (dn) != 0)
{
+ PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_activate: open TCP connection failed.\n\n"));
return SANE_STATUS_INVAL;
}
-
+ PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_activate done.\n\n"));
return SANE_STATUS_GOOD;
}
@@ -2325,12 +2361,11 @@ SANE_Status
sanei_bjnp_deactivate (SANE_Int dn)
{
PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_deactivate (%d)\n", dn));
- if ( device[dn].tcp_socket != -1)
- {
- bjnp_finish_job (dn);
- close (device[dn].tcp_socket);
- device[dn].tcp_socket = -1;
- }
+ if (!device[dn].single_tcp_session)
+ {
+ bjnp_close_tcp(dn);
+ }
+ PDBG (bjnp_dbg (LOG_INFO, "sanei_bjnp_deactivate done.\n\n"));
return SANE_STATUS_GOOD;
}
diff --git a/backend/pixma/pixma_bjnp_private.h b/backend/pixma/pixma_bjnp_private.h
index edfb330..19ba496 100644
--- a/backend/pixma/pixma_bjnp_private.h
+++ b/backend/pixma/pixma_bjnp_private.h
@@ -131,13 +131,14 @@ typedef struct
int default_port;
char * proto_string;
char * method_string;
+ int single_tcp_session;
} bjnp_protocol_defs_t;
bjnp_protocol_defs_t bjnp_protocol_defs[] =
{
- {PROTOCOL_BJNP, BJNP_PORT_SCAN,"BJNP", "bjnp"},
- {PROTOCOL_MFNP, MFNP_PORT_SCAN,"MFNP", "mfnp"},
- {PROTOCOL_NONE, -1, NULL, NULL}
+ {PROTOCOL_BJNP, BJNP_PORT_SCAN,"BJNP", "bjnp", SANE_FALSE},
+ {PROTOCOL_MFNP, MFNP_PORT_SCAN,"MFNP", "mfnp", SANE_TRUE},
+ {PROTOCOL_NONE, -1, NULL, NULL, SANE_FALSE}
};
/* commands */
@@ -346,9 +347,10 @@ typedef struct device_s
{
int open; /* connection to scanner is opened */
- /* protocol version */
+ /* protocol information */
int protocol;
char *protocol_string;
+ char single_tcp_session;
/* sockets */
diff --git a/backend/pixma/pixma_common.c b/backend/pixma/pixma_common.c
index 7b7ecec..436311a 100644
--- a/backend/pixma/pixma_common.c
+++ b/backend/pixma/pixma_common.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -48,11 +48,18 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#include <ctype.h>
#include <math.h> /* pow(C90) */
#include <sys/time.h> /* gettimeofday(4.3BSD) */
#include <unistd.h> /* usleep */
+#if defined(HAVE_LIBXML2)
+# include <libxml/parser.h>
+#else
+# error "The pixma backend requires libxml2"
+#endif
+
#include "pixma_rename.h"
#include "pixma_common.h"
#include "pixma_io.h"
@@ -143,6 +150,24 @@ pixma_hexdump (int level, const void *d_, unsigned len)
p++;
}
}
+ for (c = 0; c < 4; c++)
+ {
+ p[0] = ' ';
+ p++;
+ }
+ for (c = 0; c != 16 && (ofs + c) < plen; c++)
+ {
+ if (isprint(d[ofs + c]))
+ p[0] = d[ofs + c];
+ else
+ p[0] = '.';
+ p++;
+ if (c == 7)
+ {
+ p[0] = ' ';
+ p++;
+ }
+ }
p[0] = '\0';
pixma_dbg (level, "%s\n", line);
ofs += c;
@@ -335,7 +360,7 @@ pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
/* convert 24/48 bit RGB to 8/16 bit grayscale
*
- * Formular: g = (R + G + B) / 3
+ * Formular: Y' = 0,2126 R' + 0,7152 G' + 0,0722 B'
*
* sptr: source color scale buffer
* gptr: destination gray scale buffer
@@ -345,19 +370,28 @@ pixma_r_to_ir (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
uint8_t *
pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
{
- unsigned i, j, g;
+ unsigned i, g;
/* PDBG (pixma_dbg (4, "*pixma_rgb_to_gray*****\n")); */
for (i = 0; i < w; i++)
{
- for (j = 0, g = 0; j < 3; j++)
- {
- g += *sptr++;
- if (c == 6) g += (*sptr++ << 8); /* 48 bit RGB: high byte */
+ if (c == 6)
+ { /* 48 bit RGB */
+ unsigned r = sptr[0] + (sptr[1] << 8);
+ unsigned y = sptr[2] + (sptr[3] << 8);
+ unsigned b = sptr[4] + (sptr[5] << 8);
+
+ g = (r * 2126) + (y * 7152) + (b * 722);
+ sptr += 6;
}
+ else
+ { /* 24 bit RGB */
+ g = (sptr[0] * 2126) + (sptr[1] * 7152) + (sptr[2] * 722);
+ sptr += 3;
+ }
+ g /= 10000; /* 8 and 16 bit gray */
- g /= 3; /* 8 or 16 bit gray */
*gptr++ = g;
if (c == 6) *gptr++ = (g >> 8); /* 16 bit gray: high byte */
}
@@ -846,7 +880,7 @@ pixma_scan (pixma_t * s, pixma_scan_param_t * sp)
sp->line_size, sp->image_size, sp->channels, sp->depth);
pixma_dbg (3, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n",
sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h);
- pixma_dbg (3, " gamma_table=%p source=%d\n", sp->gamma_table, sp->source);
+ pixma_dbg (3, " gamma=%f gamma_table=%p source=%d\n", sp->gamma, sp->gamma_table, sp->source);
pixma_dbg (3, " threshold=%d threshold_curve=%d\n", sp->threshold, sp->threshold_curve);
pixma_dbg (3, " adf-wait=%d\n", sp->adf_wait);
pixma_dbg (3, " ADF page count: %d\n", sp->adf_pageid);
@@ -1152,14 +1186,35 @@ pixma_get_config (pixma_t * s)
void
pixma_fill_gamma_table (double gamma, uint8_t * table, unsigned n)
{
- int i;
+ unsigned i;
double r_gamma = 1.0 / gamma;
- double out_scale = 255.0;
double in_scale = 1.0 / (n - 1);
- for (i = 0; (unsigned) i != n; i++)
+ /* 8-bits gamma table
+ * for generation 1 scanners
+ */
+ if (n == 4096)
+ {
+ double out_scale = 255.0;
+
+ for (i = 0; (unsigned) i != n; i++)
+ {
+ table[i] = (int) (out_scale * pow (i * in_scale, r_gamma) + 0.5);
+ }
+ }
+
+ /* 16-bits gamma table */
+ else
{
- table[i] = (int) (out_scale * pow (i * in_scale, r_gamma) + 0.5);
+ double out_scale = 65535.0;
+ uint16_t value;
+
+ for (i = 0; i < n; i++)
+ {
+ value = (uint16_t) (out_scale * pow (i * in_scale, r_gamma) + 0.5);
+ table[2 * i] = (uint8_t) (value & 0xff);
+ table[2 * i + 1] = (uint8_t) (value >> 8);
+ }
}
}
@@ -1185,3 +1240,97 @@ pixma_get_device_status (pixma_t * s, pixma_device_status_t * status)
memset (status, 0, sizeof (*status));
return s->ops->get_status (s, status);
}
+
+static const char *
+format_xml_response(const char *resp_details)
+{
+ if (strcmp(resp_details, "DeviceBusy") == 0)
+ /* https://cromwell-intl.com/open-source/canon-pixma-printer-scanner.html */
+ return "DeviceBusy - Device not initialized (yet). " \
+ "Please check the USB power, try a different port or install the Ink Cartridges if the device supports them.";
+ else if (strcmp(resp_details, "ScannerCarriageLockError") == 0)
+ return "ScannerCarriageLockError - Please consult the manual to unlock the Carriage Lock.";
+ else if (strcmp(resp_details, "PCScanning") == 0)
+ return "PCScanning - Previous scan attempt was not completed. Try disconnecting and reconnecting the scanner. " \
+ "If the problem persists, consider reporting it as a bug at http://www.sane-project.org/bugs.html.";
+ else if (strcmp(resp_details, "DeviceCheckError") == 0)
+ return "DeviceCheckError - Device detected a fault. Contact the repair center.";
+ else
+ return resp_details;
+}
+
+int
+pixma_parse_xml_response(const char *xml_message)
+{
+ int status = PIXMA_EPROTO;
+ xmlDoc *doc = NULL;
+ xmlNode *node = NULL;
+ xmlChar *content = NULL;
+
+ doc = xmlReadMemory(xml_message, strlen(xml_message), "mem:device-resp.xml", NULL, 0);
+ if (doc == NULL) {
+ PDBG(pixma_dbg(10, "unable to parse xml response\n"));
+ status = PIXMA_EINVAL;
+ goto clean;
+ }
+
+ node = xmlDocGetRootElement(doc);
+ if (node == NULL) {
+ status = PIXMA_EPROTO;
+ goto clean;
+ }
+
+ /* /cmd */
+ for (; node; node = node->next) {
+ if (strcmp((const char*)node->name, "cmd") == 0)
+ break;
+ }
+ if (!node) {
+ status = PIXMA_EPROTO;
+ goto clean;
+ }
+
+ /* /cmd/contents */
+ for (node = node->children; node; node = node->next) {
+ if (strcmp((const char*)node->name, "contents") == 0)
+ break;
+ }
+ if (!node) {
+ status = PIXMA_EPROTO;
+ goto clean;
+ }
+
+ /* /cmd/contents/param_set */
+ for (node = node->children; node; node = node->next) {
+ if (strcmp((const char*)node->name, "param_set") == 0)
+ break;
+ }
+ if (!node) {
+ status = PIXMA_EPROTO;
+ goto clean;
+ }
+
+ /* /cmd/contents/param_set/response... */
+ for (node = node->children; node; node = node->next)
+ {
+ if (strcmp((const char*)node->name, "response") == 0) {
+ content = xmlNodeGetContent(node);
+ if (strcmp((const char*)content, "OK") == 0)
+ status = PIXMA_STATUS_OK;
+ else
+ status = PIXMA_EINVAL;
+ xmlFree(content);
+ } else if (strcmp((const char*)node->name, "response_detail") == 0) {
+ content = xmlNodeGetContent(node);
+ if (strlen((const char*)content) > 0) {
+ PDBG(pixma_dbg(0, "device response: %s\n",
+ format_xml_response((const char*)content)));
+ }
+ xmlFree(content);
+ }
+ }
+
+clean:
+ xmlFreeDoc(doc);
+ return status;
+}
diff --git a/backend/pixma/pixma_common.h b/backend/pixma/pixma_common.h
index c0ed4ba..3e4e5bd 100644
--- a/backend/pixma/pixma_common.h
+++ b/backend/pixma/pixma_common.h
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
This file is part of the SANE package.
@@ -205,6 +205,7 @@ uint8_t *pixma_newcmd (pixma_cmdbuf_t *, unsigned cmd,
int pixma_exec (pixma_t *, pixma_cmdbuf_t *);
int pixma_exec_short_cmd (pixma_t *, pixma_cmdbuf_t *, unsigned cmd);
int pixma_map_status_errno (unsigned status);
+int pixma_parse_xml_response(const char *xml_message);
/**@}*/
#define pixma_fill_checksum(start, end) do { \
diff --git a/backend/pixma/pixma_imageclass.c b/backend/pixma/pixma_imageclass.c
index ce0c37d..be483b2 100644
--- a/backend/pixma/pixma_imageclass.c
+++ b/backend/pixma/pixma_imageclass.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2009 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2008 Dennis Lou, dlou 99 at yahoo dot com
@@ -105,6 +105,7 @@
#define MF220_PID 0x27a8
#define MF210_PID 0x27a9
#define MF620_PID 0x27b4
+#define MF720_PID 0x27b5
#define MF410_PID 0x27c0
#define MF510_PID 0x27c2
#define MF230_PID 0x27d1
@@ -122,6 +123,7 @@
#define MF743_PID 0x27fc
#define MF640_PID 0x27fe
#define MF645_PID 0x27fd
+#define MF440_PID 0x2823
enum iclass_state_t
@@ -915,7 +917,7 @@ static const pixma_scan_ops_t pixma_iclass_ops = {
0x04a9, pid, /* vid pid */ \
1, /* iface */ \
&pixma_iclass_ops, /* ops */ \
- 0, /* min_xdpi not used in this subdriver */ \
+ 0, 0, /* min_xdpi & min_xdpi_16 not used in this subdriver */ \
dpi, dpi, /* xdpi, ydpi */ \
0, /* adftpu_min_dpi not used in this subdriver */ \
adftpu_max_dpi, /* adftpu_max_dpi */ \
@@ -961,6 +963,7 @@ const pixma_config_t pixma_iclass_devices[] = {
DEV ("Canon i-SENSYS MF220 Series", "MF220", MF220_PID, 600, 0, 637, 1050, PIXMA_CAP_ADFDUP), /* max. w = 216mm */
DEV ("Canon i-SENSYS MF210 Series", "MF210", MF210_PID, 600, 0, 637, 1050, PIXMA_CAP_ADF), /* max. w = 216mm */
DEV ("Canon i-SENSYS MF620 Series", "MF620", MF620_PID, 600, 0, 637, 1050, PIXMA_CAP_ADF),
+ DEV ("Canon i-SENSYS MF720 Series", "MF720", MF720_PID, 600, 300, 637, 877, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF410 Series", "MF410", MF410_PID, 600, 0, 637, 1050, PIXMA_CAP_ADFDUP), /* max. w = 216mm */
DEV ("Canon i-SENSYS MF510 Series", "MF510", MF510_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF230 Series", "MF230", MF230_PID, 600, 0, 637, 1050, PIXMA_CAP_ADF), /* max. w = 216mm */
@@ -973,7 +976,7 @@ const pixma_config_t pixma_iclass_devices[] = {
DEV ("Canon imageCLASS MF634C", "MF632C/634C", MF634_PID, 600, 0, 637, 1050, PIXMA_CAP_ADFDUP),
DEV ("Canon imageCLASS MF733C", "MF731C/733C", MF731_PID, 600, 0, 637, 1050, PIXMA_CAP_ADFDUP), /* however, we need this for ethernet/wifi */
DEV ("Canon imageCLASS D570", "D570", D570_PID, 600, 0, 640, 877, 0),
- DEV ("Canon i-SENSYS MF110 Series", "MF110", MF110_PID, 600, 0, 640, 1050, 0),
+ DEV ("Canon i-SENSYS MF110/910 Series", "MF110", MF110_PID, 600, 0, 640, 1050, 0),
DEV ("Canon i-SENSYS MF520 Series", "MF520", MF520_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF420 Series", "MF420", MF420_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF260 Series", "MF260", MF260_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
@@ -981,5 +984,6 @@ const pixma_config_t pixma_iclass_devices[] = {
DEV ("Canon i-SENSYS MF741C/743C", "MF741C/743C", MF743_PID, 600, 300, 640, 1050, PIXMA_CAP_ADFDUP), /* ADFDUP restricted to 300dpi */
DEV ("Canon i-SENSYS MF640 Series", "MF642C/643C/644C", MF640_PID, 600, 0, 640, 1050, PIXMA_CAP_ADFDUP),
DEV ("Canon i-SENSYS MF645C", "MF645C", MF645_PID, 600, 0, 637, 877, PIXMA_CAP_ADFDUP), /* max. w = 216mm */
+ DEV ("Canon i-SENSYS MF440 Series", "MF440", MF440_PID, 600, 300, 637, 877, PIXMA_CAP_ADFDUP),
DEV (NULL, NULL, 0, 0, 0, 0, 0, 0)
};
diff --git a/backend/pixma/pixma_io_sanei.c b/backend/pixma/pixma_io_sanei.c
index c30b404..c7b7a29 100644
--- a/backend/pixma/pixma_io_sanei.c
+++ b/backend/pixma/pixma_io_sanei.c
@@ -1,7 +1,7 @@
/* SANE - Scanner Access Now Easy.
* For limitations, see function sanei_usb_get_vendor_product().
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
This file is part of the SANE package.
diff --git a/backend/pixma/pixma_mp150.c b/backend/pixma/pixma_mp150.c
index 3973702..b438c1b 100644
--- a/backend/pixma/pixma_mp150.c
+++ b/backend/pixma/pixma_mp150.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2009 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -85,7 +85,6 @@
4096 = size of gamma table. 24 = header + checksum */
#define IMAGE_BLOCK_SIZE (512*1024)
#define CMDBUF_SIZE (4096 + 24)
-#define DEFAULT_GAMMA 2.0 /***** Gamma different from 1.0 is potentially impacting color profile generation *****/
#define UNKNOWN_PID 0xffff
@@ -282,8 +281,10 @@
#define TS8230_PID 0x185b
#define TS9580_PID 0x185d
#define TR9530_PID 0x185e
+#define G7000_PID 0x1863
#define G6000_PID 0x1865
#define G6080_PID 0x1866
+#define GM4000_PID 0x1869
#define XK80_PID 0x1873
#define TS5300_PID 0x188b
#define TS5380_PID 0x188c
@@ -321,8 +322,6 @@
<ivec:param_set servicetype=\"scan\"><ivec:jobID>00000001</ivec:jobID>\
</ivec:param_set></ivec:contents></cmd>"
-#define XML_OK "<ivec:response>OK</ivec:response>"
-
enum mp150_state_t
{
state_idle,
@@ -460,7 +459,7 @@ send_xml_dialog (pixma_t * s, const char * xml_message)
PDBG (pixma_dbg (10, "XML message sent to scanner:\n%s\n", xml_message));
PDBG (pixma_dbg (10, "XML response back from scanner:\n%s\n", mp->cb.buf));
- return (strcasestr ((const char *) mp->cb.buf, XML_OK) != NULL);
+ return pixma_parse_xml_response((const char*)mp->cb.buf) == PIXMA_STATUS_OK;
}
static int
@@ -567,42 +566,45 @@ send_gamma_table (pixma_t * s)
const uint8_t *lut = s->param->gamma_table;
uint8_t *data;
- if (mp->generation == 1)
+ if (s->cfg->cap & PIXMA_CAP_GT_4096)
{
data = pixma_newcmd (&mp->cb, cmd_gamma, 4096 + 8, 0);
data[0] = (s->param->channels == 3) ? 0x10 : 0x01;
pixma_set_be16 (0x1004, data + 2);
if (lut)
- memcpy (data + 4, lut, 4096);
+ {
+ /* PDBG (pixma_dbg (4, "*send_gamma_table***** Use 4096 bytes from LUT ***** \n")); */
+ /* PDBG (pixma_hexdump (4, lut, 4096)); */
+ memcpy (data + 4, lut, 4096);
+ }
else
- pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 4096);
+ {
+ /* fallback: we should never see this */
+ PDBG (pixma_dbg (4, "*send_gamma_table***** Generate 4096 bytes Table with %f ***** \n",
+ s->param->gamma));
+ pixma_fill_gamma_table (s->param->gamma, data + 4, 4096);
+ /* PDBG (pixma_hexdump (4, data + 4, 4096)); */
+ }
}
else
{
- /* FIXME: Gamma table for 2nd generation: 1024 * uint16_le */
- data = pixma_newcmd (&mp->cb, cmd_gamma, 2048 + 8, 0);
+ /* Gamma table for 2nd+ generation: 1024 * uint16_le */
+ data = pixma_newcmd (&mp->cb, cmd_gamma, 1024 * 2 + 8, 0);
data[0] = 0x10;
pixma_set_be16 (0x0804, data + 2);
if (lut)
{
- int i;
- for (i = 0; i < 1024; i++)
- {
- int j = (i << 2) + (i >> 8);
- data[4 + 2 * i + 0] = lut[j];
- data[4 + 2 * i + 1] = lut[j];
- }
+ /* PDBG (pixma_dbg (4, "*send_gamma_table***** Use 1024 * 2 bytes from LUT ***** \n")); */
+ /* PDBG (pixma_hexdump (4, lut, 1024 * 2)); */
+ memcpy (data + 4, lut, 1024 * 2);
}
else
{
- int i;
- pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 2048);
- for (i = 0; i < 1024; i++)
- {
- int j = (i << 1) + (i >> 9);
- data[4 + 2 * i + 0] = data[4 + j];
- data[4 + 2 * i + 1] = data[4 + j];
- }
+ /* fallback: we should never see this */
+ PDBG (pixma_dbg (4, "*send_gamma_table***** Generate 1024 * 2 Table with %f ***** \n",
+ s->param->gamma));
+ pixma_fill_gamma_table (s->param->gamma, data + 4, 1024);
+ /* PDBG (pixma_hexdump (4, data + 4, 1024 * 2)); */
}
}
return pixma_exec (s, &mp->cb);
@@ -631,6 +633,12 @@ calc_raw_width (const mp150_t * mp, const pixma_scan_param_t * param)
return raw_width;
}
+static int
+is_gray_16 (pixma_t * s)
+{
+ return (s->param->mode == PIXMA_SCAN_MODE_GRAY_16);
+}
+
static unsigned
get_cis_line_size (pixma_t * s)
{
@@ -640,7 +648,9 @@ get_cis_line_size (pixma_t * s)
__func__, s->param->line_size, s->param->w, s->param->wx, mp->scale));*/
return (s->param->wx ? s->param->line_size / s->param->w * s->param->wx
- : s->param->line_size) * mp->scale;
+ : s->param->line_size)
+ * mp->scale
+ * (is_gray_16(s) ? 3 : 1);
}
static int
@@ -705,10 +715,12 @@ send_scan_param (pixma_t * s)
pixma_set_be32 (y, data + 0x10);
pixma_set_be32 (wx, data + 0x14);
pixma_set_be32 (h, data + 0x18);
- data[0x1c] = (s->param->channels != 1) ? 0x08 : 0x04;
+ /*PDBG (pixma_dbg (4, "*send_scan_param gen. 3+ ***** Setting: channels=%hi depth=%hi ***** \n",
+ s->param->channels, s->param->depth));*/
+ data[0x1c] = ((s->param->channels != 1) || (is_gray_16(s)) ? 0x08 : 0x04);
data[0x1d] = ((s->param->software_lineart) ? 8 : s->param->depth)
- * s->param->channels; /* bits per pixel */
+ * (is_gray_16(s) ? 3 : s->param->channels); /* bits per pixel */
data[0x1f] = 0x01; /* This one also seen at 0. Don't know yet what's used for */
data[0x20] = 0xff;
@@ -902,7 +914,8 @@ handle_interrupt (pixma_t * s, int timeout)
|| s->cfg->pid == MX920_PID
|| s->cfg->pid == MB2300_PID
|| s->cfg->pid == MB5000_PID
- || s->cfg->pid == MB5400_PID)
+ || s->cfg->pid == MB5400_PID
+ || s->cfg->pid == TR4500_PID)
/* button no. in buf[7]
* size in buf[10] 01=A4; 02=Letter; 08=10x15; 09=13x18; 0b=auto
* format in buf[11] 01=JPEG; 02=TIFF; 03=PDF; 04=Kompakt-PDF
@@ -910,18 +923,45 @@ handle_interrupt (pixma_t * s, int timeout)
* target = format; original = size; scan-resolution = dpi */
{
if (buf[7] & 1)
- s->events = PIXMA_EV_BUTTON1 | buf[11] | buf[10]<<8 | buf[12]<<16; /* color scan */
+ {
+ /* color scan */
+ s->events = PIXMA_EV_BUTTON1 | (buf[11] & 0x0f) | (buf[10] & 0x0f) << 8
+ | (buf[12] & 0x0f) << 16;
+ }
if (buf[7] & 2)
- s->events = PIXMA_EV_BUTTON2 | buf[11] | buf[10]<<8 | buf[12]<<16; /* b/w scan */
+ {
+ /* b/w scan */
+ s->events = PIXMA_EV_BUTTON2 | (buf[11] & 0x0f) | (buf[10] & 0x0f) << 8
+ | (buf[12] & 0x0f) << 16;
+ }
+
+ /* some scanners provide additional information:
+ * document type in buf[6] 01=Document; 02=Photo; 03=Auto Scan
+ * ADF status in buf[8] 01 = ADF empty; 02 = ADF filled
+ * ADF orientation in buf[16] 01=Portrait; 02=Landscape */
+ if (s->cfg->pid == TR4500_PID)
+ {
+ s->events |= (buf[6] & 0x0f) << 12;
+ s->events |= (buf[8] & 0x0f) << 20;
+ s->events |= (buf[16] & 0x0f) << 4;
+ }
}
else if (s->cfg->pid == LIDE300_PID
|| s->cfg->pid == LIDE400_PID)
/* unknown value in buf[4]
- * target in buf[0x13]
- * always set button-1 */
+ * target in buf[0x13] 01=copy; 02=auto; 03=send; 05=start PDF; 06=finish PDF
+ * "Finish PDF" is Button-2, all others are Button-1 */
{
- if (buf[0x13])
- s->events = PIXMA_EV_BUTTON1 | buf[0x13];
+ if (buf[0x13] == 0x06)
+ {
+ /* button 2 = cancel / end scan */
+ s->events = PIXMA_EV_BUTTON2 | (buf[0x13] & 0x0f);
+ }
+ else if (buf[0x13])
+ {
+ /* button 1 = start scan */
+ s->events = PIXMA_EV_BUTTON1 | (buf[0x13] & 0x0f);
+ }
}
else
/* button no. in buf[0]
@@ -937,9 +977,15 @@ handle_interrupt (pixma_t * s, int timeout)
if (buf[9] & 2)
query_status (s);
if (buf[0] & 2)
- s->events = PIXMA_EV_BUTTON2 | buf[1] | ((buf[0] & 0xf0) << 4); /* b/w scan */
+ {
+ /* b/w scan */
+ s->events = PIXMA_EV_BUTTON2 | (buf[1] & 0x0f) | (buf[0] & 0xf0) << 4;
+ }
if (buf[0] & 1)
- s->events = PIXMA_EV_BUTTON1 | buf[1] | ((buf[0] & 0xf0) << 4); /* color scan */
+ {
+ /* color scan */
+ s->events = PIXMA_EV_BUTTON1 | (buf[1] & 0x0f) | ((buf[0] & 0xf0) << 4);
+ }
}
return 1;
}
@@ -1062,7 +1108,7 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
}
/* process image sizes */
- c = s->param->channels
+ c = (is_gray_16(s) ? 3 : s->param->channels)
* ((s->param->software_lineart) ? 8 : s->param->depth) / 8; /* color channels count */
cw = c * s->param->w; /* image width */
cx = c * s->param->xs; /* x-offset */
@@ -1104,7 +1150,6 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
* MP220, MX360 and generation 5 scanners are exceptions */
if (n > 1
&& s->cfg->pid != MP220_PID
- && s->cfg->pid != MP490_PID
&& s->cfg->pid != MX360_PID
&& (mp->generation < 5
/* generation 5 scanners *with* special image format */
@@ -1136,6 +1181,9 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
/* Color / Gray to Lineart convert */
if (s->param->software_lineart)
cptr = gptr = pixma_binarize_line (s->param, gptr, cptr, s->param->w, c);
+ /* Color to Grayscale convert for 16bit gray */
+ else if (is_gray_16(s))
+ cptr = gptr = pixma_rgb_to_gray (gptr, cptr, s->param->w, c);
else
cptr += cw;
}
@@ -1218,22 +1266,41 @@ mp150_check_param (pixma_t * s, pixma_scan_param_t * sp)
{
mp150_t *mp = (mp150_t *) s->subdriver;
- /* PDBG (pixma_dbg (4, "*mp150_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n",
- sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */
+ /* PDBG (pixma_dbg (4, "*mp150_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u, gamma=%f *****\n",
+ sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx, sp->gamma)); */
- /* MP150 only supports 8 bit per channel in color and grayscale mode */
- if (sp->depth != 1)
- {
- sp->software_lineart = 0;
+ sp->channels = 3;
+ sp->software_lineart = 0;
+ switch (sp->mode)
+ {
+ /* standard scan modes
+ * 8 bit per channel in color and grayscale mode */
+ case PIXMA_SCAN_MODE_GRAY:
+ sp->channels = 1;
+ /* fall through */
+ case PIXMA_SCAN_MODE_COLOR:
sp->depth = 8;
- }
- else
- {
- /* software lineart */
+ break;
+ /* extended scan modes for 48 bit flatbed scanners
+ * 16 bit per channel in color and grayscale mode */
+ case PIXMA_SCAN_MODE_GRAY_16:
+ sp->channels = 1;
+ sp->depth = 16;
+ break;
+ case PIXMA_SCAN_MODE_COLOR_48:
+ sp->channels = 3;
+ sp->depth = 16;
+ break;
+ /* software lineart
+ * 1 bit per channel */
+ case PIXMA_SCAN_MODE_LINEART:
sp->software_lineart = 1;
- sp->depth = 1;
sp->channels = 1;
- }
+ sp->depth = 1;
+ break;
+ default:
+ break;
+ }
/* for software lineart w must be a multiple of 8 */
if (sp->software_lineart == 1 && sp->w % 8)
@@ -1596,6 +1663,7 @@ static const pixma_scan_ops_t pixma_mp150_ops = {
0, /* iface */ \
&pixma_mp150_ops, /* ops */ \
min_dpi, /* min_xdpi */ \
+ 0, /* min_xdpi_16 not used in this subdriver */ \
dpi, 2*(dpi), /* xdpi, ydpi */ \
adftpu_min_dpi, adftpu_max_dpi, /* adftpu_min_dpi, adftpu_max_dpi */ \
0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \
@@ -1610,11 +1678,11 @@ static const pixma_scan_ops_t pixma_mp150_ops = {
const pixma_config_t pixma_mp150_devices[] = {
/* Generation 1: CIS */
- DEVICE ("Canon PIXMA MP150", "MP150", MP150_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
- DEVICE ("Canon PIXMA MP170", "MP170", MP170_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
- DEVICE ("Canon PIXMA MP450", "MP450", MP450_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
- DEVICE ("Canon PIXMA MP500", "MP500", MP500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
- DEVICE ("Canon PIXMA MP530", "MP530", MP530_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
+ DEVICE ("Canon PIXMA MP150", "MP150", MP150_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_GT_4096),
+ DEVICE ("Canon PIXMA MP170", "MP170", MP170_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_GT_4096),
+ DEVICE ("Canon PIXMA MP450", "MP450", MP450_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_GT_4096),
+ DEVICE ("Canon PIXMA MP500", "MP500", MP500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_GT_4096),
+ DEVICE ("Canon PIXMA MP530", "MP530", MP530_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_GT_4096 | PIXMA_CAP_ADF),
/* Generation 2: CIS */
DEVICE ("Canon PIXMA MP140", "MP140", MP140_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS),
@@ -1675,7 +1743,7 @@ const pixma_config_t pixma_mp150_devices[] = {
/* Latest devices (2010) Generation 4 CIS */
DEVICE ("Canon PIXMA MP280", "MP280", MP280_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), /* TODO: 1200dpi doesn't work yet */
- DEVICE ("Canon PIXMA MP495", "MP495", MP495_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
+ DEVICE ("Canon PIXMA MP495", "MP495", MP495_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS), /* ToDo: max. scan resolution = 1200x600dpi */
DEVICE ("Canon PIXMA MG5100", "MG5100", MG5100_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA MG5200", "MG5200", MG5200_PID, 0, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA MG6100", "MG6100", MG6100_PID, 0, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS),
@@ -1765,12 +1833,12 @@ const pixma_config_t pixma_mp150_devices[] = {
/* Latest devices (2018) Generation 5 CIS */
DEVICE ("Canon MAXIFY MB5400 Series", "MB5400", MB5400_PID, 0, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP | PIXMA_CAP_ADF_JPEG),
- DEVICE ("Canon MAXIFY MB5100 Series", "MB5100", MB5100_PID, 0, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP),
+ DEVICE ("Canon MAXIFY MB5100 Series", "MB5100", MB5100_PID, 0, 1200, 0, 0, 638, 1050, PIXMA_CAP_CIS | PIXMA_CAP_ADFDUP | PIXMA_CAP_ADF_JPEG),
DEVICE ("Canon PIXMA TS9100 Series", "TS9100", TS9100_PID, 0, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS),
- DEVICE ("Canon PIXMA TR8500 Series", "TR8500", TR8500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
+ DEVICE ("Canon PIXMA TR8500 Series", "TR8500", TR8500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF | PIXMA_CAP_ADF_JPEG),
DEVICE ("Canon PIXMA TR7500 Series", "TR7500", TR7500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
DEVICE ("Canon PIXMA TS9500 Series", "TS9500", TS9500_PID, 0, 1200, 0, 600, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
- DEVICE ("CanoScan LiDE 400", "LIDE400", LIDE400_PID, 300, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS),
+ DEVICE ("CanoScan LiDE 400", "LIDE400", LIDE400_PID, 300, 4800, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_48BIT),
DEVICE ("CanoScan LiDE 300", "LIDE300", LIDE300_PID, 300, 2400, 0, 0, 638, 877, PIXMA_CAP_CIS),
/* Latest devices (2019) Generation 5 CIS */
@@ -1788,7 +1856,7 @@ const pixma_config_t pixma_mp150_devices[] = {
DEVICE ("Canon PIXMA TR7530 Series", "TR7530", TR7530_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
DEVICE ("Canon PIXUS XK50 Series", "XK50", XK50_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXUS XK70 Series", "XK70", XK70_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
- DEVICE ("Canon PIXMA TR4500 Series", "TR4500", TR4500_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
+ DEVICE ("Canon PIXMA TR4500 Series", "TR4500", TR4500_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF | PIXMA_CAP_ADF_JPEG), /* ToDo: max. scan resolution = 600x1200dpi */
DEVICE ("Canon PIXMA E4200 Series", "E4200", E4200_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
DEVICE ("Canon PIXMA TS6200 Series", "TS6200", TS6200_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA TS6280 Series", "TS6280", TS6280_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
@@ -1798,8 +1866,10 @@ const pixma_config_t pixma_mp150_devices[] = {
DEVICE ("Canon PIXMA TS8230 Series", "TS8230", TS8230_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA TS9580 Series", "TS9580", TS9580_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
DEVICE ("Canon PIXMA TR9530 Series", "TR9530", TR9530_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF),
+ DEVICE ("Canon PIXMA G7000 Series", "G7000", G7000_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), /* ToDo: ADF has legal paper length */
DEVICE ("Canon PIXMA G6000 Series", "G6000", G6000_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA G6080 Series", "G6080", G6080_PID, 0, 600, 0, 0, 638, 877, PIXMA_CAP_CIS),
+ DEVICE ("Canon PIXMA GM4000 Series", "GM4000", GM4000_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS | PIXMA_CAP_ADF), /* ToDo: ADF has legal paper length */
DEVICE ("Canon PIXUS XK80 Series", "XK80", XK80_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA TS5300 Series", "TS5300", TS5300_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
DEVICE ("Canon PIXMA TS5380 Series", "TS5380", TS5380_PID, 0, 1200, 0, 0, 638, 877, PIXMA_CAP_CIS),
diff --git a/backend/pixma/pixma_mp730.c b/backend/pixma/pixma_mp730.c
index 93d518b..fcc9ae8 100644
--- a/backend/pixma/pixma_mp730.c
+++ b/backend/pixma/pixma_mp730.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2008 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -815,7 +815,7 @@ static const pixma_scan_ops_t pixma_mp730_ops = {
0x04a9, pid, /* vid pid */ \
1, /* iface */ \
&pixma_mp730_ops, /* ops */ \
- 0, /* min_xdpi not used in this subdriver */ \
+ 0, 0, /* min_xdpi & min_xdpi_16 not used in this subdriver */ \
dpi, dpi, /* xdpi, ydpi */ \
0, 0, /* adftpu_min_dpi & adftpu_max_dpi not used in this subdriver */ \
0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \
diff --git a/backend/pixma/pixma_mp750.c b/backend/pixma/pixma_mp750.c
index 7f00023..cc1c3ad 100644
--- a/backend/pixma/pixma_mp750.c
+++ b/backend/pixma/pixma_mp750.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
This file is part of the SANE package.
@@ -955,7 +955,7 @@ static const pixma_scan_ops_t pixma_mp750_ops = {
0x04a9, pid, /* vid pid */ \
0, /* iface */ \
&pixma_mp750_ops, /* ops */ \
- 0, /* min_xdpi not used in this subdriver */ \
+ 0, 0, /* min_xdpi & min_xdpi_16 not used in this subdriver */ \
dpi, 2*(dpi), /* xdpi, ydpi */ \
0, 0, /* adftpu_min_dpi & adftpu_max_dpi not used in this subdriver */ \
0, 0, /* tpuir_min_dpi & tpuir_max_dpi not used in this subdriver */ \
diff --git a/backend/pixma/pixma_mp800.c b/backend/pixma/pixma_mp800.c
index feef611..905c246 100644
--- a/backend/pixma/pixma_mp800.c
+++ b/backend/pixma/pixma_mp800.c
@@ -1,6 +1,6 @@
/* SANE - Scanner Access Now Easy.
- Copyright (C) 2011-2019 Rolf Bensch <rolf at bensch hyphen online dot de>
+ Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
Copyright (C) 2007-2009 Nicolas Martin, <nicols-guest at alioth dot debian dot org>
Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
@@ -91,7 +91,6 @@
4096 = size of gamma table. 24 = header + checksum */
#define IMAGE_BLOCK_SIZE (512*1024)
#define CMDBUF_SIZE (4096 + 24)
-#define DEFAULT_GAMMA 2.0 /***** Gamma different from 1.0 is potentially impacting color profile generation *****/
#define UNKNOWN_PID 0xffff
#define CANON_VID 0x04a9
@@ -153,8 +152,6 @@
<ivec:param_set servicetype=\"scan\"><ivec:jobID>00000001</ivec:jobID>\
</ivec:param_set></ivec:contents></cmd>"
-#define XML_OK "<ivec:response>OK</ivec:response>"
-
enum mp810_state_t
{
state_idle,
@@ -294,7 +291,7 @@ static int send_xml_dialog (pixma_t * s, const char * xml_message)
PDBG(pixma_dbg (10, "XML message sent to scanner:\n%s\n", xml_message));
PDBG(pixma_dbg (10, "XML response back from scanner:\n%s\n", mp->cb.buf));
- return (strcasestr ((const char *) mp->cb.buf, XML_OK) != NULL);
+ return pixma_parse_xml_response((const char*)mp->cb.buf) == PIXMA_STATUS_OK;
}
static void new_cmd_tpu_msg (pixma_t *s, pixma_cmdbuf_t * cb, uint16_t cmd)
@@ -438,44 +435,47 @@ static int send_gamma_table (pixma_t * s)
const uint8_t *lut = s->param->gamma_table;
uint8_t *data;
- if (mp->generation == 1)
+ if (s->cfg->cap & PIXMA_CAP_GT_4096)
{
data = pixma_newcmd (&mp->cb, cmd_gamma, 4096 + 8, 0);
data[0] = (s->param->channels == 3) ? 0x10 : 0x01;
pixma_set_be16 (0x1004, data + 2);
if (lut)
- memcpy (data + 4, lut, 4096);
- else
- pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 4096);
- }
- else
- {
- /* FIXME: Gamma table for 2nd generation: 1024 * uint16_le */
- data = pixma_newcmd (&mp->cb, cmd_gamma, 2048 + 8, 0);
- data[0] = 0x10;
- pixma_set_be16 (0x0804, data + 2);
- if (lut)
- {
- int i;
- for (i = 0; i < 1024; i++)
{
- int j = (i << 2) + (i >> 8);
- data[4 + 2 * i + 0] = lut[j];
- data[4 + 2 * i + 1] = lut[j];
+ /* PDBG (pixma_dbg (4, "*send_gamma_table***** Use 4096 bytes from LUT ***** \n")); */
+ /* PDBG (pixma_hexdump (4, lut, 4096)); */
+ memcpy (data + 4, lut, 4096);
}
- }
else
- {
- int i;
- pixma_fill_gamma_table (DEFAULT_GAMMA, data + 4, 2048);
- for (i = 0; i < 1024; i++)
{
- int j = (i << 1) + (i >> 9);
- data[4 + 2 * i + 0] = data[4 + j];
- data[4 + 2 * i + 1] = data[4 + j];
+ /* fallback: we should never see this */
+ PDBG (pixma_dbg (4, "*send_gamma_table***** Generate 4096 bytes Table with %f ***** \n",
+ s->param->gamma));
+ pixma_fill_gamma_table (s->param->gamma, data + 4, 4096);
+ /* PDBG (pixma_hexdump (4, data + 4, 4096)); */
}
- }
}
+ else
+ {
+ /* Gamma table for 2nd+ generation: 1024 * uint16_le */
+ data = pixma_newcmd (&mp->cb, cmd_gamma, 1024 * 2 + 8, 0);
+ data[0] = 0x10;
+ pixma_set_be16 (0x0804, data + 2);
+ if (lut)
+ {
+ /* PDBG (pixma_dbg (4, "*send_gamma_table***** Use 1024 * 2 bytes from LUT ***** \n")); */
+ /* PDBG (pixma_hexdump (4, lut, 1024 * 2)); */
+ memcpy (data + 4, lut, 1024 * 2);
+ }
+ else
+ {
+ /* fallback: we should never see this */
+ PDBG (pixma_dbg (4, "*send_gamma_table***** Generate 1024 * 2 bytes Table with %f ***** \n",
+ s->param->gamma));
+ pixma_fill_gamma_table (s->param->gamma, data + 4, 1024);
+ /* PDBG (pixma_hexdump (4, data + 4, 1024 * 2)); */
+ }
+ }
return pixma_exec (s, &mp->cb);
}
@@ -1172,9 +1172,17 @@ static int handle_interrupt (pixma_t * s, int timeout)
* target = format; original = size; scan-resolution = dpi */
{
if (buf[7] & 1)
- s->events = PIXMA_EV_BUTTON1 | buf[11] | buf[10]<<8 | buf[12]<<16; /* color scan */
+ {
+ /* color scan */
+ s->events = PIXMA_EV_BUTTON1 | (buf[11] & 0x0f) | (buf[10] & 0x0f) << 8
+ | (buf[12] & 0x0f) << 16;
+ }
if (buf[7] & 2)
- s->events = PIXMA_EV_BUTTON2 | buf[11] | buf[10]<<8 | buf[12]<<16; /* b/w scan */
+ {
+ /* b/w scan */
+ s->events = PIXMA_EV_BUTTON2 | (buf[11] & 0x0f) | (buf[10] & 0x0f) << 8
+ | (buf[12] & 0x0f) << 16;
+ }
}
else if (s->cfg->pid == CS8800F_PID
|| s->cfg->pid == CS9000F_PID
@@ -1185,9 +1193,15 @@ static int handle_interrupt (pixma_t * s, int timeout)
{
if ((s->cfg->pid == CS8800F_PID && buf[1] == 0x70)
|| (s->cfg->pid != CS8800F_PID && buf[1] == 0x50))
- s->events = PIXMA_EV_BUTTON2 | buf[1] >> 4; /* button 2 = cancel / end scan */
+ {
+ /* button 2 = cancel / end scan */
+ s->events = PIXMA_EV_BUTTON2 | buf[1] >> 4;
+ }
else
- s->events = PIXMA_EV_BUTTON1 | buf[1] >> 4; /* button 1 = start scan */
+ {
+ /* button 1 = start scan */
+ s->events = PIXMA_EV_BUTTON1 | buf[1] >> 4;
+ }
}
else
/* button no. in buf[0]
@@ -1204,9 +1218,15 @@ static int handle_interrupt (pixma_t * s, int timeout)
query_status (s);
if (buf[0] & 2)
- s->events = PIXMA_EV_BUTTON2 | buf[1] | ((buf[0] & 0xf0) << 4); /* b/w scan */
+ {
+ /* b/w scan */
+ s->events = PIXMA_EV_BUTTON2 | (buf[1] & 0x0f) | (buf[0] & 0xf0) << 4;
+ }
if (buf[0] & 1)
- s->events = PIXMA_EV_BUTTON1 | buf[1] | ((buf[0] & 0xf0) << 4); /* color scan */
+ {
+ /* color scan */
+ s->events = PIXMA_EV_BUTTON1 | (buf[1] & 0x0f) | (buf[0] & 0xf0) << 4;
+ }
}
return 1;
}
@@ -1871,8 +1891,8 @@ static int mp810_check_param (pixma_t * s, pixma_scan_param_t * sp)
mp810_t *mp = (mp810_t *) s->subdriver;
unsigned w_max;
- /* PDBG (pixma_dbg (4, "*mp810_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n",
- sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */
+ /* PDBG (pixma_dbg (4, "*mp810_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u, gamma=%f *****\n",
+ sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx, sp->gamma)); */
sp->channels = 3;
sp->software_lineart = 0;
@@ -2066,9 +2086,7 @@ static int mp810_check_param (pixma_t * s, pixma_scan_param_t * sp)
k = MAX (sp->xdpi, 300) / sp->xdpi;
else if (sp->source == PIXMA_SOURCE_TPU
|| sp->mode == PIXMA_SCAN_MODE_COLOR_48 || sp->mode == PIXMA_SCAN_MODE_GRAY_16)
- /* TPU mode and 16 bit flatbed scans
- * TODO: either the frontend (xsane) cannot handle 48 bit flatbed scans @ 75 dpi (prescan)
- * or there is a bug in this subdriver */
+ /* TPU mode and 16 bit flatbed scans */
k = MAX (sp->xdpi, 150) / sp->xdpi;
else
/* default */
@@ -2375,13 +2393,14 @@ static const pixma_scan_ops_t pixma_mp800_ops =
mp810_get_status
};
-#define DEVICE(name, model, pid, dpi, adftpu_min_dpi, adftpu_max_dpi, tpuir_min_dpi, tpuir_max_dpi, w, h, cap) { \
+#define DEVICE(name, model, pid, min_dpi_16, dpi, adftpu_min_dpi, adftpu_max_dpi, tpuir_min_dpi, tpuir_max_dpi, w, h, cap) { \
name, /* name */ \
model, /* model */ \
CANON_VID, pid, /* vid pid */ \
0, /* iface */ \
&pixma_mp800_ops, /* ops */ \
0, /* min_xdpi not used in this subdriver */ \
+ min_dpi_16, /* min_xdpi_16 */ \
dpi, 2*(dpi), /* xdpi, ydpi */ \
adftpu_min_dpi, adftpu_max_dpi, /* adftpu_min_dpi, adftpu_max_dpi */ \
tpuir_min_dpi, tpuir_max_dpi, /* tpuir_min_dpi, tpuir_max_dpi */ \
@@ -2393,42 +2412,42 @@ static const pixma_scan_ops_t pixma_mp800_ops =
PIXMA_CAP_GAMMA_TABLE|PIXMA_CAP_EVENTS|cap \
}
-#define END_OF_DEVICE_LIST DEVICE(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+#define END_OF_DEVICE_LIST DEVICE(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
const pixma_config_t pixma_mp800_devices[] =
{
/* Generation 1: CCD */
- DEVICE ("Canon PIXMA MP800", "MP800", MP800_PID, 2400, 150, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
- DEVICE ("Canon PIXMA MP800R", "MP800R", MP800R_PID, 2400, 150, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
- DEVICE ("Canon PIXMA MP830", "MP830", MP830_PID, 2400, 150, 0, 0, 0, 638, 877, PIXMA_CAP_ADFDUP),
+ DEVICE ("Canon PIXMA MP800", "MP800", MP800_PID, 0, 2400, 150, 0, 0, 0, 638, 877, PIXMA_CAP_TPU | PIXMA_CAP_GT_4096),
+ DEVICE ("Canon PIXMA MP800R", "MP800R", MP800R_PID, 0, 2400, 150, 0, 0, 0, 638, 877, PIXMA_CAP_TPU | PIXMA_CAP_GT_4096),
+ DEVICE ("Canon PIXMA MP830", "MP830", MP830_PID, 0, 2400, 150, 0, 0, 0, 638, 877, PIXMA_CAP_ADFDUP | PIXMA_CAP_GT_4096),
/* Generation 2: CCD */
- DEVICE ("Canon PIXMA MP810", "MP810", MP810_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
- DEVICE ("Canon PIXMA MP960", "MP960", MP960_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon PIXMA MP810", "MP810", MP810_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon PIXMA MP960", "MP960", MP960_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
/* Generation 3 CCD not managed as Generation 2 */
- DEVICE ("Canon Pixma MP970", "MP970", MP970_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon Pixma MP970", "MP970", MP970_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
/* Flatbed scanner CCD (2007) */
- DEVICE ("Canoscan 8800F", "8800F", CS8800F_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU /*| PIXMA_CAP_NEGATIVE*/ | PIXMA_CAP_48BIT),
+ DEVICE ("Canoscan 8800F", "8800F", CS8800F_PID, 150, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU /*| PIXMA_CAP_NEGATIVE*/ | PIXMA_CAP_48BIT),
/* PIXMA 2008 vintage CCD */
- DEVICE ("Canon MP980 series", "MP980", MP980_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon MP980 series", "MP980", MP980_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
/* Generation 4 CCD */
- DEVICE ("Canon MP990 series", "MP990", MP990_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon MP990 series", "MP990", MP990_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
/* Flatbed scanner (2010) */
- DEVICE ("Canoscan 9000F", "9000F", CS9000F_PID, 4800, 300, 9600, 600, 2400, 638, 877, PIXMA_CAP_TPUIR /*| PIXMA_CAP_NEGATIVE*/ | PIXMA_CAP_48BIT),
+ DEVICE ("Canoscan 9000F", "9000F", CS9000F_PID, 150, 4800, 300, 9600, 600, 2400, 638, 877, PIXMA_CAP_TPUIR /*| PIXMA_CAP_NEGATIVE*/ | PIXMA_CAP_48BIT),
/* Latest devices (2010) Generation 4 CCD untested */
- DEVICE ("Canon PIXMA MG8100", "MG8100", MG8100_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon PIXMA MG8100", "MG8100", MG8100_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
/* Latest devices (2011) Generation 4 CCD untested */
- DEVICE ("Canon PIXMA MG8200", "MG8200", MG8200_PID, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
+ DEVICE ("Canon PIXMA MG8200", "MG8200", MG8200_PID, 0, 4800, 300, 0, 0, 0, 638, 877, PIXMA_CAP_TPU),
/* Flatbed scanner (2013) */
- DEVICE ("Canoscan 9000F Mark II", "9000FMarkII", CS9000F_MII_PID, 4800, 300, 9600, 600, 2400, 638, 877, PIXMA_CAP_TPUIR | PIXMA_CAP_48BIT),
+ DEVICE ("Canoscan 9000F Mark II", "9000FMarkII", CS9000F_MII_PID, 150, 4800, 300, 9600, 600, 2400, 638, 877, PIXMA_CAP_TPUIR | PIXMA_CAP_48BIT),
END_OF_DEVICE_LIST
};
diff --git a/backend/pixma/pixma_sane_options.c b/backend/pixma/pixma_sane_options.c
deleted file mode 100644
index 2b8f609..0000000
--- a/backend/pixma/pixma_sane_options.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/* Automatically generated from pixma_sane.c */
-static const SANE_Range constraint_gamma_table =
- { 0,255,0 };
-static const SANE_Range constraint_gamma =
- { SANE_FIX(0.3),SANE_FIX(5),SANE_FIX(0) };
-static const SANE_Range constraint_threshold =
- { 0,100,1 };
-static const SANE_Range constraint_threshold_curve =
- { 0,127,1 };
-static const SANE_Range constraint_adf_wait =
- { 0,3600,1 };
-
-
-static
-int find_string_in_list(SANE_String_Const str, const SANE_String_Const *list)
-{
- int i;
- for (i = 0; list[i] && strcmp(str, list[i]) != 0; i++) {}
- return i;
-}
-
-static
-int build_option_descriptors(struct pixma_sane_t *ss)
-{
- SANE_Option_Descriptor *sod;
- option_descriptor_t *opt;
-
- memset(OPT_IN_CTX, 0, sizeof(OPT_IN_CTX));
-
- opt = &(OPT_IN_CTX[opt_opt_num_opts]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_TITLE_NUM_OPTIONS;
- sod->desc = SANE_DESC_NUM_OPTIONS;
- sod->name = "";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_DETECT;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_opt_num_opts].info = 0;
- opt->def.w = opt_last;
- opt->val.w = opt_last;
-
- opt = &(OPT_IN_CTX[opt__group_1]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_GROUP;
- sod->title = SANE_I18N("Scan mode");
- sod->desc = sod->title;
-
- opt = &(OPT_IN_CTX[opt_resolution]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_TITLE_SCAN_RESOLUTION;
- sod->desc = SANE_DESC_SCAN_RESOLUTION;
- sod->name = "resolution";
- sod->unit = SANE_UNIT_DPI;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC;
- sod->constraint_type = SANE_CONSTRAINT_WORD_LIST;
- sod->constraint.word_list = ss->dpi_list;
- OPT_IN_CTX[opt_resolution].info = SANE_INFO_RELOAD_PARAMS;
- opt->def.w = 75;
- opt->val.w = 75;
-
- opt = &(OPT_IN_CTX[opt_mode]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_STRING;
- sod->title = SANE_TITLE_SCAN_MODE;
- sod->desc = SANE_DESC_SCAN_MODE;
- sod->name = "mode";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 31;
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC;
- sod->constraint_type = SANE_CONSTRAINT_STRING_LIST;
- sod->constraint.string_list = ss->mode_list;
- OPT_IN_CTX[opt_mode].info = SANE_INFO_RELOAD_PARAMS;
- opt->def.s = SANE_VALUE_SCAN_MODE_COLOR;
- opt->val.w = find_string_in_list(opt->def.s, sod->constraint.string_list);
-
- opt = &(OPT_IN_CTX[opt_source]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_STRING;
- sod->title = SANE_TITLE_SCAN_SOURCE;
- sod->desc = SANE_I18N("Selects the scan source (such as a document-feeder). Set source before mode and resolution. Resets mode and resolution to auto values.");
- sod->name = "source";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 31;
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT;
- sod->constraint_type = SANE_CONSTRAINT_STRING_LIST;
- sod->constraint.string_list = ss->source_list;
- OPT_IN_CTX[opt_source].info = 0;
- opt->def.s = SANE_I18N("Flatbed");
- opt->val.w = find_string_in_list(opt->def.s, sod->constraint.string_list);
-
- opt = &(OPT_IN_CTX[opt_button_controlled]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_BOOL;
- sod->title = SANE_I18N("Button-controlled scan");
- sod->desc = SANE_I18N("When enabled, scan process will not start immediately. To proceed, press \"SCAN\" button (for MP150) or \"COLOR\" button (for other models). To cancel, press \"GRAY\" button.");
- sod->name = "button-controlled";
- sod->unit = SANE_UNIT_NONE;
- sod->size = sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_button_controlled].info = 0;
- opt->def.w = SANE_FALSE;
- opt->val.w = SANE_FALSE;
-
- opt = &(OPT_IN_CTX[opt__group_2]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_GROUP;
- sod->title = SANE_I18N("Gamma");
- sod->desc = sod->title;
-
- opt = &(OPT_IN_CTX[opt_custom_gamma]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_BOOL;
- sod->title = SANE_TITLE_CUSTOM_GAMMA;
- sod->desc = SANE_DESC_CUSTOM_GAMMA;
- sod->name = "custom-gamma";
- sod->unit = SANE_UNIT_NONE;
- sod->size = sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_custom_gamma].info = 0;
- opt->def.w = SANE_TRUE;
- opt->val.w = SANE_TRUE;
-
- opt = &(OPT_IN_CTX[opt_gamma_table]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_TITLE_GAMMA_VECTOR;
- sod->desc = SANE_DESC_GAMMA_VECTOR;
- sod->name = "gamma-table";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 4096 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &constraint_gamma_table;
- OPT_IN_CTX[opt_gamma_table].info = 0;
-
- opt = &(OPT_IN_CTX[opt_gamma]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_FIXED;
- sod->title = SANE_I18N("Gamma function exponent");
- sod->desc = SANE_I18N("Changes intensity of midtones");
- sod->name = "gamma";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &constraint_gamma;
- OPT_IN_CTX[opt_gamma].info = 0;
- opt->def.w = SANE_FIX(AUTO_GAMMA);
- opt->val.w = SANE_FIX(AUTO_GAMMA);
-
- opt = &(OPT_IN_CTX[opt__group_3]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_GROUP;
- sod->title = SANE_I18N("Geometry");
- sod->desc = sod->title;
-
- opt = &(OPT_IN_CTX[opt_tl_x]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_FIXED;
- sod->title = SANE_TITLE_SCAN_TL_X;
- sod->desc = SANE_DESC_SCAN_TL_X;
- sod->name = "tl-x";
- sod->unit = SANE_UNIT_MM;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &ss->xrange;
- OPT_IN_CTX[opt_tl_x].info = SANE_INFO_RELOAD_PARAMS;
- opt->def.w = SANE_FIX(0);
- opt->val.w = SANE_FIX(0);
-
- opt = &(OPT_IN_CTX[opt_tl_y]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_FIXED;
- sod->title = SANE_TITLE_SCAN_TL_Y;
- sod->desc = SANE_DESC_SCAN_TL_Y;
- sod->name = "tl-y";
- sod->unit = SANE_UNIT_MM;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &ss->yrange;
- OPT_IN_CTX[opt_tl_y].info = SANE_INFO_RELOAD_PARAMS;
- opt->def.w = SANE_FIX(0);
- opt->val.w = SANE_FIX(0);
-
- opt = &(OPT_IN_CTX[opt_br_x]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_FIXED;
- sod->title = SANE_TITLE_SCAN_BR_X;
- sod->desc = SANE_DESC_SCAN_BR_X;
- sod->name = "br-x";
- sod->unit = SANE_UNIT_MM;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &ss->xrange;
- OPT_IN_CTX[opt_br_x].info = SANE_INFO_RELOAD_PARAMS;
- opt->def.w = sod->constraint.range->max;
- opt->val.w = sod->constraint.range->max;
-
- opt = &(OPT_IN_CTX[opt_br_y]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_FIXED;
- sod->title = SANE_TITLE_SCAN_BR_Y;
- sod->desc = SANE_DESC_SCAN_BR_Y;
- sod->name = "br-y";
- sod->unit = SANE_UNIT_MM;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &ss->yrange;
- OPT_IN_CTX[opt_br_y].info = SANE_INFO_RELOAD_PARAMS;
- opt->def.w = sod->constraint.range->max;
- opt->val.w = sod->constraint.range->max;
-
- opt = &(OPT_IN_CTX[opt__group_4]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_GROUP;
- sod->title = SANE_I18N("Buttons");
- sod->desc = sod->title;
-
- opt = &(OPT_IN_CTX[opt_button_update]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_BUTTON;
- sod->title = SANE_I18N("Update button state");
- sod->desc = sod->title;
- sod->name = "button-update";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 0;
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_button_update].info = 0;
-
- opt = &(OPT_IN_CTX[opt_button_1]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("Button 1");
- sod->desc = sod->title;
- sod->name = "button-1";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_button_1].info = 0;
- opt->def.w = 0;
- opt->val.w = 0;
-
- opt = &(OPT_IN_CTX[opt_button_2]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("Button 2");
- sod->desc = sod->title;
- sod->name = "button-2";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_button_2].info = 0;
- opt->def.w = 0;
- opt->val.w = 0;
-
- opt = &(OPT_IN_CTX[opt_original]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("Type of original to scan");
- sod->desc = sod->title;
- sod->name = "original";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_original].info = 0;
- opt->def.w = 0;
- opt->val.w = 0;
-
- opt = &(OPT_IN_CTX[opt_target]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("Target operation type");
- sod->desc = sod->title;
- sod->name = "target";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_target].info = 0;
- opt->def.w = 0;
- opt->val.w = 0;
-
- opt = &(OPT_IN_CTX[opt_scan_resolution]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("Scan resolution");
- sod->desc = sod->title;
- sod->name = "scan-resolution";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_DETECT|SANE_CAP_ADVANCED;
- sod->constraint_type = SANE_CONSTRAINT_NONE;
- OPT_IN_CTX[opt_scan_resolution].info = 0;
- opt->def.w = 0;
- opt->val.w = 0;
-
- opt = &(OPT_IN_CTX[opt__group_5]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_GROUP;
- sod->title = SANE_I18N("Extras");
- sod->desc = sod->title;
-
- opt = &(OPT_IN_CTX[opt_threshold]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_TITLE_THRESHOLD;
- sod->desc = SANE_DESC_THRESHOLD;
- sod->name = "threshold";
- sod->unit = SANE_UNIT_PERCENT;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &constraint_threshold;
- OPT_IN_CTX[opt_threshold].info = 0;
- opt->def.w = 50;
- opt->val.w = 50;
-
- opt = &(OPT_IN_CTX[opt_threshold_curve]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("Threshold curve");
- sod->desc = SANE_I18N("Dynamic threshold curve, from light to dark, normally 50-65");
- sod->name = "threshold-curve";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &constraint_threshold_curve;
- OPT_IN_CTX[opt_threshold_curve].info = 0;
-
- opt = &(OPT_IN_CTX[opt_adf_wait]);
- sod = &opt->sod;
- sod->type = SANE_TYPE_INT;
- sod->title = SANE_I18N("ADF Waiting Time");
- sod->desc = SANE_I18N("When set, the scanner waits upto the specified time in seconds for a new document inserted into the automatic document feeder.");
- sod->name = "adf-wait";
- sod->unit = SANE_UNIT_NONE;
- sod->size = 1 * sizeof(SANE_Word);
- sod->cap = SANE_CAP_SOFT_SELECT|SANE_CAP_SOFT_DETECT|SANE_CAP_AUTOMATIC|SANE_CAP_INACTIVE;
- sod->constraint_type = SANE_CONSTRAINT_RANGE;
- sod->constraint.range = &constraint_adf_wait;
- OPT_IN_CTX[opt_adf_wait].info = 0;
- opt->def.w = 0;
- opt->val.w = 0;
-
- return 0;
-
-}
diff --git a/backend/pixma/pixma_sane_options.h b/backend/pixma/pixma_sane_options.h
deleted file mode 100644
index 1472f1f..0000000
--- a/backend/pixma/pixma_sane_options.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Automatically generated from pixma_sane.c */
-
-typedef union {
- SANE_Word w;
- SANE_Int i;
- SANE_Bool b;
- SANE_Fixed f;
- SANE_String s;
- void *ptr;
-} option_value_t;
-
-typedef enum {
- opt_opt_num_opts,
- opt__group_1,
- opt_resolution,
- opt_mode,
- opt_source,
- opt_button_controlled,
- opt__group_2,
- opt_custom_gamma,
- opt_gamma_table,
- opt_gamma,
- opt__group_3,
- opt_tl_x,
- opt_tl_y,
- opt_br_x,
- opt_br_y,
- opt__group_4,
- opt_button_update,
- opt_button_1,
- opt_button_2,
- opt_original,
- opt_target,
- opt_scan_resolution,
- opt__group_5,
- opt_threshold,
- opt_threshold_curve,
- opt_adf_wait,
- opt_last
-} option_t;
-
-
-typedef struct {
- SANE_Option_Descriptor sod;
- option_value_t val,def;
- SANE_Word info;
-} option_descriptor_t;
-
-
-struct pixma_sane_t;
-static int build_option_descriptors(struct pixma_sane_t *ss);
diff --git a/backend/pixma/scripts/pixma_gen_options.py b/backend/pixma/scripts/pixma_gen_options.py
index c4c75e0..cee2c58 100755
--- a/backend/pixma/scripts/pixma_gen_options.py
+++ b/backend/pixma/scripts/pixma_gen_options.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
+from __future__ import print_function
import sys,os,re
+import functools
class Error(Exception):
pass
@@ -181,40 +183,35 @@ def parseFile(f):
def genHeader(options):
- print """
-typedef union {
- SANE_Word w;
- SANE_Int i;
- SANE_Bool b;
- SANE_Fixed f;
- SANE_String s;
- void *ptr;
-} option_value_t;
-"""
- print 'typedef enum {'
+ print ("\ntypedef union {")
+ print (" SANE_Word w;")
+ print (" SANE_Int i;")
+ print (" SANE_Bool b;")
+ print (" SANE_Fixed f;")
+ print (" SANE_String s;")
+ print (" void *ptr;")
+ print ("} option_value_t;")
+ print ("\ntypedef enum {")
for o in options:
- print ' %(cname_opt)s,' % o
- print ' ' + opt_prefix + 'last'
- print '} option_t;'
- print """
+ print (" %(cname_opt)s," % o)
+ print (" " + opt_prefix + "last")
+ print ("} option_t;")
-typedef struct {
- SANE_Option_Descriptor sod;
- option_value_t val,def;
- SANE_Word info;
-} option_descriptor_t;
+ print ("\ntypedef struct {")
+ print (" SANE_Option_Descriptor sod;")
+ print (" option_value_t val,def;")
+ print (" SANE_Word info;")
+ print ("} option_descriptor_t;")
-
-struct pixma_sane_t;
-static int build_option_descriptors(struct pixma_sane_t *ss);
-"""
+ print ("\nstruct pixma_sane_t;")
+ print ("static int build_option_descriptors(struct pixma_sane_t *ss);\n")
def genMinMaxRange(n, t, r):
if t == 'SANE_TYPE_FIXED':
r = ['SANE_FIX(%s)' % x for x in r]
- print 'static const SANE_Range ' + n + ' = '
- print ' { ' + r[0] + ',' + r[1] + ',' + r[2] + ' };'
+ print ("static const SANE_Range " + n + " =")
+ print (" { " + r[0] + "," + r[1] + "," + r[2] + " };")
def genList(n, t, l):
@@ -227,13 +224,14 @@ def genList(n, t, l):
elif t == 'SANE_TYPE_STRING':
etype = 'SANE_String_Const'
l = ['SANE_I18N("%s")' % x for x in l] + ['NULL']
- print 'static const %s %s[%d] = {' % (etype, n, len(l))
+ print ("static const %s %s[%d] = {" % (etype, n, len(l)))
for x in l[0:-1]:
- print '\t' + x + ','
- print '\t' + l[-1] + ' };'
+ print ("\t" + x + ",")
+ print ("\t" + l[-1] + " };")
def genConstraints(options):
+ print ("")
for o in options:
if 'constraint' not in o: continue
c = o['constraint']
@@ -243,7 +241,6 @@ def genConstraints(options):
genMinMaxRange(oname, otype, c)
elif isinstance(c, list):
genList(oname, otype, c)
- print
def buildCodeVerbatim(o):
for f in ('name', 'title', 'desc', 'type', 'unit', 'size', 'cap',
@@ -283,12 +280,12 @@ def ccode(o):
o['code_size'] = code
if ('code_cap' not in o) and ('cap' in o):
- o['code_cap'] = reduce(lambda a,b: a+'|'+b, o['cap'])
+ o['code_cap'] = functools.reduce(lambda a,b: a+'|'+b, o['cap'])
else:
o['code_cap'] = '0'
if ('code_info' not in o) and ('info' in o):
- o['code_info'] = reduce(lambda a,b: a+'|'+b, o['info'])
+ o['code_info'] = functools.reduce(lambda a,b: a+'|'+b, o['info'])
else:
o['code_info'] = '0'
@@ -335,22 +332,21 @@ def ccode(o):
return o
def genBuildOptions(options):
- print """
-static
-int find_string_in_list(SANE_String_Const str, const SANE_String_Const *list)
-{
- int i;
- for (i = 0; list[i] && strcmp(str, list[i]) != 0; i++) {}
- return i;
-}
-
-static
-int build_option_descriptors(struct pixma_sane_t *ss)
-{
- SANE_Option_Descriptor *sod;
- option_descriptor_t *opt;
-
- memset(OPT_IN_CTX, 0, sizeof(OPT_IN_CTX));"""
+ print ("\nstatic")
+ print ("int find_string_in_list(SANE_String_Const str, const SANE_String_Const *list)")
+ print ("{")
+ print (" int i;")
+ print (" for (i = 0; list[i] && strcmp(str, list[i]) != 0; i++) {}")
+ print (" return i;")
+ print ("}")
+ print ("")
+ print ("static")
+ print ("int build_option_descriptors(struct pixma_sane_t *ss)")
+ print ("{")
+ print (" SANE_Option_Descriptor *sod;")
+ print (" option_descriptor_t *opt;")
+ print ("")
+ print (" memset(OPT_IN_CTX, 0, sizeof(OPT_IN_CTX));")
for o in options:
o = ccode(o)
@@ -370,10 +366,9 @@ int build_option_descriptors(struct pixma_sane_t *ss)
' OPT_IN_CTX[%(cname_opt)s].info = %(code_info)s;\n' \
'%(full_code_default)s'
sys.stdout.write(code % o)
- print
- print ' return 0;\n'
- print '}'
- print
+ print ("")
+ print (" return 0;")
+ print ("}\n")
g = Struct()
g.ngroups = 0
@@ -381,7 +376,8 @@ opt_prefix = 'opt_'
con_prefix = 'constraint_'
cnameMap = createCNameMap()
options = parseFile(sys.stdin)
-print "/* Automatically generated from pixma_sane.c */"
+print ("/* DO NOT EDIT THIS FILE! */")
+print ("/* Automatically generated from pixma.c */")
if (len(sys.argv) == 2) and (sys.argv[1] == 'h'):
genHeader(options)
else: