diff --git a/backend/Makefile.am b/backend/Makefile.am index 2c47a5cc5..5455e7744 100644 --- a/backend/Makefile.am +++ b/backend/Makefile.am @@ -933,12 +933,12 @@ libpixma_la_SOURCES = pixma/pixma.c \ pixma/pixma_bjnp.h \ pixma/pixma_bjnp_private.h \ pixma/pixma_rename.h -libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma +libpixma_la_CPPFLAGS = $(AM_CPPFLAGS) $(XML_CFLAGS) -DBACKEND_NAME=pixma nodist_libsane_pixma_la_SOURCES = pixma-s.c libsane_pixma_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=pixma libsane_pixma_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) -libsane_pixma_la_LIBADD = $(COMMON_LIBS) libpixma.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS) +libsane_pixma_la_LIBADD = $(COMMON_LIBS) libpixma.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_thread.lo $(SANEI_SANEI_JPEG_LO) $(JPEG_LIBS) $(XML_LIBS) $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(SANEI_THREAD_LIBS) $(RESMGR_LIBS) EXTRA_DIST += pixma.conf.in # included in pixma.c EXTRA_DIST += pixma/pixma_sane_options.c pixma/pixma_sane_options.h diff --git a/backend/pixma/pixma_common.c b/backend/pixma/pixma_common.c index b164566fe..171df1a34 100644 --- a/backend/pixma/pixma_common.c +++ b/backend/pixma/pixma_common.c @@ -54,6 +54,12 @@ #include /* gettimeofday(4.3BSD) */ #include /* usleep */ +#if defined(HAVE_LIBXML2) +# include +#else +# error "The pixma backend requires libxml2" +#endif + #include "pixma_rename.h" #include "pixma_common.h" #include "pixma_io.h" @@ -1213,3 +1219,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 c0ed4bac0..ae4ceace9 100644 --- a/backend/pixma/pixma_common.h +++ b/backend/pixma/pixma_common.h @@ -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_mp150.c b/backend/pixma/pixma_mp150.c index 0263816c9..ce2c33b8c 100644 --- a/backend/pixma/pixma_mp150.c +++ b/backend/pixma/pixma_mp150.c @@ -323,8 +323,6 @@ 00000001\ " -#define XML_OK "OK" - enum mp150_state_t { state_idle, @@ -462,7 +460,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 diff --git a/backend/pixma/pixma_mp800.c b/backend/pixma/pixma_mp800.c index feef6112c..e050bc02d 100644 --- a/backend/pixma/pixma_mp800.c +++ b/backend/pixma/pixma_mp800.c @@ -153,8 +153,6 @@ 00000001\ " -#define XML_OK "OK" - enum mp810_state_t { state_idle, @@ -294,7 +292,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)