diff options
Diffstat (limited to 'backend/pixma')
-rw-r--r-- | backend/pixma/.gitignore | 1 | ||||
-rw-r--r-- | backend/pixma/pixma.c | 179 | ||||
-rw-r--r-- | backend/pixma/pixma.h | 28 | ||||
-rw-r--r-- | backend/pixma/pixma_bjnp.c | 201 | ||||
-rw-r--r-- | backend/pixma/pixma_bjnp_private.h | 10 | ||||
-rw-r--r-- | backend/pixma/pixma_common.c | 175 | ||||
-rw-r--r-- | backend/pixma/pixma_common.h | 3 | ||||
-rw-r--r-- | backend/pixma/pixma_imageclass.c | 10 | ||||
-rw-r--r-- | backend/pixma/pixma_io_sanei.c | 2 | ||||
-rw-r--r-- | backend/pixma/pixma_mp150.c | 192 | ||||
-rw-r--r-- | backend/pixma/pixma_mp730.c | 4 | ||||
-rw-r--r-- | backend/pixma/pixma_mp750.c | 4 | ||||
-rw-r--r-- | backend/pixma/pixma_mp800.c | 135 | ||||
-rw-r--r-- | backend/pixma/pixma_sane_options.c | 362 | ||||
-rw-r--r-- | backend/pixma/pixma_sane_options.h | 51 | ||||
-rwxr-xr-x | backend/pixma/scripts/pixma_gen_options.py | 102 |
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: |