diff --git a/backend/escl/escl.c b/backend/escl/escl.c index 1d96a5eee..45f8873e0 100644 --- a/backend/escl/escl.c +++ b/backend/escl/escl.c @@ -1144,23 +1144,33 @@ sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len) } else { SANE_Status status = SANE_STATUS_EOF; + SANE_Status job = SANE_STATUS_UNSUPPORTED; *len = 0; free(handler->scanner->img_data); handler->scanner->img_data = NULL; if (handler->scanner->source != PLATEN) { + SANE_Bool next_page = SANE_FALSE; SANE_Status st = escl_status(handler->device, handler->scanner->source, - handler->result); + handler->result, + &job); DBG(10, "eSCL : command returned status %s\n", sane_strstatus(st)); - SANE_Bool next_page = - (SANE_STATUS_GOOD == st ? - SANE_TRUE : - SANE_FALSE); - handler->scanner->work = next_page; - handler->ps.last_frame = !next_page; - if (handler->ps.last_frame == SANE_TRUE) + // Thank's Alexander Pevzner (pzz@apevzner.com) + switch (st) { + case SANE_STATUS_GOOD: + case SANE_STATUS_UNSUPPORTED: + case SANE_STATUS_DEVICE_BUSY: + DBG(10, "eSCL : next page\n"); + if (job != SANE_STATUS_GOOD) + next_page = SANE_TRUE; + default: + break; + } + handler->scanner->work = next_page; + handler->ps.last_frame = !next_page; + if (handler->ps.last_frame == SANE_TRUE) status = SANE_STATUS_NO_DOCS; - else + else status = SANE_STATUS_EOF; } else diff --git a/backend/escl/escl.h b/backend/escl/escl.h index dca83228b..67a466c12 100644 --- a/backend/escl/escl.h +++ b/backend/escl/escl.h @@ -181,7 +181,10 @@ enum 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_status(const ESCL_Device *device, int source, char *jobid); +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); diff --git a/backend/escl/escl_reset.c b/backend/escl/escl_reset.c index 5d0a9588c..64d779a24 100644 --- a/backend/escl/escl_reset.c +++ b/backend/escl/escl_reset.c @@ -31,6 +31,15 @@ #include +static size_t +write_callback(void __sane_unused__*str, + size_t __sane_unused__ size, + size_t nmemb, + void __sane_unused__ *userp) +{ + return nmemb; +} + /** * \fn void escl_scanner(const ESCL_Device *device, char *result) * \brief Function that resets the scanner after each scan, using curl. @@ -54,13 +63,17 @@ CURL_CALL: snprintf(scan_cmd, sizeof(scan_cmd), "%s%s%s", scan_jobs, result, scanner_start); escl_curl_url(curl_handle, device, scan_cmd); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_callback); if (curl_easy_perform(curl_handle) == CURLE_OK) { curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &answer); i++; if (i >= 15) return; } curl_easy_cleanup(curl_handle); - if (SANE_STATUS_GOOD != escl_status(device, PLATEN, result)) + if (SANE_STATUS_GOOD != escl_status(device, + PLATEN, + NULL, + NULL)) goto CURL_CALL; } } diff --git a/backend/escl/escl_status.c b/backend/escl/escl_status.c index 9f44ab155..9f4347a63 100644 --- a/backend/escl/escl_status.c +++ b/backend/escl/escl_status.c @@ -85,8 +85,7 @@ find_nodes_s(xmlNode *node) static void print_xml_job_status(xmlNode *node, - SANE_Status *processing, - SANE_Status *complete, + SANE_Status *job, int *image) { while (node) { @@ -94,49 +93,33 @@ print_xml_job_status(xmlNode *node, if (find_nodes_s(node)) { if (strcmp((const char *)node->name, "JobState") == 0) { const char *state = (const char *)xmlNodeGetContent(node); - if (!strcmp(state, "Processing")) { - *processing = SANE_STATUS_GOOD; - } - if (!strcmp(state, "Completed")) { - *complete = SANE_STATUS_GOOD; - } - } - else if (strcmp((const char *)node->name, "ImagesToTransfer") == 0) { - const char *state = (const char *)xmlNodeGetContent(node); - *image = atoi(state); + if (!strcmp(state, "Processing")) { + *job = SANE_STATUS_DEVICE_BUSY; + DBG(10, "jobId Processing SANE_STATUS_DEVICE_BUSY\n"); + } + else if (!strcmp(state, "Completed")) { + *job = SANE_STATUS_GOOD; + DBG(10, "jobId Completed SANE_STATUS_GOOD\n"); + } + else if (strcmp((const char *)node->name, "ImagesToTransfer") == 0) { + const char *state = (const char *)xmlNodeGetContent(node); + *image = atoi(state); + } } } } - print_xml_job_status(node->children, processing, complete, image); + print_xml_job_status(node->children, job, image); node = node->next; } } static void -print_xml_feeder_status(xmlNode *node, - const char *job, - SANE_Status *processing, - SANE_Status *complete, - int *image) -{ - while (node) { - if (node->type == XML_ELEMENT_NODE) { - if (find_nodes_s(node)) { - if (strcmp((const char *)node->name, "JobUri") == 0) { - if (strstr((const char *)xmlNodeGetContent(node), job)) { - print_xml_job_status(node, processing, complete, image); - return; - } - } - } - } - print_xml_feeder_status(node->children, job, processing, complete, image); - node = node->next; - } -} - -static void -print_xml_platen_status(xmlNode *node, SANE_Status *status) +print_xml_platen_and_adf_status(xmlNode *node, + SANE_Status *platen, + SANE_Status *adf, + const char* jobId, + SANE_Status *job, + int *image) { while (node) { if (node->type == XML_ELEMENT_NODE) { @@ -145,19 +128,54 @@ print_xml_platen_status(xmlNode *node, SANE_Status *status) printf ("State\t"); const char *state = (const char *)xmlNodeGetContent(node); if (!strcmp(state, "Idle")) { - printf("Idle SANE_STATUS_GOOD\n"); - *status = SANE_STATUS_GOOD; + DBG(10, "Idle SANE_STATUS_GOOD\n"); + *platen = SANE_STATUS_GOOD; } else if (!strcmp(state, "Processing")) { - printf("Processing SANE_STATUS_DEVICE_BUSY\n"); - *status = SANE_STATUS_DEVICE_BUSY; + DBG(10, "Processing SANE_STATUS_DEVICE_BUSY\n"); + *platen = SANE_STATUS_DEVICE_BUSY; } else { - printf("%s SANE_STATUS_UNSUPPORTED\n", state); - *status = SANE_STATUS_UNSUPPORTED; + DBG(10, "%s SANE_STATUS_UNSUPPORTED\n", state); + *platen = SANE_STATUS_UNSUPPORTED; } } + // Thank's Alexander Pevzner (pzz@apevzner.com) + else if (adf && strcmp((const char *)node->name, "AdfState") == 0) { + const char *state = (const char *)xmlNodeGetContent(node); + if (!strcmp(state, "ScannerAdfLoaded")){ + DBG(10, "ScannerAdfLoaded SANE_STATUS_GOOD\n"); + *adf = SANE_STATUS_GOOD; + } else if (!strcmp(state, "ScannerAdfJam")) { + DBG(10, "ScannerAdfJam SANE_STATUS_JAMMED\n"); + *adf = SANE_STATUS_JAMMED; + } else if (!strcmp(state, "ScannerAdfDoorOpen")) { + DBG(10, "ScannerAdfDoorOpen SANE_STATUS_COVER_OPEN\n"); + *adf = SANE_STATUS_COVER_OPEN; + } else if (!strcmp(state, "ScannerAdfProcessing")) { + /* Kyocera version */ + DBG(10, "ScannerAdfProcessing SANE_STATUS_NO_DOC\n"); + *adf = SANE_STATUS_NO_DOCS; + } else if (!strcmp(state, "ScannerAdfEmpty")) { + DBG(10, "ScannerAdfEmpty SANE_STATUS_NO_DOCS\n"); + /* Cannon TR4500, EPSON XP-7100 */ + *adf = SANE_STATUS_NO_DOCS; + } else { + DBG(10, "%s SANE_STATUS_NO_DOCS\n", state); + *adf = SANE_STATUS_UNSUPPORTED; + } + } + else if (jobId && job && strcmp((const char *)node->name, "JobUri") == 0) { + if (strstr((const char *)xmlNodeGetContent(node), jobId)) { + print_xml_job_status(node, job, image); + } + } } } - print_xml_platen_status(node->children, status); + print_xml_platen_and_adf_status(node->children, + platen, + adf, + jobId, + job, + image); node = node->next; } } @@ -171,17 +189,28 @@ print_xml_platen_status(xmlNode *node, SANE_Status *status) * \return status (if everything is OK, status = SANE_STATUS_GOOD, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL) */ SANE_Status -escl_status(const ESCL_Device *device, int source, char *jobid) +escl_status(const ESCL_Device *device, + int source, + const char* jobId, + SANE_Status *job) { - SANE_Status status; + SANE_Status status = SANE_STATUS_DEVICE_BUSY; + SANE_Status platen= SANE_STATUS_DEVICE_BUSY; + SANE_Status adf= SANE_STATUS_DEVICE_BUSY; CURL *curl_handle = NULL; struct idle *var = NULL; xmlDoc *data = NULL; xmlNode *node = NULL; const char *scanner_status = "/eSCL/ScannerStatus"; + int image = -1; + int pass = 0; +reload: if (device == NULL) return (SANE_STATUS_NO_MEM); + status = SANE_STATUS_DEVICE_BUSY; + platen= SANE_STATUS_DEVICE_BUSY; + adf= SANE_STATUS_DEVICE_BUSY; var = (struct idle*)calloc(1, sizeof(struct idle)); if (var == NULL) return (SANE_STATUS_NO_MEM); @@ -209,23 +238,16 @@ escl_status(const ESCL_Device *device, int source, char *jobid) status = SANE_STATUS_NO_MEM; goto clean; } - status = SANE_STATUS_DEVICE_BUSY; /* Decode Job status */ - if (source == PLATEN) { - print_xml_platen_status(node, &status); + // Thank's Alexander Pevzner (pzz@apevzner.com) + print_xml_platen_and_adf_status(node, &platen, &adf, jobId, job, &image); + if (platen != SANE_STATUS_GOOD && + platen != SANE_STATUS_UNSUPPORTED) { + status = platen; + } else if (source == PLATEN) { + status = platen; } else { - SANE_Status processing = SANE_STATUS_UNSUPPORTED; - SANE_Status complete = SANE_STATUS_UNSUPPORTED; - int image = -1; - print_xml_feeder_status(node, jobid, &processing, &complete, &image); - if (processing == SANE_STATUS_GOOD && image == 0 && - complete == SANE_STATUS_UNSUPPORTED) - status = SANE_STATUS_EOF; - else if (complete == SANE_STATUS_GOOD && image == -1 && - processing == SANE_STATUS_UNSUPPORTED) - status = SANE_STATUS_EOF; - else - status = SANE_STATUS_GOOD; + status = adf; } DBG (10, "STATUS : %s\n", sane_strstatus(status)); clean: @@ -236,5 +258,14 @@ clean_data: curl_easy_cleanup(curl_handle); free(var->memory); free(var); + if (pass == 0 && + source != PLATEN && + image == 0 && + (status == SANE_STATUS_GOOD || + status == SANE_STATUS_UNSUPPORTED || + status == SANE_STATUS_DEVICE_BUSY)) { + pass = 1; + goto reload; + } return (status); }