From 0004caad6fa50567c423f134c7c01f3e232a6932 Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Mon, 18 May 2020 13:43:57 +0200 Subject: [PATCH] Check driverless support and set device-info accordingly --- cupsfilters/ipp.c | 41 +++++++++++++++++++++++++++++++++++++++++ cupsfilters/ipp.h | 25 +++++++++++++++++++++++++ utils/driverless.c | 30 ++++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/cupsfilters/ipp.c b/cupsfilters/ipp.c index b9f7bebc5..aa3ae6cdc 100644 --- a/cupsfilters/ipp.c +++ b/cupsfilters/ipp.c @@ -73,6 +73,20 @@ resolve_uri(const char *raw_uri) } #ifdef HAVE_CUPS_1_6 +/* Check how the driverless support is provided */ +int +check_driverless_support(const char* uri) +{ + int support_status = DRVLESS_CHECKERR; + ipp_t *response = NULL; + + response = get_printer_attributes3(NULL, uri, NULL, 0, NULL, 0, 1, &support_status); + if (response != NULL) + ippDelete(response); + + return support_status; +} + /* Get attributes of a printer specified only by URI */ ipp_t * get_printer_attributes(const char* raw_uri, @@ -96,6 +110,23 @@ get_printer_attributes2(http_t *http_printer, const char* const req_attrs[], int req_attrs_size, int debug) +{ + return get_printer_attributes3(http_printer, raw_uri, pattrs, pattrs_size, + req_attrs, req_attrs_size, debug, NULL); +} + +/* Get attributes of a printer specified by URI and under a given HTTP + connection, for example via a domain socket, and give info about used + fallbacks */ +ipp_t * +get_printer_attributes3(http_t *http_printer, + const char* raw_uri, + const char* const pattrs[], + int pattrs_size, + const char* const req_attrs[], + int req_attrs_size, + int debug, + int* driverless_info) { const char *uri; int have_http, uri_status, host_port, i = 0, total_attrs = 0, fallback, @@ -139,6 +170,10 @@ get_printer_attributes2(http_t *http_printer, "uri-security-supported" }; + /* Expect a device capable of standard IPP Everywhere*/ + if (driverless_info != NULL) + *driverless_info = FULL_DRVLESS; + /* Request printer properties via IPP, for example to - generate a PPD file for the printer (mainly driverless-capable printers) @@ -282,12 +317,18 @@ get_printer_attributes2(http_t *http_printer, if (fallback == 1 + cap) { log_printf(get_printer_attributes_log, "No further fallback available, giving up\n"); + if (driverless_info != NULL) + *driverless_info = DRVLESS_CHECKERR; } else if (cap && fallback == 1) { log_printf(get_printer_attributes_log, "The server doesn't support the standard IPP request, trying request without media-col\n"); + if (driverless_info != NULL) + *driverless_info = DRVLESS_INCOMPLETEIPP; } else if (fallback == 0) { log_printf(get_printer_attributes_log, "The server doesn't support IPP2.0 request, trying IPP1.1 request\n"); + if (driverless_info != NULL) + *driverless_info = DRVLESS_IPP11; } } diff --git a/cupsfilters/ipp.h b/cupsfilters/ipp.h index 8e2bc9ec6..6d19b18ce 100644 --- a/cupsfilters/ipp.h +++ b/cupsfilters/ipp.h @@ -42,6 +42,23 @@ char get_printer_attributes_log[LOGSIZE]; const char *resolve_uri(const char *raw_uri); #ifdef HAVE_CUPS_1_6 + /* Enum of possible driverless options */ +enum driverless_support_modes { + DRVLESS_CHECKERR, /* Unable to get get-printer-attributes response*/ + FULL_DRVLESS, /* Standard IPP Everywhere support, works with 'everywhere' model */ + DRVLESS_IPP11, /* Driverless support via IPP 1.1 request */ + DRVLESS_INCOMPLETEIPP /* Driverless support without media-col-database attribute */ +}; + +/* Array of text strings explaining available driverless support */ +const char * driverless_support_strs[] = { + "driverless - cannot check driverless status", + "fully driverless", + "driverless via IPP 1.1", + "driverless with incomplete IPP request" +}; + +int check_driverless_support(const char* uri); ipp_t *get_printer_attributes(const char* raw_uri, const char* const pattrs[], int pattrs_size, @@ -55,6 +72,14 @@ ipp_t *get_printer_attributes2(http_t *http_printer, const char* const req_attrs[], int req_attrs_size, int debug); +ipp_t *get_printer_attributes3(http_t *http_printer, + const char* raw_uri, + const char* const pattrs[], + int pattrs_size, + const char* const req_attrs[], + int req_attrs_size, + int debug, + int* driverless_support); #endif /* HAVE_CUPS_1_6 */ # ifdef __cplusplus diff --git a/utils/driverless.c b/utils/driverless.c index 1bfab121b..4ec1f1d94 100644 --- a/utils/driverless.c +++ b/utils/driverless.c @@ -46,7 +46,8 @@ static void cancel_job(int sig); int list_printers (int mode) { - int ippfind_pid, /* Process ID for ippfind */ + int driverless_support = 0, /* Process ID for ippfind */ + ippfind_pid, /* Process ID of ippfind */ post_proc_pid = 0, /* Process ID of post-processing */ post_proc_pipe[2], /* Pipe to post-processing */ wait_children, /* Number of child processes left */ @@ -75,6 +76,7 @@ list_printers (int mode) make[512], /* Manufacturer */ model[256], /* Model */ pdl[256], /* PDL */ + driverless_info[256], /* Driverless info string */ device_id[2048]; /* 1284 device ID */ /* @@ -362,14 +364,34 @@ list_printers (int mode) else strncpy(make_and_model, model, sizeof(make_and_model) - 1); + /* Check which driverless support is available for the found device: + * 0) DRVLESS_CHECKERR - the device failed to respond + * to any get-printer-attributes request versions available. + * 1) FULL_DRVLESS - the device responded correctly to IPP 2.0 get-printer-attributes request. + * The device is compatible with CUPS 'everywhere' model. + * 2) DRVLESS_IPP11 - the device responded correctly to IPP 1.1 get-printer-attributes request. + * 3) DRVLESS_INCOMPLETEIPP - the device responded correctly to IPP get-printer-attributes request + * without media-col-database attribute + * + * If we know which driverless support is available, we can divide which devices can be supported + * by CUPS temporary queues and which devices need cups-browsed to run. + */ + driverless_support = check_driverless_support(service_uri); + + if (driverless_support == DRVLESS_CHECKERR) + fprintf(stderr, "Failed to get info about driverless support."); + + snprintf(driverless_info, 255, "%s", driverless_support_strs[driverless_support]); + driverless_info[255] = '\0'; + if (mode == 1) /* Call with "list" argument (PPD generator in list mode */ - printf("\"driverless:%s\" en \"%s\" \"%s, driverless, cups-filters " VERSION - "\" \"%s\"\n", service_uri, make, make_and_model, device_id); + printf("\"driverless:%s\" en \"%s\" \"%s, %s, cups-filters " VERSION + "\" \"%s\"\n", service_uri, make, make_and_model, driverless_info, device_id); else /* Call without arguments and env variable "SOFTWARE" starting with "CUPS" (Backend in discovery mode) */ - printf("network %s \"%s\" \"%s (driverless)\" \"%s\" \"\"\n", service_uri, make_and_model, make_and_model, device_id); + printf("network %s \"%s\" \"%s (%s)\" \"%s\" \"\"\n", service_uri, make_and_model, make_and_model, driverless_info, device_id); read_error: continue; -- 2.47.2