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: | 
