diff options
Diffstat (limited to 'backend/escl')
| -rw-r--r-- | backend/escl/escl.c | 587 | ||||
| -rw-r--r-- | backend/escl/escl.h | 120 | ||||
| -rw-r--r-- | backend/escl/escl_capabilities.c | 111 | ||||
| -rw-r--r-- | backend/escl/escl_crop.c | 4 | ||||
| -rw-r--r-- | backend/escl/escl_devices.c | 31 | ||||
| -rw-r--r-- | backend/escl/escl_jpeg.c | 4 | ||||
| -rw-r--r-- | backend/escl/escl_mupdf.c | 4 | ||||
| -rw-r--r-- | backend/escl/escl_newjob.c | 156 | ||||
| -rw-r--r-- | backend/escl/escl_pdf.c | 8 | ||||
| -rw-r--r-- | backend/escl/escl_png.c | 8 | ||||
| -rw-r--r-- | backend/escl/escl_reset.c | 6 | ||||
| -rw-r--r-- | backend/escl/escl_scan.c | 8 | ||||
| -rw-r--r-- | backend/escl/escl_status.c | 5 | ||||
| -rw-r--r-- | backend/escl/escl_tiff.c | 4 | 
14 files changed, 907 insertions, 149 deletions
| diff --git a/backend/escl/escl.c b/backend/escl/escl.c index c40fd98..bb62219 100644 --- a/backend/escl/escl.c +++ b/backend/escl/escl.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -29,15 +29,32 @@  #include <setjmp.h> -#include <curl/curl.h> -  #include "../include/sane/saneopts.h"  #include "../include/sane/sanei.h"  #include "../include/sane/sanei_backend.h"  #include "../include/sane/sanei_config.h" + +#ifndef SANE_NAME_SHARPEN +# define SANE_NAME_SHARPEN "sharpen" +# define SANE_TITLE_SHARPEN SANE_I18N("Sharpen") +# define SANE_DESC_SHARPEN SANE_I18N("Set sharpen value.") +#endif + +#ifndef SANE_NAME_THRESHOLD +# define SANE_NAME_THRESHOLD "threshold" +#endif +#ifndef SANE_TITLE_THRESHOLD +# define SANE_TITLE_THRESHOLD SANE_I18N("Threshold") +#endif +#ifndef SANE_DESC_THRESHOLD +# define SANE_DESC_THRESHOLD \ +    SANE_I18N("Set threshold for line-art scans.") +#endif +  #define min(A,B) (((A)<(B)) ? (A) : (B))  #define max(A,B) (((A)>(B)) ? (A) : (B)) +#define IS_ACTIVE(OPTION) (((handler->opt[OPTION].cap) & SANE_CAP_INACTIVE) == 0)  #define INPUT_BUFFER_SIZE 4096  static const SANE_Device **devlist = NULL; @@ -56,6 +73,10 @@ typedef struct Handled {      SANE_Range x_range2;      SANE_Range y_range1;      SANE_Range y_range2; +    SANE_Range brightness_range; +    SANE_Range contrast_range; +    SANE_Range sharpen_range; +    SANE_Range thresold_range;      SANE_Bool cancel;      SANE_Bool write_scan_data;      SANE_Bool decompress_scan_data; @@ -70,7 +91,10 @@ escl_free_device(ESCL_Device *current)      free((void*)current->ip_address);      free((void*)current->model_name);      free((void*)current->type); -    free(current->unix_socket); +    free((void*)current->is); +    free((void*)current->uuid); +    free((void*)current->unix_socket); +    curl_slist_free_all(current->hack);      free(current);      return NULL;  } @@ -110,6 +134,10 @@ escl_check_and_add_device(ESCL_Device *current)        DBG (10, "Scanner Type allocation failure.\n");        return (SANE_STATUS_NO_MEM);      } +    if (!current->is) { +      DBG (10, "Scanner Is allocation failure.\n"); +      return (SANE_STATUS_NO_MEM); +    }      ++num_devices;      current->next = list_devices_primary;      list_devices_primary = current; @@ -150,14 +178,20 @@ escl_add_in_list(ESCL_Device *current)   * \return escl_add_in_list(current)   */  SANE_Status -escl_device_add(int port_nb, const char *model_name, char *ip_address, char *type) +escl_device_add(int port_nb, +                const char *model_name, +                char *ip_address, +                const char *is, +                const char *uuid, +                char *type)  {      char tmp[PATH_MAX] = { 0 };      char *model = NULL;      ESCL_Device *current = NULL;      DBG (10, "escl_device_add\n");      for (current = list_devices_primary; current; current = current->next) { -	if (strcmp(current->ip_address, ip_address) == 0) +	if ((strcmp(current->ip_address, ip_address) == 0) || +            (uuid && current->uuid && !strcmp(current->uuid, uuid)))             {  	      if (strcmp(current->type, type))                  { @@ -166,6 +200,10 @@ escl_device_add(int port_nb, const char *model_name, char *ip_address, char *typ                      {                         free (current->type);                         current->type = strdup(type); +                       if (strcmp(current->ip_address, ip_address)) { +                           free (current->ip_address); +                           current->ip_address = strdup(ip_address); +                       }                         current->port_nb = port_nb;                         current->https = SANE_TRUE;                      } @@ -191,7 +229,12 @@ escl_device_add(int port_nb, const char *model_name, char *ip_address, char *typ      model = (char*)(tmp[0] != 0 ? tmp : model_name);      current->model_name = strdup(model);      current->ip_address = strdup(ip_address); +    memset(tmp, 0, PATH_MAX); +    snprintf(tmp, sizeof(tmp), "%s scanner", (is ? is : "flatbed or ADF")); +    current->is = strdup(tmp);      current->type = strdup(type); +    if (uuid) +       current->uuid = strdup(uuid);      return escl_add_in_list(current);  } @@ -259,7 +302,7 @@ get_vendor(char *search)   * \brief Function that checks if the url of the received scanner is secured or not (http / https).   *        --> if the url is not secured, our own url will be composed like "http://'ip':'port'".   *        --> else, our own url will be composed like "https://'ip':'port'". - *        AND, it's in this function that we gather all the informations of the url (that were in our list) : + *        AND, it's in this function that we gather all the information of the url (that were in our list) :   *        the model_name, the port, the ip, and the type of url.   *        SO, leaving this function, we have in memory the complete url.   * @@ -308,7 +351,7 @@ convertFromESCLDev(ESCL_Device *cdev)         DBG (10, "Model allocation failure.\n");         goto freename;      } -    sdev->type = strdup("flatbed scanner"); +    sdev->type = strdup(cdev->is);      if (!sdev->type) {         DBG (10, "Scanner Type allocation failure.\n");         goto freevendor; @@ -383,7 +426,8 @@ sane_exit(void)   * \return escl_add_in_list(escl_device) if the parsing worked, SANE_STATUS_GOOD otherwise.   */  static SANE_Status -attach_one_config(SANEI_Config __sane_unused__ *config, const char *line) +attach_one_config(SANEI_Config __sane_unused__ *config, const char *line, +		  void __sane_unused__ *data)  {      int port = 0;      SANE_Status status; @@ -392,6 +436,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)      if (strncmp(line, "device", 6) == 0) {          char *name_str = NULL;          char *opt_model = NULL; +        char *opt_hack = NULL;          line = sanei_config_get_string(line + 6, &name_str);          DBG (10, "New Escl_Device URL [%s].\n", (name_str ? name_str : "VIDE")); @@ -403,6 +448,10 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)              line = sanei_config_get_string(line, &opt_model);              DBG (10, "New Escl_Device model [%s].\n", opt_model);          } +        if (*line) { +            line = sanei_config_get_string(line, &opt_hack); +            DBG (10, "New Escl_Device hack [%s].\n", opt_hack); +        }          escl_free_device(escl_device);          escl_device = (ESCL_Device*)calloc(1, sizeof(ESCL_Device)); @@ -419,7 +468,9 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)              return status;          }          escl_device->model_name = opt_model ? opt_model : strdup("Unknown model"); -        escl_device->type = strdup("flatbed scanner"); +        escl_device->is = strdup("flatbed or ADF scanner"); +        escl_device->type = strdup("In url"); +        escl_device->uuid = NULL;      }      if (strncmp(line, "[device]", 8) == 0) { @@ -430,7 +481,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)  	   return (SANE_STATUS_NO_MEM);  	}      } -    if (strncmp(line, "ip", 2) == 0) { +    else if (strncmp(line, "ip", 2) == 0) {  	const char *ip_space = sanei_config_skip_whitespace(line + 2);  	DBG (10, "New Escl_Device IP [%s].", (ip_space ? ip_space : "VIDE"));  	if (escl_device != NULL && ip_space != NULL) { @@ -438,14 +489,14 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)  	    escl_device->ip_address = strdup(ip_space);  	}      } -    if (sscanf(line, "port %i", &port) == 1 && port != 0) { +    else if (sscanf(line, "port %i", &port) == 1 && port != 0) {  	DBG (10, "New Escl_Device PORT [%d].", port);  	if (escl_device != NULL) {  	    DBG (10, "New Escl_Device PORT Affected.");  	    escl_device->port_nb = port;  	}      } -    if (strncmp(line, "model", 5) == 0) { +    else if (strncmp(line, "model", 5) == 0) {  	const char *model_space = sanei_config_skip_whitespace(line + 5);  	DBG (10, "New Escl_Device MODEL [%s].", (model_space ? model_space : "VIDE"));  	if (escl_device != NULL && model_space != NULL) { @@ -453,7 +504,7 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)  	    escl_device->model_name = strdup(model_space);  	}      } -    if (strncmp(line, "type", 4) == 0) { +    else if (strncmp(line, "type", 4) == 0) {  	const char *type_space = sanei_config_skip_whitespace(line + 4);  	DBG (10, "New Escl_Device TYPE [%s].", (type_space ? type_space : "VIDE"));  	if (escl_device != NULL && type_space != NULL) { @@ -461,6 +512,8 @@ attach_one_config(SANEI_Config __sane_unused__ *config, const char *line)  	    escl_device->type = strdup(type_space);  	}      } +    escl_device->is = strdup("flatbed or ADF scanner"); +    escl_device->uuid = NULL;      status = escl_check_and_add_device(escl_device);      if (status == SANE_STATUS_GOOD)         escl_device = NULL; @@ -487,7 +540,8 @@ sane_get_devices(const SANE_Device ***device_list, SANE_Bool local_only)      if (device_list == NULL)  	return (SANE_STATUS_INVAL); -    status = sanei_configure_attach(ESCL_CONFIG_FILE, NULL, attach_one_config); +    status = sanei_configure_attach(ESCL_CONFIG_FILE, NULL, +				    attach_one_config, NULL);      if (status != SANE_STATUS_GOOD)  	return (status);      escl_devices(&status); @@ -526,10 +580,156 @@ _source_size_max (SANE_String_Const * sources)    return size;  } +static int +_get_resolution(escl_sane_t *handler, int resol) +{ +    int x = 1; +    int n = handler->scanner->caps[handler->scanner->source].SupportedResolutions[0] + 1; +    int old = -1; +    for (; x < n; x++) { +      DBG(10, "SEARCH RESOLUTION [ %d | %d]\n", resol, (int)handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]); +      if (resol == handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]) +         return resol; +      else if (resol < handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]) +      { +          if (old == -1) +             return handler->scanner->caps[handler->scanner->source].SupportedResolutions[1]; +          else +             return old; +      } +      else +          old = handler->scanner->caps[handler->scanner->source].SupportedResolutions[x]; +    } +    return old; +} + + +/** + * \fn static SANE_Status init_options(SANE_String_Const name, escl_sane_t *s) + * \brief Function thzt initializes all the needed options of the received scanner + *        (the resolution / the color / the margins) thanks to the information received with + *        the 'escl_capabilities' function, called just before. + * + * \return status (if everything is OK, status = SANE_STATUS_GOOD) + */ +static SANE_Status +init_options_small(SANE_String_Const name_source, escl_sane_t *s) +{ +    int found = 0; +    DBG (10, "escl init_options\n"); + +    SANE_Status status = SANE_STATUS_GOOD; +    if (!s->scanner) return SANE_STATUS_INVAL; +    if (name_source) { +	   int source = s->scanner->source; +	   if (!strcmp(name_source, SANE_I18N ("ADF Duplex"))) +	       s->scanner->source = ADFDUPLEX; +	   else if (!strncmp(name_source, "A", 1) || +	            !strcmp(name_source, SANE_I18N ("ADF"))) +	       s->scanner->source = ADFSIMPLEX; +	   else +	       s->scanner->source = PLATEN; +	   if (source == s->scanner->source) return status; +           s->scanner->caps[s->scanner->source].default_color = +                strdup(s->scanner->caps[source].default_color); +           s->scanner->caps[s->scanner->source].default_resolution = +                _get_resolution(s, s->scanner->caps[source].default_resolution); +    } +    if (s->scanner->caps[s->scanner->source].ColorModes == NULL) { +        if (s->scanner->caps[PLATEN].ColorModes) +            s->scanner->source = PLATEN; +        else if (s->scanner->caps[ADFSIMPLEX].ColorModes) +            s->scanner->source = ADFSIMPLEX; +        else if (s->scanner->caps[ADFDUPLEX].ColorModes) +            s->scanner->source = ADFDUPLEX; +        else +            return SANE_STATUS_INVAL; +    } +    if (s->scanner->source == PLATEN) { +        DBG (10, "SOURCE PLATEN.\n"); +    } +    else if (s->scanner->source == ADFDUPLEX) { +        DBG (10, "SOURCE ADFDUPLEX.\n"); +    } +    else if (s->scanner->source == ADFSIMPLEX) { +        DBG (10, "SOURCE ADFSIMPLEX.\n"); +    } +    s->x_range1.min = 0; +    s->x_range1.max = +	    PIXEL_TO_MM((s->scanner->caps[s->scanner->source].MaxWidth - +		         s->scanner->caps[s->scanner->source].MinWidth), +			300.0); +    s->x_range1.quant = 0; +    s->x_range2.min = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MinWidth, 300.0); +    s->x_range2.max = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MaxWidth, 300.0); +    s->x_range2.quant = 0; +    s->y_range1.min = 0; +    s->y_range1.max = +	    PIXEL_TO_MM((s->scanner->caps[s->scanner->source].MaxHeight - +	                 s->scanner->caps[s->scanner->source].MinHeight), +			300.0); +    s->y_range1.quant = 0; +    s->y_range2.min = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MinHeight, 300.0); +    s->y_range2.max = PIXEL_TO_MM(s->scanner->caps[s->scanner->source].MaxHeight, 300.0); +    s->y_range2.quant = 0; + +    s->opt[OPT_MODE].constraint.string_list = s->scanner->caps[s->scanner->source].ColorModes; +    if (s->val[OPT_MODE].s) +        free(s->val[OPT_MODE].s); +    s->val[OPT_MODE].s = NULL; + +    if (s->scanner->caps[s->scanner->source].default_color) { +        int x = 0; +        if (!strcmp(s->scanner->caps[s->scanner->source].default_color, "Grayscale8")) +           s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_GRAY); +        else if (!strcmp(s->scanner->caps[s->scanner->source].default_color, "BlackAndWhite1")) +           s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_LINEART); +        else +           s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_COLOR); +        for (x = 0; s->scanner->caps[s->scanner->source].ColorModes[x]; x++) { +            if (s->scanner->caps[s->scanner->source].ColorModes[x] && +              !strcasecmp(s->scanner->caps[s->scanner->source].ColorModes[x], s->val[OPT_MODE].s)) { +              found = 1; +              break; +            } +        } +    } +    if (!s->scanner->caps[s->scanner->source].default_color || found == 0) { +        if (s->scanner->caps[s->scanner->source].default_color) +           free(s->scanner->caps[s->scanner->source].default_color); +        s->val[OPT_MODE].s = strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); +        if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) +            s->scanner->caps[s->scanner->source].default_color = strdup("Grayscale8"); +        else if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) +            s->scanner->caps[s->scanner->source].default_color = strdup("BlackAndWhite1"); +        else +            s->scanner->caps[s->scanner->source].default_color = strdup("RGB24"); +    } +    if (!s->val[OPT_MODE].s) { +       DBG (10, "Color Mode Default allocation failure.\n"); +       return (SANE_STATUS_NO_MEM); +    } +    if (!s->scanner->caps[s->scanner->source].default_color) { +       DBG (10, "Color Mode Default allocation failure.\n"); +       return (SANE_STATUS_NO_MEM); +    } +    s->val[OPT_RESOLUTION].w = s->scanner->caps[s->scanner->source].default_resolution; +    s->opt[OPT_TL_X].constraint.range = &s->x_range1; +    s->opt[OPT_TL_Y].constraint.range = &s->y_range1; +    s->opt[OPT_BR_X].constraint.range = &s->x_range2; +    s->opt[OPT_BR_Y].constraint.range = &s->y_range2; + +    if (s->val[OPT_SCAN_SOURCE].s) +      free (s->val[OPT_SCAN_SOURCE].s); +    s->val[OPT_SCAN_SOURCE].s = strdup (s->scanner->Sources[s->scanner->source]); + +    return (SANE_STATUS_GOOD); +} +  /**   * \fn static SANE_Status init_options(SANE_String_Const name, escl_sane_t *s)   * \brief Function thzt initializes all the needed options of the received scanner - *        (the resolution / the color / the margins) thanks to the informations received with + *        (the resolution / the color / the margins) thanks to the information received with   *        the 'escl_capabilities' function, called just before.   *   * \return status (if everything is OK, status = SANE_STATUS_GOOD) @@ -554,8 +754,25 @@ init_options(SANE_String_Const name_source, escl_sane_t *s)  	       s->scanner->source = PLATEN;  	   if (source == s->scanner->source) return status;      } -    else -	   s->scanner->source = PLATEN; +    if (s->scanner->caps[s->scanner->source].ColorModes == NULL) { +        if (s->scanner->caps[PLATEN].ColorModes) +            s->scanner->source = PLATEN; +        else if (s->scanner->caps[ADFSIMPLEX].ColorModes) +            s->scanner->source = ADFSIMPLEX; +        else if (s->scanner->caps[ADFDUPLEX].ColorModes) +            s->scanner->source = ADFDUPLEX; +        else +            return SANE_STATUS_INVAL; +    } +    if (s->scanner->source == PLATEN) { +        DBG (10, "SOURCE PLATEN.\n"); +    } +    else if (s->scanner->source == ADFDUPLEX) { +        DBG (10, "SOURCE ADFDUPLEX.\n"); +    } +    else if (s->scanner->source == ADFSIMPLEX) { +        DBG (10, "SOURCE ADFSIMPLEX.\n"); +    }      memset (s->opt, 0, sizeof (s->opt));      memset (s->val, 0, sizeof (s->val));      for (i = 0; i < NUM_OPTIONS; ++i) { @@ -590,6 +807,7 @@ init_options(SANE_String_Const name_source, escl_sane_t *s)      s->opt[OPT_MODE_GROUP].desc = "";      s->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;      s->opt[OPT_MODE_GROUP].cap = 0; +    s->opt[OPT_MODE_GROUP].size = 0;      s->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;      s->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE; @@ -599,17 +817,39 @@ init_options(SANE_String_Const name_source, escl_sane_t *s)      s->opt[OPT_MODE].unit = SANE_UNIT_NONE;      s->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;      s->opt[OPT_MODE].constraint.string_list = s->scanner->caps[s->scanner->source].ColorModes; -    s->val[OPT_MODE].s = (char *)strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); +    if (s->scanner->caps[s->scanner->source].default_color) { +        if (!strcasecmp(s->scanner->caps[s->scanner->source].default_color, "Grayscale8")) +           s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_GRAY); +        else if (!strcasecmp(s->scanner->caps[s->scanner->source].default_color, "BlackAndWhite1")) +           s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_LINEART); +        else +           s->val[OPT_MODE].s = (char *)strdup(SANE_VALUE_SCAN_MODE_COLOR); +    } +    else { +        s->val[OPT_MODE].s = (char *)strdup(s->scanner->caps[s->scanner->source].ColorModes[0]); +        if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) { +           s->scanner->caps[s->scanner->source].default_color = strdup("Grayscale8"); +        } +        else if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) { +           s->scanner->caps[s->scanner->source].default_color = +                strdup("BlackAndWhite1"); +        } +        else { +           s->scanner->caps[s->scanner->source].default_color = +               strdup("RGB24"); +       } +    }      if (!s->val[OPT_MODE].s) {         DBG (10, "Color Mode Default allocation failure.\n");         return (SANE_STATUS_NO_MEM);      } +    DBG (10, "++ Color Mode Default allocation [%s].\n", s->scanner->caps[s->scanner->source].default_color);      s->opt[OPT_MODE].size = max_string_size(s->scanner->caps[s->scanner->source].ColorModes); -    s->scanner->caps[s->scanner->source].default_color = (char *)strdup(s->scanner->caps[s->scanner->source].ColorModes[0]);      if (!s->scanner->caps[s->scanner->source].default_color) {         DBG (10, "Color Mode Default allocation failure.\n");         return (SANE_STATUS_NO_MEM);      } +    DBG (10, "Color Mode Default allocation (%s).\n", s->scanner->caps[s->scanner->source].default_color);      s->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;      s->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION; @@ -638,6 +878,7 @@ init_options(SANE_String_Const name_source, escl_sane_t *s)      s->opt[OPT_GEOMETRY_GROUP].desc = SANE_DESC_GEOMETRY;      s->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;      s->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED; +    s->opt[OPT_GEOMETRY_GROUP].size = 0;      s->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;      s->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X; @@ -696,6 +937,113 @@ init_options(SANE_String_Const name_source, escl_sane_t *s)      if (s->val[OPT_SCAN_SOURCE].s)         free (s->val[OPT_SCAN_SOURCE].s);      s->val[OPT_SCAN_SOURCE].s = strdup (s->scanner->Sources[s->scanner->source]); + +    /* "Enhancement" group: */ +    s->opt[OPT_ENHANCEMENT_GROUP].title = SANE_I18N ("Enhancement"); +    s->opt[OPT_ENHANCEMENT_GROUP].desc = "";    /* not valid for a group */ +    s->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP; +    s->opt[OPT_ENHANCEMENT_GROUP].cap = SANE_CAP_ADVANCED; +    s->opt[OPT_ENHANCEMENT_GROUP].size = 0; +    s->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE; + + +    s->opt[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS; +    s->opt[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS; +    s->opt[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS; +    s->opt[OPT_BRIGHTNESS].type = SANE_TYPE_INT; +    s->opt[OPT_BRIGHTNESS].unit = SANE_UNIT_NONE; +    s->opt[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE; +    if (s->scanner->brightness) { +       s->opt[OPT_BRIGHTNESS].constraint.range = &s->brightness_range; +       s->val[OPT_BRIGHTNESS].w = s->scanner->brightness->normal; +       s->brightness_range.quant=1; +       s->brightness_range.min=s->scanner->brightness->min; +       s->brightness_range.max=s->scanner->brightness->max; +    } +    else{ +      SANE_Range range = { 0, 255, 0 }; +      s->opt[OPT_BRIGHTNESS].constraint.range = ⦥ +      s->val[OPT_BRIGHTNESS].w = 0; +      s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; +    } +    s->opt[OPT_CONTRAST].name = SANE_NAME_CONTRAST; +    s->opt[OPT_CONTRAST].title = SANE_TITLE_CONTRAST; +    s->opt[OPT_CONTRAST].desc = SANE_DESC_CONTRAST; +    s->opt[OPT_CONTRAST].type = SANE_TYPE_INT; +    s->opt[OPT_CONTRAST].unit = SANE_UNIT_NONE; +    s->opt[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE; +    if (s->scanner->contrast) { +       s->opt[OPT_CONTRAST].constraint.range = &s->contrast_range; +       s->val[OPT_CONTRAST].w = s->scanner->contrast->normal; +       s->contrast_range.quant=1; +       s->contrast_range.min=s->scanner->contrast->min; +       s->contrast_range.max=s->scanner->contrast->max; +    } +    else{ +      SANE_Range range = { 0, 255, 0 }; +      s->opt[OPT_CONTRAST].constraint.range = ⦥ +      s->val[OPT_CONTRAST].w = 0; +      s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; +    } +    s->opt[OPT_SHARPEN].name = SANE_NAME_SHARPEN; +    s->opt[OPT_SHARPEN].title = SANE_TITLE_SHARPEN; +    s->opt[OPT_SHARPEN].desc = SANE_DESC_SHARPEN; +    s->opt[OPT_SHARPEN].type = SANE_TYPE_INT; +    s->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE; +    s->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_RANGE; +    if (s->scanner->sharpen) { +       s->opt[OPT_SHARPEN].constraint.range = &s->sharpen_range; +       s->val[OPT_SHARPEN].w = s->scanner->sharpen->normal; +       s->sharpen_range.quant=1; +       s->sharpen_range.min=s->scanner->sharpen->min; +       s->sharpen_range.max=s->scanner->sharpen->max; +    } +    else{ +      SANE_Range range = { 0, 255, 0 }; +      s->opt[OPT_SHARPEN].constraint.range = ⦥ +      s->val[OPT_SHARPEN].w = 0; +      s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; +    } +    /*threshold*/ +    s->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD; +    s->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD; +    s->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD; +    s->opt[OPT_THRESHOLD].type = SANE_TYPE_INT; +    s->opt[OPT_THRESHOLD].unit = SANE_UNIT_NONE; +    s->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE; +    if (s->scanner->threshold) { +      s->opt[OPT_THRESHOLD].constraint.range = &s->thresold_range; +      s->val[OPT_THRESHOLD].w = s->scanner->threshold->normal; +      s->thresold_range.quant=1; +      s->thresold_range.min= s->scanner->threshold->min; +      s->thresold_range.max=s->scanner->threshold->max; +    } +    else{ +      SANE_Range range = { 0, 255, 0 }; +      s->opt[OPT_THRESHOLD].constraint.range = ⦥ +      s->val[OPT_THRESHOLD].w = 0; +      s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; +    } +    if (!strcasecmp(s->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) { +       if (s->scanner->threshold) +       	  s->opt[OPT_THRESHOLD].cap  &= ~SANE_CAP_INACTIVE; +       if (s->scanner->brightness) +       	  s->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; +       if (s->scanner->contrast) +       	  s->opt[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE; +       if (s->scanner->sharpen) +          s->opt[OPT_SHARPEN].cap |= SANE_CAP_INACTIVE; +    } +    else { +       if (s->scanner->threshold) +       	  s->opt[OPT_THRESHOLD].cap  |= SANE_CAP_INACTIVE; +       if (s->scanner->brightness) +          s->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; +       if (s->scanner->contrast) +          s->opt[OPT_CONTRAST].cap   &= ~SANE_CAP_INACTIVE; +       if (s->scanner->sharpen) +          s->opt[OPT_SHARPEN].cap   &= ~SANE_CAP_INACTIVE; +    }      return (status);  } @@ -745,6 +1093,50 @@ escl_parse_name(SANE_String_Const name, ESCL_Device *device)      return SANE_STATUS_GOOD;  } +static void +_get_hack(SANE_String_Const name, ESCL_Device *device) +{ +  FILE *fp; +  SANE_Char line[PATH_MAX]; +  DBG (3, "_get_hack: start\n"); +  if (device->model_name && +      (strcasestr(device->model_name, "LaserJet FlowMFP M578") || +       strcasestr(device->model_name, "LaserJet MFP M630"))) { +       device->hack = curl_slist_append(NULL, "Host: localhost"); +       DBG (3, "_get_hack: finish\n"); +       return; +  } + +  /* open configuration file */ +  fp = sanei_config_open (ESCL_CONFIG_FILE); +  if (!fp) +    { +      DBG (2, "_get_hack: couldn't access %s\n", ESCL_CONFIG_FILE); +      DBG (3, "_get_hack: exit\n"); +    } + +  /* loop reading the configuration file, all line beginning by "option " are +   * parsed for value to store in configuration structure, other line are +   * used are device to try to attach +   */ +  while (sanei_config_read (line, PATH_MAX, fp)) +    { +       if (strstr(line, name)) { +          DBG (3, "_get_hack: idevice found\n"); +	  if (strstr(line, "hack=localhost")) { +              DBG (3, "_get_hack: device found\n"); +	      device->hack = curl_slist_append(NULL, "Host: localhost"); +	  } +	  goto finish_hack; +       } +    } +finish_hack: +  DBG (3, "_get_hack: finish\n"); +  fclose(fp); +} + + +  /**   * \fn SANE_Status sane_open(SANE_String_Const name, SANE_Handle *h)   * \brief Function that establishes a connection with the device named by 'name', @@ -786,6 +1178,8 @@ sane_open(SANE_String_Const name, SANE_Handle *h)          escl_free_handler(handler);          return (status);      } +    _get_hack(name, device); +      status = init_options(NULL, handler);      if (status != SANE_STATUS_GOOD) {          escl_free_handler(handler); @@ -897,9 +1291,12 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int  	case OPT_BR_X:  	case OPT_BR_Y:  	case OPT_NUM_OPTS: -	case OPT_RESOLUTION:  	case OPT_PREVIEW:  	case OPT_GRAY_PREVIEW: +	case OPT_RESOLUTION: +        case OPT_BRIGHTNESS: +        case OPT_CONTRAST: +        case OPT_SHARPEN:  	    *(SANE_Word *) v = handler->val[n].w;  	    break;  	case OPT_SCAN_SOURCE: @@ -919,16 +1316,18 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int  	case OPT_BR_X:  	case OPT_BR_Y:  	case OPT_NUM_OPTS: -	case OPT_RESOLUTION:  	case OPT_PREVIEW:  	case OPT_GRAY_PREVIEW: +        case OPT_BRIGHTNESS: +        case OPT_CONTRAST: +        case OPT_SHARPEN:  	    handler->val[n].w = *(SANE_Word *) v;  	    if (i)  		*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;  	    break;  	case OPT_SCAN_SOURCE:  	    DBG(10, "SET OPT_SCAN_SOURCE(%s)\n", (SANE_String_Const)v); -	    init_options((SANE_String_Const)v, handler); +	    init_options_small((SANE_String_Const)v, handler);  	    if (i)  		*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;  	    break; @@ -940,6 +1339,48 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int  	      DBG (10, "OPT_MODE allocation failure.\n");  	      return (SANE_STATUS_NO_MEM);  	    } +	    DBG(10, "SET OPT_MODE(%s)\n", (SANE_String_Const)v); + +            if (!strcasecmp(handler->val[n].s, SANE_VALUE_SCAN_MODE_GRAY)) { +              handler->scanner->caps[handler->scanner->source].default_color = strdup("Grayscale8"); +	    DBG(10, "SET OPT_MODE(Grayscale8)\n"); +            } +            else if (!strcasecmp(handler->val[n].s, SANE_VALUE_SCAN_MODE_LINEART)) { +              handler->scanner->caps[handler->scanner->source].default_color = +                 strdup("BlackAndWhite1"); +	    DBG(10, "SET OPT_MODE(BlackAndWhite1)\n"); +            } +            else { +              handler->scanner->caps[handler->scanner->source].default_color = +                 strdup("RGB24"); +	         DBG(10, "SET OPT_MODE(RGB24)\n"); +            } +            DBG (10, "Color Mode allocation (%s).\n", handler->scanner->caps[handler->scanner->source].default_color); +	    if (i) +		*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; +            if (handler->scanner->brightness) +                handler->opt[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE; +            if (handler->scanner->contrast) +                handler->opt[OPT_CONTRAST].cap   |= SANE_CAP_INACTIVE; +            if (handler->scanner->threshold) +                handler->opt[OPT_THRESHOLD].cap  |= SANE_CAP_INACTIVE; +            if (handler->scanner->sharpen) +                handler->opt[OPT_SHARPEN].cap  |= SANE_CAP_INACTIVE; +            if (!strcasecmp(handler->val[n].s, SANE_VALUE_SCAN_MODE_LINEART)) { +               if (handler->scanner->threshold) +                  handler->opt[OPT_THRESHOLD].cap  &= ~SANE_CAP_INACTIVE; +            } +            else { +               if (handler->scanner->brightness) +                  handler->opt[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE; +               if (handler->scanner->contrast) +                  handler->opt[OPT_CONTRAST].cap   &= ~SANE_CAP_INACTIVE; +               if (handler->scanner->sharpen) +                  handler->opt[OPT_SHARPEN].cap   &= ~SANE_CAP_INACTIVE; +            } +	    break; +	case OPT_RESOLUTION: +            handler->val[n].w = _get_resolution(handler, (int)(*(SANE_Word *) v));  	    if (i)  		*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT;  	    break; @@ -975,7 +1416,7 @@ _go_next_page(SANE_Status status,  /**   * \fn SANE_Status sane_start(SANE_Handle h) - * \brief Function that initiates aquisition of an image from the device represented by handle 'h'. + * \brief Function that initiates acquisition of an image from the device represented by handle 'h'.   *        This function calls the "escl_newjob" function and the "escl_scan" function.   *   * \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL) @@ -1005,11 +1446,13 @@ sane_start(SANE_Handle h)                                      NULL);         if (st != SANE_STATUS_GOOD)            return st; -       if(handler->scanner->caps[handler->scanner->source].default_color) -          free(handler->scanner->caps[handler->scanner->source].default_color);         if (handler->val[OPT_PREVIEW].w == SANE_TRUE)         { -          int i = 0, val = 9999;; +          int i = 0, val = 9999; + +          if(handler->scanner->caps[handler->scanner->source].default_color) +             free(handler->scanner->caps[handler->scanner->source].default_color); +            if (handler->val[OPT_GRAY_PREVIEW].w == SANE_TRUE ||  	      !strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY))  	     handler->scanner->caps[handler->scanner->source].default_color = @@ -1032,15 +1475,18 @@ sane_start(SANE_Handle h)         {            handler->scanner->caps[handler->scanner->source].default_resolution =  	     handler->val[OPT_RESOLUTION].w; -          if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) -	     handler->scanner->caps[handler->scanner->source].default_color = strdup("Grayscale8"); -          else if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) -	     handler->scanner->caps[handler->scanner->source].default_color = -	         strdup("BlackAndWhite1"); -          else -	     handler->scanner->caps[handler->scanner->source].default_color = -	         strdup("RGB24"); +          if (!handler->scanner->caps[handler->scanner->source].default_color) { +             if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY)) +	        handler->scanner->caps[handler->scanner->source].default_color = strdup("Grayscale8"); +             else if (!strcasecmp(handler->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART)) +	        handler->scanner->caps[handler->scanner->source].default_color = +	            strdup("BlackAndWhite1"); +             else +	        handler->scanner->caps[handler->scanner->source].default_color = +	            strdup("RGB24"); +          }         } +       DBG (10, "Before newjob Color Mode allocation (%s).\n", handler->scanner->caps[handler->scanner->source].default_color);         handler->scanner->caps[handler->scanner->source].height =              MM_TO_PIXEL(handler->val[OPT_BR_Y].w, 300.0);         handler->scanner->caps[handler->scanner->source].width = @@ -1066,6 +1512,67 @@ sane_start(SANE_Handle h)            DBG (10, "Default Color allocation failure.\n");            return (SANE_STATUS_NO_MEM);         } + +       if (handler->scanner->threshold) { +          DBG(10, "Have Thresold\n"); +          if (IS_ACTIVE(OPT_THRESHOLD)) { +            DBG(10, "Use Thresold [%d]\n", handler->val[OPT_THRESHOLD].w); +            handler->scanner->val_threshold = handler->val[OPT_THRESHOLD].w; +            handler->scanner->use_threshold = 1; +         } +         else  { +            DBG(10, "Not use Thresold\n"); +            handler->scanner->use_threshold = 0; +         } +       } +       else +          DBG(10, "Don't have Thresold\n"); + +       if (handler->scanner->sharpen) { +          DBG(10, "Have Sharpen\n"); +           if (IS_ACTIVE(OPT_SHARPEN)) { +             DBG(10, "Use Sharpen [%d]\n", handler->val[OPT_SHARPEN].w); +             handler->scanner->val_sharpen = handler->val[OPT_SHARPEN].w; +             handler->scanner->use_sharpen = 1; +          } +         else  { +            DBG(10, "Not use Sharpen\n"); +            handler->scanner->use_sharpen = 0; +         } +       } +       else +          DBG(10, "Don't have Sharpen\n"); + +       if (handler->scanner->contrast) { +          DBG(10, "Have Contrast\n"); +          if (IS_ACTIVE(OPT_CONTRAST)) { +             DBG(10, "Use Contrast [%d]\n", handler->val[OPT_CONTRAST].w); +             handler->scanner->val_contrast = handler->val[OPT_CONTRAST].w; +             handler->scanner->use_contrast = 1; +          } +          else  { +             DBG(10, "Not use Contrast\n"); +             handler->scanner->use_contrast = 0; +          } +       } +       else +          DBG(10, "Don't have Contrast\n"); + +       if (handler->scanner->brightness) { +          DBG(10, "Have Brightness\n"); +          if (IS_ACTIVE(OPT_BRIGHTNESS)) { +             DBG(10, "Use Brightness [%d]\n", handler->val[OPT_BRIGHTNESS].w); +             handler->scanner->val_brightness = handler->val[OPT_BRIGHTNESS].w; +             handler->scanner->use_brightness = 1; +          } +          else  { +             DBG(10, "Not use Brightness\n"); +             handler->scanner->use_brightness = 0; +          } +       } +       else +          DBG(10, "Don't have Brightness\n"); +         handler->result = escl_newjob(handler->scanner, handler->device, &status);         if (status != SANE_STATUS_GOOD)            return (status); @@ -1104,7 +1611,7 @@ sane_start(SANE_Handle h)         status = get_PDF_data(handler->scanner, &w, &he, &bps);      }      else { -       DBG(10, "Unknow image format\n"); +       DBG(10, "Unknown image format\n");         return SANE_STATUS_INVAL;      } @@ -1257,6 +1764,12 @@ escl_curl_url(CURL *handle, const ESCL_Device *device, SANE_String_Const path)      DBG( 1, "escl_curl_url: URL: %s\n", url );      curl_easy_setopt(handle, CURLOPT_URL, url);      free(url); +    DBG( 1, "Before use hack\n"); +    if (device->hack) { +        DBG( 1, "Use hack\n"); +        curl_easy_setopt(handle, CURLOPT_HTTPHEADER, device->hack); +    } +    DBG( 1, "After use hack\n");      if (device->https) {          DBG( 1, "Ignoring safety certificates, use https\n");          curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); diff --git a/backend/escl/escl.h b/backend/escl/escl.h index 53ce7c7..67b11c7 100644 --- a/backend/escl/escl.h +++ b/backend/escl/escl.h @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -27,10 +27,13 @@  #include "../include/sane/config.h" +  #if !(HAVE_LIBCURL && defined(WITH_AVAHI) && defined(HAVE_LIBXML2))  #error "The escl backend requires libcurl, libavahi and libxml2"  #endif + +  #ifndef HAVE_LIBJPEG  /* FIXME: Make JPEG support optional.     Support for PNG and PDF is to be added later but currently only @@ -45,6 +48,8 @@  #include <stdio.h>  #include <math.h> +#include <curl/curl.h> +  #ifndef BACKEND_NAME  #define BACKEND_NAME escl  #endif @@ -87,12 +92,15 @@ typedef struct {  typedef struct ESCL_Device {      struct ESCL_Device *next; -    char    *model_name; -    int             port_nb; -    char      *ip_address; -    char *type; +    char     *model_name; +    int       port_nb; +    char     *ip_address; +    char     *is; +    char     *uuid; +    char     *type;      SANE_Bool https; -    char      *unix_socket; +    struct curl_slist *hack; +    char     *unix_socket;  } ESCL_Device;  typedef struct capst @@ -127,8 +135,20 @@ typedef struct capst      int RiskyTopMargin;      int RiskyBottomMargin;      int duplex; +    int have_jpeg; +    int have_png; +    int have_tiff; +    int have_pdf;  } caps_t; +typedef struct support +{ +    int min; +    int max; +    int normal; +    int step; +} support_t; +  typedef struct capabilities  {      caps_t caps[3]; @@ -141,6 +161,18 @@ typedef struct capabilities      long img_read;      size_t real_read;      SANE_Bool work; +    support_t *brightness; +    support_t *contrast; +    support_t *sharpen; +    support_t *threshold; +    int use_brightness; +    int val_brightness; +    int use_contrast; +    int val_contrast; +    int use_sharpen; +    int val_sharpen; +    int use_threshold; +    int val_threshold;  } capabilities_t;  typedef struct { @@ -162,8 +194,7 @@ enum      OPT_MODE_GROUP,      OPT_MODE,      OPT_RESOLUTION, -    OPT_PREVIEW, -    OPT_GRAY_PREVIEW, +    OPT_SCAN_SOURCE,      OPT_GEOMETRY_GROUP,      OPT_TL_X, @@ -171,7 +202,13 @@ enum      OPT_BR_X,      OPT_BR_Y, -    OPT_SCAN_SOURCE, +    OPT_ENHANCEMENT_GROUP, +    OPT_PREVIEW, +    OPT_GRAY_PREVIEW, +    OPT_BRIGHTNESS, +    OPT_CONTRAST, +    OPT_SHARPEN, +    OPT_THRESHOLD,      NUM_OPTIONS  }; @@ -180,35 +217,68 @@ enum  #define MM_TO_PIXEL(millimeters, dpi) (SANE_Word)round(SANE_UNFIX(millimeters) * (dpi) / 25.4)  ESCL_Device *escl_devices(SANE_Status *status); -SANE_Status escl_device_add(int port_nb, const char *model_name, -		            char *ip_address, char *type); +SANE_Status escl_device_add(int port_nb, +                            const char *model_name, +                            char *ip_address, +                            const char *is, +                            const char *uuid, +                            char *type); +  SANE_Status escl_status(const ESCL_Device *device,                          int source,                          const char* jobId,                          SANE_Status *job); -capabilities_t *escl_capabilities(const ESCL_Device *device, SANE_Status *status); -char *escl_newjob(capabilities_t *scanner, const ESCL_Device *device, -		  SANE_Status *status); -SANE_Status escl_scan(capabilities_t *scanner, const ESCL_Device *device, -	              char *result); -void escl_scanner(const ESCL_Device *device, char *result); + +capabilities_t *escl_capabilities(ESCL_Device *device, +                                  SANE_Status *status); + +char *escl_newjob(capabilities_t *scanner, +                  const ESCL_Device *device, +                  SANE_Status *status); + +SANE_Status escl_scan(capabilities_t *scanner, +                      const ESCL_Device *device, +                      char *result); + +void escl_scanner(const ESCL_Device *device, +                  char *result);  typedef void CURL; -void escl_curl_url(CURL *handle, const ESCL_Device *device, SANE_String_Const path); -unsigned char *escl_crop_surface(capabilities_t *scanner, unsigned char *surface, -	                      int w, int h, int bps, int *width, int *height); +void escl_curl_url(CURL *handle, +                   const ESCL_Device *device, +                   SANE_String_Const path); + +unsigned char *escl_crop_surface(capabilities_t *scanner, +                                 unsigned char *surface, +                                 int w, +                                 int h, +                                 int bps, +                                 int *width, +                                 int *height);  // JPEG -SANE_Status get_JPEG_data(capabilities_t *scanner, int *width, int *height, int *bps); +SANE_Status get_JPEG_data(capabilities_t *scanner, +                          int *width, +                          int *height, +                          int *bps);  // PNG -SANE_Status get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps); +SANE_Status get_PNG_data(capabilities_t *scanner, +                         int *width, +                         int *height, +                         int *bps);  // TIFF -SANE_Status get_TIFF_data(capabilities_t *scanner, int *width, int *height, int *bps); +SANE_Status get_TIFF_data(capabilities_t *scanner, +                          int *width, +                          int *height, +                          int *bps);  // PDF -SANE_Status get_PDF_data(capabilities_t *scanner, int *width, int *height, int *bps); +SANE_Status get_PDF_data(capabilities_t *scanner, +                         int *width, +                         int *height, +                         int *bps);  #endif diff --git a/backend/escl/escl_capabilities.c b/backend/escl/escl_capabilities.c index fdd5cfe..db194f9 100644 --- a/backend/escl/escl_capabilities.c +++ b/backend/escl/escl_capabilities.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -30,7 +30,6 @@  #include <stdlib.h>  #include <string.h> -#include <curl/curl.h>  #include <libxml/parser.h>  #include "../include/sane/saneopts.h" @@ -90,9 +89,9 @@ char_to_array(SANE_String_Const *tab, int *tabsize, SANE_String_Const mode, int      }      (*tabsize)++;      if (*tabsize == 1) -        board = (SANE_String_Const *)malloc(sizeof(SANE_String_Const) * (*tabsize) + 1); +        board = (SANE_String_Const *)malloc(sizeof(SANE_String_Const) * ((*tabsize) + 1));      else -        board = (SANE_String_Const *)realloc(tab, sizeof(SANE_String_Const) * (*tabsize) + 1); +        board = (SANE_String_Const *)realloc(tab, sizeof(SANE_String_Const) * ((*tabsize) + 1));      board[*tabsize - 1] = (SANE_String_Const)strdup(convert);      board[*tabsize] = NULL;      return (board); @@ -173,7 +172,7 @@ find_nodes_c(xmlNode *node)  /**   * \fn static int find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner) - * \brief Function that searchs in the xml file if a scanner capabilitie stocked + * \brief Function that searches in the xml file if a scanner capabilitie stocked   *        in one of the created array (character/integer array) is found.   *   * \return 0 @@ -194,32 +193,40 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner, int type)          int i = 0;          SANE_Bool have_jpeg = SANE_FALSE, have_png = SANE_FALSE, have_tiff = SANE_FALSE, have_pdf = SANE_FALSE;          scanner->caps[type].DocumentFormats = char_to_array(scanner->caps[type].DocumentFormats, &scanner->caps[type].DocumentFormatsSize, (SANE_String_Const)xmlNodeGetContent(node), 0); +	scanner->caps[type].have_jpeg = -1; +	scanner->caps[type].have_png = -1; +	scanner->caps[type].have_tiff = -1; +	scanner->caps[type].have_pdf = -1;          for(; i < scanner->caps[type].DocumentFormatsSize; i++)           {              if (!strcmp(scanner->caps[type].DocumentFormats[i], "image/jpeg"))              {  			   have_jpeg = SANE_TRUE; +			   scanner->caps[type].have_jpeg = i;              }  #if(defined HAVE_LIBPNG)              else if(!strcmp(scanner->caps[type].DocumentFormats[i], "image/png"))              {                 have_png = SANE_TRUE; +	       scanner->caps[type].have_png = i;              }  #endif  #if(defined HAVE_TIFFIO_H)              else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "image/tiff"))              {                 have_tiff = SANE_TRUE; +	       scanner->caps[type].have_tiff = i;              }  #endif  #if(defined HAVE_POPPLER_GLIB)              else if(type == PLATEN && !strcmp(scanner->caps[type].DocumentFormats[i], "application/pdf"))              {                 have_pdf = SANE_TRUE; +	       scanner->caps[type].have_pdf = i;              }  #endif           } -         if (have_pdf) +	 if (have_pdf)               scanner->caps[type].default_format = strdup("application/pdf");           else if (have_tiff)               scanner->caps[type].default_format = strdup("image/tiff"); @@ -239,7 +246,7 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner, int type)  /**   * \fn static int find_value_of_int_variables(xmlNode *node, capabilities_t *scanner) - * \brief Function that searchs in the xml file if a integer scanner capabilitie is found. + * \brief Function that searches in the xml file if a integer scanner capabilitie is found.   *        The integer scanner capabilities that are interesting are :   *        MinWidth, MaxWidth, MaxHeight, MinHeight, MaxScanRegions, MaxOpticalXResolution,   *        RiskyLeftMargin, RiskyRightMargin, RiskyTopMargin, RiskyBottomMargin. @@ -283,11 +290,74 @@ find_value_of_int_variables(xmlNode *node, capabilities_t *scanner, int type)      return (0);  } +static support_t* +print_support(xmlNode *node) +{ +    support_t *sup = (support_t*)calloc(1, sizeof(support_t)); +    int cpt = 0; +    int have_norm = 0; +    while (node) { +	if (!strcmp((const char *)node->name, "Min")){ +            sup->min = atoi((const char *)xmlNodeGetContent(node)); +            cpt++; +	} +	else if (!strcmp((const char *)node->name, "Max")) { +            sup->max = atoi((const char *)xmlNodeGetContent(node)); +            cpt++; +	} +	else if (!strcmp((const char *)node->name, "Normal")) { +            sup->normal = atoi((const char *)xmlNodeGetContent(node)); +            cpt++; +            have_norm = 1; +	} +	else if (!strcmp((const char *)node->name, "Step")) { +            sup->step = atoi((const char *)xmlNodeGetContent(node)); +            cpt++; +        } +        node = node->next; +    } +    if (cpt == 4) +        return sup; +    if (cpt == 3 && have_norm == 0) { +	sup->normal = (sup->max / 2 ); +        return sup; +    } +    free(sup); +    return NULL; +} + +static int +find_struct_variables(xmlNode *node, capabilities_t *scanner) +{ +    const char *name = (const char *)node->name; +    if (strcmp(name, "BrightnessSupport") == 0) { +        scanner->brightness = +           print_support(node->children); +        return 1; +    } +    else if (strcmp(name, "ContrastSupport") == 0) { +        scanner->contrast = +           print_support(node->children); +        return 1; +    } +    else if (strcmp(name, "SharpenSupport") == 0) { +        scanner->sharpen = +           print_support(node->children); +        return 1; +    } +    else if (strcmp(name, "ThresholdSupport") == 0) { +        scanner->threshold = +           print_support(node->children); +        return 1; +    } +    return (0); +} +  /**   * \fn static int find_true_variables(xmlNode *node, capabilities_t *scanner) - * \brief Function that searchs in the xml file if we find a scanner capabilitie stocked + * \brief Function that searches in the xml file if we find a scanner capability stored   *        in one of the created array (character/integer array), - *        or, if we find a integer scanner capabilitie. + *        or, if we find a integer scanner capability.   *   * \return 0   */ @@ -322,36 +392,39 @@ find_true_variables(xmlNode *node, capabilities_t *scanner, int type)   * \return 0   */  static int -print_xml_c(xmlNode *node, capabilities_t *scanner, int type) +print_xml_c(xmlNode *node, ESCL_Device *device, capabilities_t *scanner, int type)  {      while (node) {          if (node->type == XML_ELEMENT_NODE) {              if (find_nodes_c(node) && type != -1)                  find_true_variables(node, scanner, type);          } -	if (!strcmp((const char *)node->name, "PlatenInputCaps")) { +        if (!strcmp((const char *)node->name, "MakeAndModel")){ +            device->model_name = strdup((const char *)xmlNodeGetContent(node)); +	} +	else if (!strcmp((const char *)node->name, "PlatenInputCaps")) {             scanner->Sources[PLATEN] = (SANE_String_Const)strdup(SANE_I18N ("Flatbed"));             scanner->SourcesSize++;  	   scanner->source = PLATEN; -           print_xml_c(node->children, scanner, PLATEN); +           print_xml_c(node->children, device, scanner, PLATEN);  	   scanner->caps[PLATEN].duplex = 0;  	}  	else if (!strcmp((const char *)node->name, "AdfSimplexInputCaps")) {             scanner->Sources[ADFSIMPLEX] = (SANE_String_Const)strdup(SANE_I18N("ADF"));             scanner->SourcesSize++;  	   if (scanner->source == -1) scanner->source = ADFSIMPLEX; -           print_xml_c(node->children, scanner, ADFSIMPLEX); +           print_xml_c(node->children, device, scanner, ADFSIMPLEX);  	   scanner->caps[ADFSIMPLEX].duplex = 0;  	}  	else if (!strcmp((const char *)node->name, "AdfDuplexInputCaps")) {             scanner->Sources[ADFDUPLEX] = (SANE_String_Const)strdup(SANE_I18N ("ADF Duplex"));             scanner->SourcesSize++;  	   if (scanner->source == -1) scanner->source = ADFDUPLEX; -           print_xml_c(node->children, scanner, ADFDUPLEX); +           print_xml_c(node->children, device, scanner, ADFDUPLEX);  	   scanner->caps[ADFDUPLEX].duplex = 1;  	} -	else -           print_xml_c(node->children, scanner, type); +	else if (find_struct_variables(node, scanner) == 0) +           print_xml_c(node->children, device, scanner, type);          node = node->next;      }      return (0); @@ -390,7 +463,7 @@ _reduce_color_modes(capabilities_t *scanner)   * \return scanner (the structure that stocks all the capabilities elements)   */  capabilities_t * -escl_capabilities(const ESCL_Device *device, SANE_Status *status) +escl_capabilities(ESCL_Device *device, SANE_Status *status)  {      capabilities_t *scanner = (capabilities_t*)calloc(1, sizeof(capabilities_t));      CURL *curl_handle = NULL; @@ -434,7 +507,7 @@ escl_capabilities(const ESCL_Device *device, SANE_Status *status)      scanner->Sources = (SANE_String_Const *)malloc(sizeof(SANE_String_Const) * 4);      for (i = 0; i < 4; i++)         scanner->Sources[i] = NULL; -    print_xml_c(node, scanner, -1); +    print_xml_c(node, device, scanner, -1);      _reduce_color_modes(scanner);  clean:      xmlFreeDoc(data); diff --git a/backend/escl/escl_crop.c b/backend/escl/escl_crop.c index 8740d22..59284ac 100644 --- a/backend/escl/escl_crop.c +++ b/backend/escl/escl_crop.c @@ -15,8 +15,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ diff --git a/backend/escl/escl_devices.c b/backend/escl/escl_devices.c index 7ecbe31..3ca28de 100644 --- a/backend/escl/escl_devices.c +++ b/backend/escl/escl_devices.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -38,6 +38,7 @@  #include "../include/sane/sanei.h"  static AvahiSimplePoll *simple_poll = NULL; +static int count_finish = 0;  /**   * \fn static void resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED @@ -62,6 +63,9 @@ resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interfac                              void __sane_unused__ *userdata)  {      char a[AVAHI_ADDRESS_STR_MAX], *t; +    const char *is; +    const char *uuid; +    AvahiStringList   *s;      assert(r);      switch (event) {      case AVAHI_RESOLVER_FAILURE: @@ -69,8 +73,19 @@ resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interfac      case AVAHI_RESOLVER_FOUND:          avahi_address_snprint(a, sizeof(a), address);          t = avahi_string_list_to_string(txt); -        if (strstr(t, "\"rs=eSCL\"") || strstr(t, "\"rs=/eSCL\"")) -            escl_device_add(port, name, a, (char*)type); +        if (strstr(t, "\"rs=eSCL\"") || strstr(t, "\"rs=/eSCL\"")) { +	    s = avahi_string_list_find(txt, "is"); +	    if (s && s->size > 3) +	       is = (const char*)s->text + 3; +	    else +	       is = (const char*)NULL; +	    s = avahi_string_list_find(txt, "uuid"); +	    if (s && s->size > 5) +	       uuid = (const char*)s->text + 5; +	    else +	       uuid = (const char*)NULL; +            escl_device_add(port, name, a, is, uuid, (char*)type); +        }      }  } @@ -107,7 +122,11 @@ browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface,      case AVAHI_BROWSER_ALL_FOR_NOW:      case AVAHI_BROWSER_CACHE_EXHAUSTED:          if (event != AVAHI_BROWSER_CACHE_EXHAUSTED) -            avahi_simple_poll_quit(simple_poll); +           { +		count_finish++; +		if (count_finish == 2) +            		avahi_simple_poll_quit(simple_poll); +	   }          break;      }  } @@ -143,6 +162,8 @@ escl_devices(SANE_Status *status)      AvahiServiceBrowser *sb = NULL;      int error; +    count_finish = 0; +      *status = SANE_STATUS_GOOD;      if (!(simple_poll = avahi_simple_poll_new())) {          DBG( 1, "Failed to create simple poll object.\n"); diff --git a/backend/escl/escl_jpeg.c b/backend/escl/escl_jpeg.c index 8d6b6b6..651e7c5 100644 --- a/backend/escl/escl_jpeg.c +++ b/backend/escl/escl_jpeg.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ diff --git a/backend/escl/escl_mupdf.c b/backend/escl/escl_mupdf.c index 9399218..dd23482 100644 --- a/backend/escl/escl_mupdf.c +++ b/backend/escl/escl_mupdf.c @@ -15,8 +15,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ diff --git a/backend/escl/escl_newjob.c b/backend/escl/escl_newjob.c index ee8c03c..24bfbc9 100644 --- a/backend/escl/escl_newjob.c +++ b/backend/escl/escl_newjob.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -29,8 +29,7 @@  #include <stdio.h>  #include <stdlib.h>  #include <string.h> - -#include <curl/curl.h> +#include <unistd.h>  #ifdef PATH_MAX  # undef PATH_MAX @@ -38,12 +37,6 @@  #define PATH_MAX 4096 -struct uploading -{ -    const char *read_data; -    size_t size; -}; -  struct downloading  {      char *memory; @@ -71,6 +64,7 @@ static const char settings[] =      "   <pwg:InputSource>%s</pwg:InputSource>" \      "   <scan:InputSource>%s</scan:InputSource>" \      "%s" \ +    "%s" \      "</scan:ScanSettings>";  /** @@ -114,6 +108,15 @@ download_callback(void *str, size_t size, size_t nmemb, void *userp)      return (realsize);  } +static char* +add_support_option(char *key, int val) +{ +   int size = (strlen(key) * 3) +  10; +   char *tmp = (char*)calloc(1, size); +   snprintf (tmp, size, "<scan:%s>%d</scan:%s>\n", key, val, key); +   return tmp; +} +  /**   * \fn char *escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *status)   * \brief Function that, using curl, uploads the data (composed by the scanner capabilities) to the @@ -128,7 +131,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st  {      CURL *curl_handle = NULL;      int off_x = 0, off_y = 0; -    struct uploading *upload = NULL; +    struct downloading *upload = NULL;      struct downloading *download = NULL;      const char *scan_jobs = "/eSCL/ScanJobs";      char cap_data[PATH_MAX] = { 0 }; @@ -138,6 +141,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st      char *f_ext = "";      char *format_ext = NULL;      char duplex_mode[1024] = { 0 }; +    int wakup_count = 0;      *status = SANE_STATUS_GOOD;      if (device == NULL || scanner == NULL) { @@ -145,7 +149,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st          DBG( 1, "Create NewJob : the name or the scan are invalid.\n");          return (NULL);      } -    upload = (struct uploading *)calloc(1, sizeof(struct uploading)); +    upload = (struct downloading *)calloc(1, sizeof(struct downloading));      if (upload == NULL) {          *status = SANE_STATUS_NO_MEM;          DBG( 1, "Create NewJob : memory allocation failure\n"); @@ -158,7 +162,33 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st          *status = SANE_STATUS_NO_MEM;          return (NULL);      } -    curl_handle = curl_easy_init(); +    if (scanner->caps[scanner->source].default_format) +        free(scanner->caps[scanner->source].default_format); +    scanner->caps[scanner->source].default_format = NULL; +    int have_png = scanner->caps[scanner->source].have_png; +    int have_jpeg = scanner->caps[scanner->source].have_jpeg; +    int have_tiff = scanner->caps[scanner->source].have_tiff; +    int have_pdf = scanner->caps[scanner->source].have_pdf; + +    if ((scanner->source == PLATEN && have_pdf == -1) || +        (scanner->source > PLATEN)) { +	    if (have_tiff != -1) { +		    scanner->caps[scanner->source].default_format = +			    strdup(scanner->caps[scanner->source].DocumentFormats[have_tiff]); +	    } +	    else if (have_png != -1) { +		    scanner->caps[scanner->source].default_format = +			    strdup(scanner->caps[scanner->source].DocumentFormats[have_png]); +	    } +	    else if (have_jpeg != -1) { +		    scanner->caps[scanner->source].default_format = +			    strdup(scanner->caps[scanner->source].DocumentFormats[have_jpeg]); +	    } +    } +    else { +	    scanner->caps[scanner->source].default_format = +		    strdup(scanner->caps[scanner->source].DocumentFormats[have_pdf]); +    }      if (scanner->caps[scanner->source].format_ext == 1)      {          char f_ext_tmp[1024]; @@ -179,29 +209,71 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st           off_x = (scanner->caps[scanner->source].pos_x > scanner->caps[scanner->source].width) / 2;      if (scanner->caps[scanner->source].pos_y > scanner->caps[scanner->source].height)           off_y = (scanner->caps[scanner->source].pos_y > scanner->caps[scanner->source].height) / 2; + +    char support_options[1024]; +    memset(support_options, 0, 1024); +    char *source = (scanner->source == PLATEN ? "Platen" : "Feeder"); +    if (scanner->use_threshold) +    { +       char *tmp = add_support_option("ThresholdSupport", scanner->val_threshold); +       if (support_options[0]) +          strcat(support_options, tmp); +       else +          strcpy(support_options, tmp); +       free(tmp); +    } +    if (scanner->use_sharpen) +    { +       char *tmp = add_support_option("SharpenSupport", scanner->val_sharpen); +       if (support_options[0]) +          strcat(support_options, tmp); +       else +          strcpy(support_options, tmp); +       free(tmp); +    } +    if (scanner->use_contrast) +    { +       char *tmp = add_support_option("ContrastSupport", scanner->val_contrast); +       if (support_options[0]) +          strcat(support_options, tmp); +       else +          strcpy(support_options, tmp); +       free(tmp); +    } +    if (scanner->use_brightness) +    { +       char *tmp = add_support_option("BrightnessSupport", scanner->val_brightness); +       if (support_options[0]) +          strcat(support_options, tmp); +       else +          strcpy(support_options, tmp); +       free(tmp); +    } +    snprintf(cap_data, sizeof(cap_data), settings, +    		scanner->caps[scanner->source].height, +    		scanner->caps[scanner->source].width, +    		off_x, +    		off_y, +    		scanner->caps[scanner->source].default_format, +    		format_ext, +    		scanner->caps[scanner->source].default_color, +    		scanner->caps[scanner->source].default_resolution, +    		scanner->caps[scanner->source].default_resolution, +    		source, +    		source, +    		duplex_mode[0] == 0 ? " " : duplex_mode, +                support_options[0] == 0 ? " " : support_options); +    upload->memory = strdup(cap_data); +    upload->size = strlen(cap_data); +wake_up_device: +    DBG( 1, "Create NewJob : %s\n", cap_data); +    download->memory = malloc(1); +    download->size = 0; +    curl_handle = curl_easy_init();      if (curl_handle != NULL) { -		char *source = (scanner->source == PLATEN ? "Platen" : "Feeder"); -        snprintf(cap_data, sizeof(cap_data), settings, -			scanner->caps[scanner->source].height, -			scanner->caps[scanner->source].width, -			off_x, -			off_y, -			scanner->caps[scanner->source].default_format, -			format_ext, -			scanner->caps[scanner->source].default_color, -			scanner->caps[scanner->source].default_resolution, -			scanner->caps[scanner->source].default_resolution, -			source, -			source, -			duplex_mode[0] == 0 ? "" : duplex_mode); -        DBG( 1, "Create NewJob : %s\n", cap_data); -        upload->read_data = strdup(cap_data); -        upload->size = strlen(cap_data); -        download->memory = malloc(1); -        download->size = 0;          escl_curl_url(curl_handle, device, scan_jobs);          curl_easy_setopt(curl_handle, CURLOPT_POST, 1L); -        curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, upload->read_data); +        curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (const char*)upload->memory);          curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, upload->size);          curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, download_callback);          curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *)download); @@ -224,6 +296,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st                            result = strdup(location);                            DBG( 1, "Create NewJob : %s\n", result);                            *temporary = '\n'; +                          wakup_count = 0;                         }                      }                      if (result == NULL) { @@ -231,6 +304,7 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st                          *status = SANE_STATUS_INVAL;                      }                      free(download->memory); +                    download->memory = NULL;                  }                  else {                      DBG( 1, "Create NewJob : The creation of the failed job: %s\n", download->memory); @@ -238,8 +312,10 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st                      if (strstr(download->memory, "409 Conflict") != NULL)                          *status = SANE_STATUS_NO_DOCS;                      // If "503 Service Unavailable" appear, it means that device is busy (scanning in progress) -                    else if (strstr(download->memory, "503 Service Unavailable") != NULL) +                    else if (strstr(download->memory, "503 Service Unavailable") != NULL) { +                        wakup_count += 1;                          *status = SANE_STATUS_DEVICE_BUSY; +		    }                      else                          *status = SANE_STATUS_INVAL;                  } @@ -252,8 +328,18 @@ escl_newjob (capabilities_t *scanner, const ESCL_Device *device, SANE_Status *st          }          curl_easy_cleanup(curl_handle);      } -    if (upload != NULL) +    if (wakup_count > 0 && wakup_count < 4) { +        free(download->memory); +        download->memory = NULL; +        download->size = 0; +        *status = SANE_STATUS_GOOD; +        usleep(250); +        goto wake_up_device; +    } +    if (upload != NULL) { +        free(upload->memory);          free(upload); +    }      if (download != NULL)          free(download);      return (result); diff --git a/backend/escl/escl_pdf.c b/backend/escl/escl_pdf.c index ae85a3a..02dce66 100644 --- a/backend/escl/escl_pdf.c +++ b/backend/escl/escl_pdf.c @@ -15,8 +15,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -35,14 +35,14 @@  #include <errno.h> -#if(defined HAVE_POPPLER_GLIB) +#if HAVE_POPPLER_GLIB  #include <poppler/glib/poppler.h>  #endif  #include <setjmp.h> -#if(defined HAVE_POPPLER_GLIB) +#if HAVE_POPPLER_GLIB  #define INPUT_BUFFER_SIZE 4096 diff --git a/backend/escl/escl_png.c b/backend/escl/escl_png.c index cf92449..294ec00 100644 --- a/backend/escl/escl_png.c +++ b/backend/escl/escl_png.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -87,7 +87,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps)                  goto close_file;  	}  	// initialize the setjmp for returning properly after a libpng -	//   error occured +	//   error occurred  	if (setjmp (png_jmpbuf (png_ptr)))  	{  		png_destroy_read_struct (&png_ptr, &info_ptr, NULL); @@ -107,7 +107,7 @@ get_PNG_data(capabilities_t *scanner, int *width, int *height, int *bps)  	png_read_info (png_ptr, info_ptr);  	int bit_depth, color_type; -	// get some usefull information from header +	// get some useful information from header  	bit_depth = png_get_bit_depth (png_ptr, info_ptr);  	color_type = png_get_color_type (png_ptr, info_ptr);  	// convert index color images to RGB images diff --git a/backend/escl/escl_reset.c b/backend/escl/escl_reset.c index 64d779a..7494dda 100644 --- a/backend/escl/escl_reset.c +++ b/backend/escl/escl_reset.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -29,8 +29,6 @@  #include <stdlib.h>  #include <string.h> -#include <curl/curl.h> -  static size_t  write_callback(void __sane_unused__*str,                 size_t __sane_unused__ size, diff --git a/backend/escl/escl_scan.c b/backend/escl/escl_scan.c index 9fce801..53bd438 100644 --- a/backend/escl/escl_scan.c +++ b/backend/escl/escl_scan.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -30,15 +30,13 @@  #include <stdlib.h>  #include <string.h> -#include <curl/curl.h> -  #include "../include/sane/sanei.h"  /**   * \fn static size_t write_callback(void *str, size_t size, size_t nmemb, void *userp)   * \brief Callback function that writes the image scanned into the temporary file.   * - * \return to_write (the result of the fwrite fonction) + * \return to_write (the result of the fwrite function)   */  static size_t  write_callback(void *str, size_t size, size_t nmemb, void *userp) diff --git a/backend/escl/escl_status.c b/backend/escl/escl_status.c index 7b98566..a68f6ea 100644 --- a/backend/escl/escl_status.c +++ b/backend/escl/escl_status.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ @@ -30,7 +30,6 @@  #include <stdlib.h>  #include <string.h> -#include <curl/curl.h>  #include <libxml/parser.h>  struct idle diff --git a/backend/escl/escl_tiff.c b/backend/escl/escl_tiff.c index 98bc5f3..e33498c 100644 --- a/backend/escl/escl_tiff.c +++ b/backend/escl/escl_tiff.c @@ -16,8 +16,8 @@     for more details.     You should have received a copy of the GNU General Public License -   along with sane; see the file COPYING.  If not, write to the Free -   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +   along with sane; see the file COPYING. +   If not, see <https://www.gnu.org/licenses/>.     This file implements a SANE backend for eSCL scanners.  */ | 
