13bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
23bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Copyright (C) 2016 The Android Open Source Project
33bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Copyright (C) 2016 Mopria Alliance, Inc.
43bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
53bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
63bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Licensed under the Apache License, Version 2.0 (the "License");
73bf66744d61d18c66d46f2608de0467ad3df0268Mopria * you may not use this file except in compliance with the License.
83bf66744d61d18c66d46f2608de0467ad3df0268Mopria * You may obtain a copy of the License at
93bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
103bf66744d61d18c66d46f2608de0467ad3df0268Mopria *      http://www.apache.org/licenses/LICENSE-2.0
113bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
123bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Unless required by applicable law or agreed to in writing, software
133bf66744d61d18c66d46f2608de0467ad3df0268Mopria * distributed under the License is distributed on an "AS IS" BASIS,
143bf66744d61d18c66d46f2608de0467ad3df0268Mopria * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
153bf66744d61d18c66d46f2608de0467ad3df0268Mopria * See the License for the specific language governing permissions and
163bf66744d61d18c66d46f2608de0467ad3df0268Mopria * limitations under the License.
173bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
183bf66744d61d18c66d46f2608de0467ad3df0268Mopria
193bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "lib_wprint.h"
203bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "cups.h"
213bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "http-private.h"
223bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "ipphelper.h"
233bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "wprint_debug.h"
243bf66744d61d18c66d46f2608de0467ad3df0268Mopria
253bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "ipp_print.h"
263bf66744d61d18c66d46f2608de0467ad3df0268Mopria#include "../plugins/media.h"
273bf66744d61d18c66d46f2608de0467ad3df0268Mopria
283bf66744d61d18c66d46f2608de0467ad3df0268Mopria#define TAG "ipphelper"
293bf66744d61d18c66d46f2608de0467ad3df0268Mopria
303bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
313bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Get the IPP version of the given printer
323bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
333bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic status_t determine_ipp_version(char *, http_t *);
343bf66744d61d18c66d46f2608de0467ad3df0268Mopria
353bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
363bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Tests IPP versions and sets it to the latest working version
373bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
383bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic status_t test_and_set_ipp_version(char *, http_t *, int, int);
393bf66744d61d18c66d46f2608de0467ad3df0268Mopria
403bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
413bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Parses supported IPP versions from the IPP response and copies them into ippVersions
423bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
433bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic void parse_IPPVersions(ipp_t *response, ipp_version_supported_t *ippVersions);
443bf66744d61d18c66d46f2608de0467ad3df0268Mopria
453bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
463bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Parses printer URIs from the IPP response and copies them into capabilities
473bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
483bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic void parse_printerUris(ipp_t *response, printer_capabilities_t *capabilities);
493bf66744d61d18c66d46f2608de0467ad3df0268Mopria
503bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
513bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Known media sizes.
523bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
533bf66744d61d18c66d46f2608de0467ad3df0268Mopria * A note on rounding: In some cases the Android-specified width (in mils) is rounded down.
543bf66744d61d18c66d46f2608de0467ad3df0268Mopria * This causes artifacts in libjpeg-turbo when rendering to the correct width, so in these
553bf66744d61d18c66d46f2608de0467ad3df0268Mopria * cases we override with a rounded-up value.
563bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
573bf66744d61d18c66d46f2608de0467ad3df0268Mopriastruct MediaSizeTableElement SupportedMediaSizes[SUPPORTED_MEDIA_SIZE_COUNT] = {
583bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { US_LETTER, "LETTER", 8500, 11000, UNKNOWN_VALUE, UNKNOWN_VALUE, "na_letter_8.5x11in" },
593bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { US_LEGAL, "LEGAL", 8500, 14000, UNKNOWN_VALUE, UNKNOWN_VALUE, "na_legal_8.5x14in" },
603bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { LEDGER, "LEDGER", 11000, 17000, UNKNOWN_VALUE, UNKNOWN_VALUE, "na_ledger_11x17in" },
613bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { INDEX_CARD_5X7, "5X7", 5000, 7000, UNKNOWN_VALUE, UNKNOWN_VALUE, "na_5x7_5x7in" },
623bf66744d61d18c66d46f2608de0467ad3df0268Mopria
633bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Android system uses width of 11690
643bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { ISO_A3, "A3", 11694, 16540, 297, 420, "iso_a3_297x420mm" },
653bf66744d61d18c66d46f2608de0467ad3df0268Mopria
663bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Android system uses width of 8267
673bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { ISO_A4, "A4", 8268, 11692, 210, 297, "iso_a4_210x297mm" },
683bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { ISO_A5, "A5", 5830, 8270, 148, 210, "iso_a5_148x210mm" },
693bf66744d61d18c66d46f2608de0467ad3df0268Mopria
703bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Android system uses width of 10118
713bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { JIS_B4, "JIS B4", 10119, 14331, 257, 364, "jis_b4_257x364mm" },
723bf66744d61d18c66d46f2608de0467ad3df0268Mopria
733bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Android system uses width of 7165
743bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { JIS_B5, "JIS B5", 7167, 10118, 182, 257, "jis_b5_182x257mm" },
753bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { US_GOVERNMENT_LETTER, "8x10", 8000, 10000, UNKNOWN_VALUE, UNKNOWN_VALUE,
763bf66744d61d18c66d46f2608de0467ad3df0268Mopria        "na_govt-letter_8x10in" },
773bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { INDEX_CARD_4X6, "4x6", 4000, 6000, UNKNOWN_VALUE, UNKNOWN_VALUE, "na_index-4x6_4x6in" },
783bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { JPN_HAGAKI_PC, "JPOST", 3940, 5830, 100, 148, "jpn_hagaki_100x148mm" },
793bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { PHOTO_89X119, "89X119", 3504, 4685, 89, 119, "om_dsc-photo_89x119mm" },
803bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { CARD_54X86, "54X86", 2126, 3386, 54, 86, "om_card_54x86mm" },
813bf66744d61d18c66d46f2608de0467ad3df0268Mopria        { OE_PHOTO_L, "L", 3500, 5000, UNKNOWN_VALUE, UNKNOWN_VALUE, "oe_photo-l_3.5x5in" }
823bf66744d61d18c66d46f2608de0467ad3df0268Mopria};
833bf66744d61d18c66d46f2608de0467ad3df0268Mopria
843bf66744d61d18c66d46f2608de0467ad3df0268Mopriatypedef struct {
853bf66744d61d18c66d46f2608de0467ad3df0268Mopria    double Lower;
863bf66744d61d18c66d46f2608de0467ad3df0268Mopria    double Upper;
873bf66744d61d18c66d46f2608de0467ad3df0268Mopria} media_dimension_mm_t;
883bf66744d61d18c66d46f2608de0467ad3df0268Mopria
893bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic const char *__request_ipp_version[] = {"ipp-versions-supported"};
903bf66744d61d18c66d46f2608de0467ad3df0268Mopria
913bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic int __ipp_version_major = 2;
923bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic int __ipp_version_minor = 0;
933bf66744d61d18c66d46f2608de0467ad3df0268Mopria
943bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatus_t set_ipp_version(ipp_t *op_to_set, char *printer_uri, http_t *http,
953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ipp_version_state use_existing_version) {
963bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("set_ipp_version(): Enter %d", use_existing_version);
973bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (op_to_set == NULL) {
983bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return ERROR;
993bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1003bf66744d61d18c66d46f2608de0467ad3df0268Mopria    switch (use_existing_version) {
1013bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case NEW_REQUEST_SEQUENCE:
1023bf66744d61d18c66d46f2608de0467ad3df0268Mopria            __ipp_version_major = 2;
1033bf66744d61d18c66d46f2608de0467ad3df0268Mopria            __ipp_version_minor = 0;
1043bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
1053bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_VERSION_RESOLVED:
1063bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
1073bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_VERSION_UNSUPPORTED:
1083bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (determine_ipp_version(printer_uri, http) != 0) {
1093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                return ERROR;
1103bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
1113bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
1123bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1133bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ippSetVersion(op_to_set, __ipp_version_major, __ipp_version_minor);
1143bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("set_ipp_version(): Done");
1153bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return OK;
1163bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
1173bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1183bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic status_t determine_ipp_version(char *printer_uri, http_t *http) {
1193bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("determine_ipp_version(): Enter printer_uri =  %s", printer_uri);
1203bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1213bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (http == NULL) {
1223bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGE("determine_ipp_version(): http is NULL cannot continue");
1233bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return ERROR;
1243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1253bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((test_and_set_ipp_version(printer_uri, http, 1, 1) == OK)
1263bf66744d61d18c66d46f2608de0467ad3df0268Mopria            || (test_and_set_ipp_version(printer_uri, http, 1, 0) == OK)
1273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            || (test_and_set_ipp_version(printer_uri, http, 2, 0) == OK)) {
1283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("successfully set ipp version.");
1293bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
1303bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("could not get ipp version using any known ipp version.");
1313bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return ERROR;
1323bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
1333bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return OK;
1343bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
1353bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1363bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic status_t test_and_set_ipp_version(char *printer_uri, http_t *http, int major, int minor) {
1373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    status_t return_value = ERROR;
1383bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int service_unavailable_retry_count = 0;
1393bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int bad_request_retry_count = 0;
1403bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_t *request = NULL;
1413bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_t *response;
1423bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_version_supported_t ippVersions;
1433bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char http_resource[1024];
1443bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int op = IPP_GET_PRINTER_ATTRIBUTES;
1453bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1463bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("test_and_set_ipp_version(): Enter %d - %d", major, minor);
1473bf66744d61d18c66d46f2608de0467ad3df0268Mopria    memset(&ippVersions, 0, sizeof(ipp_version_supported_t));
1483bf66744d61d18c66d46f2608de0467ad3df0268Mopria    getResourceFromURI(printer_uri, http_resource, 1024);
1493bf66744d61d18c66d46f2608de0467ad3df0268Mopria    do {
1503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        request = ippNewRequest(op);
1513bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ippSetVersion(request, major, minor);
1523bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri);
1533bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes",
1543bf66744d61d18c66d46f2608de0467ad3df0268Mopria                sizeof(__request_ipp_version) / sizeof(__request_ipp_version[0]),
1553bf66744d61d18c66d46f2608de0467ad3df0268Mopria                NULL, __request_ipp_version);
1563bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if ((response = cupsDoRequest(http, request, http_resource)) == NULL) {
1573bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ipp_status_t ipp_status = cupsLastError();
1583bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("test_and_set_ipp_version:  response is null:  ipp_status %d %s",
1593bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ipp_status, ippErrorString(ipp_status));
1603bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ipp_status == IPP_INTERNAL_ERROR) {
1613bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("test_and_set_ipp_version: 1280 received, bailing...");
1623bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
1633bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if ((ipp_status == IPP_SERVICE_UNAVAILABLE) &&
1643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    (service_unavailable_retry_count < IPP_SERVICE_ERROR_MAX_RETRIES)) {
1653bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("test_and_set_ipp_version: 1282 received, retrying %d of %d",
1663bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        service_unavailable_retry_count, IPP_SERVICE_ERROR_MAX_RETRIES);
1673bf66744d61d18c66d46f2608de0467ad3df0268Mopria                service_unavailable_retry_count++;
1683bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
1693bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ipp_status == IPP_BAD_REQUEST) {
1703bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("test_and_set_ipp_version: IPP_Status of IPP_BAD_REQUEST "
1713bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        "received. retry (%d) of (%d)", bad_request_retry_count,
1723bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        IPP_BAD_REQUEST_MAX_RETRIES);
1733bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (bad_request_retry_count > IPP_BAD_REQUEST_MAX_RETRIES) {
1743bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    break;
1753bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
1763bf66744d61d18c66d46f2608de0467ad3df0268Mopria                bad_request_retry_count++;
1773bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
1783bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ipp_status == IPP_NOT_FOUND) {
1793bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("test_and_set_ipp_version: IPP_Status of IPP_NOT_FOUND received");
1803bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
1813bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
1823bf66744d61d18c66d46f2608de0467ad3df0268Mopria            return_value = ERROR;
1833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        } else {
1843bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ipp_status_t ipp_status = cupsLastError();
1853bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("ipp CUPS last ERROR: %d, %s", ipp_status, ippErrorString(ipp_status));
1863bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ipp_status == IPP_BAD_REQUEST) {
1873bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("IPP_Status of IPP_BAD_REQUEST received. retry (%d) of (%d)",
1883bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        bad_request_retry_count, IPP_BAD_REQUEST_MAX_RETRIES);
1893bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (bad_request_retry_count > IPP_BAD_REQUEST_MAX_RETRIES) {
1903bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    break;
1913bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
1923bf66744d61d18c66d46f2608de0467ad3df0268Mopria                bad_request_retry_count++;
1933bf66744d61d18c66d46f2608de0467ad3df0268Mopria                ippDelete(response);
1943bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
1953bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
1963bf66744d61d18c66d46f2608de0467ad3df0268Mopria
1973bf66744d61d18c66d46f2608de0467ad3df0268Mopria            parse_IPPVersions(response, &ippVersions);
1983bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ippVersions.supportsIpp20) {
1993bf66744d61d18c66d46f2608de0467ad3df0268Mopria                __ipp_version_major = 2;
2003bf66744d61d18c66d46f2608de0467ad3df0268Mopria                __ipp_version_minor = 0;
2013bf66744d61d18c66d46f2608de0467ad3df0268Mopria                return_value = OK;
2023bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("test_and_set_ipp_version(): ipp version set to %d,%d",
2033bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        __ipp_version_major, __ipp_version_minor);
2043bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ippVersions.supportsIpp11) {
2053bf66744d61d18c66d46f2608de0467ad3df0268Mopria                __ipp_version_major = 1;
2063bf66744d61d18c66d46f2608de0467ad3df0268Mopria                __ipp_version_minor = 1;
2073bf66744d61d18c66d46f2608de0467ad3df0268Mopria                return_value = OK;
2083bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("test_and_set_ipp_version(): ipp version set to %d,%d",
2093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        __ipp_version_major, __ipp_version_minor);
2103bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ippVersions.supportsIpp10) {
2113bf66744d61d18c66d46f2608de0467ad3df0268Mopria                __ipp_version_major = 1;
2123bf66744d61d18c66d46f2608de0467ad3df0268Mopria                __ipp_version_minor = 0;
2133bf66744d61d18c66d46f2608de0467ad3df0268Mopria                return_value = OK;
2143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("test_and_set_ipp_version(): ipp version set to %d,%d",
2153bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        __ipp_version_major, __ipp_version_minor);
2163bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else {
2173bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("test_and_set_ipp_version: ipp version not found");
2183bf66744d61d18c66d46f2608de0467ad3df0268Mopria                return_value = ERROR;
2193bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
2203bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
2213bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (response != NULL) ippDelete(response);
2223bf66744d61d18c66d46f2608de0467ad3df0268Mopria        break;
2233bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } while (1);
2243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return return_value;
2253bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
2263bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2273bf66744d61d18c66d46f2608de0467ad3df0268Mopriaipp_status_t get_PrinterState(http_t *http, char *printer_uri,
2283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn_t *printer_state_dyn, ipp_pstate_t *printer_state) {
2293bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("get_PrinterState(): Enter");
2303bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2313bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Requested printer attributes
2323bf66744d61d18c66d46f2608de0467ad3df0268Mopria    static const char *pattrs[] = {"printer-make-and-model", "printer-state",
2333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            "printer-state-message", "printer-state-reasons"};
2343bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2353bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_t *request = NULL;
2363bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_t *response = NULL;
2373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_status_t ipp_status = IPP_OK;
2383bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int op = IPP_GET_PRINTER_ATTRIBUTES;
2393bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char http_resource[1024];
2403bf66744d61d18c66d46f2608de0467ad3df0268Mopria    getResourceFromURI(printer_uri, http_resource, 1024);
2413bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2423bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (printer_state_dyn == NULL) {
2433bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGE("get_PrinterState(): printer_state_dyn is null");
2443bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return ipp_status;
2453bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
2463bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2473bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (printer_state) {
2483bf66744d61d18c66d46f2608de0467ad3df0268Mopria        *printer_state = IPP_PRINTER_STOPPED;
2493bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
2503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGE("get_PrinterState(): printer_state is null");
2513bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
2523bf66744d61d18c66d46f2608de0467ad3df0268Mopria    request = ippNewRequest(op);
2533bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2543bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri);
2553bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2563bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes",
2573bf66744d61d18c66d46f2608de0467ad3df0268Mopria            sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
2583bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((response = ipp_doCupsRequest(http, request, http_resource, printer_uri)) == NULL) {
2603bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ipp_status = cupsLastError();
2613bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGE("get_PrinterState(): response is null: ipp_status %d", ipp_status);
2623bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn->printer_status = PRINT_STATUS_UNABLE_TO_CONNECT;
2633bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn->printer_reasons[0] = PRINT_STATUS_UNABLE_TO_CONNECT;
2643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
2653bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ipp_status = cupsLastError();
2663bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("ipp CUPS last ERROR: %d, %s", ipp_status, ippErrorString(ipp_status));
2673bf66744d61d18c66d46f2608de0467ad3df0268Mopria        get_PrinterStateReason(response, printer_state, printer_state_dyn);
2683bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("get_PrinterState(): printer_state_dyn->printer_status: %d",
2693bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_status);
2703bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
2713bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("get_PrinterState(): exit http->fd %d, ipp_status %d, printer_state %d", http->fd,
2723bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ipp_status, printer_state_dyn->printer_status);
2733bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2743bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ippDelete(request);
2753bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ippDelete(response);
2763bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return ipp_status;
2773bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
2783bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2793bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid get_PrinterStateReason(ipp_t *response, ipp_pstate_t *printer_state,
2803bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn_t *printer_state_dyn) {
2813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("get_PrinterStateReason(): Enter");
2823bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_attribute_t *attrptr;
2833bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int reason_idx = 0;
2843bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int idx = 0;
2853bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_pstate_t printer_ippstate = IPP_PRINTER_IDLE;
2863bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2873bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) == NULL) {
2883bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGE("get_PrinterStateReason printer-state null");
2893bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn->printer_status = PRINT_STATUS_UNABLE_TO_CONNECT;
2903bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn->printer_reasons[0] = PRINT_STATUS_UNABLE_TO_CONNECT;
2913bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
2923bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_ippstate = (ipp_pstate_t) ippGetInteger(attrptr, 0);
2933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        *printer_state = printer_ippstate;
2943bf66744d61d18c66d46f2608de0467ad3df0268Mopria
2953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("get_PrinterStateReason printer-state: %d", printer_ippstate);
2963bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // set the printer_status; they may be modified based on the status reasons below.
2973bf66744d61d18c66d46f2608de0467ad3df0268Mopria        switch (printer_ippstate) {
2983bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_PRINTER_IDLE:
2993bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_status = PRINT_STATUS_IDLE;
3003bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
3013bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_PRINTER_PROCESSING:
3023bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_status = PRINT_STATUS_PRINTING;
3033bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
3043bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_PRINTER_STOPPED:
3053bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_status = PRINT_STATUS_SVC_REQUEST;
3063bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
3073bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
3083bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
3093bf66744d61d18c66d46f2608de0467ad3df0268Mopria
3103bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-state-reasons", IPP_TAG_KEYWORD)) == NULL) {
3113bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGE(" get_PrinterStateReason printer-state reason null");
3123bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn->printer_status = PRINT_STATUS_UNABLE_TO_CONNECT;
3133bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_state_dyn->printer_reasons[0] = PRINT_STATUS_UNABLE_TO_CONNECT;
3143bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
3153bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (idx = 0; idx < ippGetCount(attrptr); idx++) {
3163bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // Per RFC2911 any of these can have -error, -warning, or -report appended to end
3173bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("get_PrinterStateReason printer-state-reason: %s",
3183bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ippGetString(attrptr, idx, NULL));
3193bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_NONE,
3203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strlen(IPP_PRNT_STATE_NONE)) == 0) {
3213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                switch (printer_ippstate) {
3223bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    case IPP_PRINTER_IDLE:
3233bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_IDLE;
3243bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        break;
3253bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    case IPP_PRINTER_PROCESSING:
3263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_PRINTING;
3273bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        break;
3283bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    case IPP_PRINTER_STOPPED:
3293bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        // should this be PRINT_STATUS_SVC_REQUEST
3303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_UNKNOWN;
3313bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        break;
3323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
3333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_SPOOL_FULL,
3343bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strlen(IPP_PRNT_STATE_SPOOL_FULL)) == 0) {
3353bf66744d61d18c66d46f2608de0467ad3df0268Mopria                switch (printer_ippstate) {
3363bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    case IPP_PRINTER_IDLE:
3373bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_UNKNOWN;
3383bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        break;
3393bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    case IPP_PRINTER_PROCESSING:
3403bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_PRINTING;
3413bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        break;
3423bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    case IPP_PRINTER_STOPPED:
3433bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        // should this be PRINT_STATUS_SVC_REQUEST
3443bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_UNKNOWN;
3453bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        break;
3463bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
3473bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_MARKER_SUPPLY_LOW,
3483bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strlen(IPP_PRNT_STATE_MARKER_SUPPLY_LOW)) == 0) {
3493bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_LOW_ON_INK;
3503bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_TONER_LOW,
3513bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strlen(IPP_PRNT_STATE_TONER_LOW)) == 0) {
3523bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_LOW_ON_TONER;
3533bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_OTHER_WARN,
3543bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strlen(IPP_PRNT_STATE_OTHER_WARN)) == 0) {
3553bf66744d61d18c66d46f2608de0467ad3df0268Mopria                printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_UNKNOWN;
3563bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else {
3573bf66744d61d18c66d46f2608de0467ad3df0268Mopria                // check blocking cases
3583bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_MEDIA_NEEDED,
3593bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_MEDIA_NEEDED)) == 0) {
3603bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_OUT_OF_PAPER;
3613bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_MEDIA_EMPTY,
3623bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_MEDIA_EMPTY)) == 0) {
3633bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_OUT_OF_PAPER;
3643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_TONER_EMPTY,
3653bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_TONER_EMPTY)) == 0) {
3663bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_OUT_OF_TONER;
3673bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL),
3683bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        IPP_PRNT_STATE_MARKER_SUPPLY_EMPTY,
3693bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_MARKER_SUPPLY_EMPTY)) == 0) {
3703bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_OUT_OF_INK;
3713bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_DOOR_OPEN,
3723bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_DOOR_OPEN)) == 0) {
3733bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_DOOR_OPEN;
3743bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_COVER_OPEN,
3753bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_COVER_OPEN)) == 0) {
3763bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_DOOR_OPEN;
3773bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_MEDIA_JAM,
3783bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_MEDIA_JAM)) == 0) {
3793bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_JAMMED;
3803bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_SHUTDOWN,
3813bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_SHUTDOWN)) == 0) {
3823bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_SHUTTING_DOWN;
3833bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_STATE_OTHER_ERR,
3843bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_STATE_OTHER_ERR)) == 0) {
3853bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_SVC_REQUEST;
3863bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strncmp(ippGetString(attrptr, idx, NULL), IPP_PRNT_PAUSED,
3873bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strlen(IPP_PRNT_PAUSED)) == 0) {
3883bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    printer_state_dyn->printer_reasons[reason_idx++] = PRINT_STATUS_UNKNOWN;
3893bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
3903bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
3913bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }  // end of reasons loop
3923bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
3933bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
3943bf66744d61d18c66d46f2608de0467ad3df0268Mopria
3953bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic void print_col(ipp_t *col) {
3963bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
3973bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_attribute_t *attr;
3983bf66744d61d18c66d46f2608de0467ad3df0268Mopria
3993bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("{");
4003bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (attr = ippFirstAttribute(col); attr; attr = ippNextAttribute(col)) {
4013bf66744d61d18c66d46f2608de0467ad3df0268Mopria        switch (ippGetValueTag(attr)) {
4023bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_INTEGER:
4033bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_ENUM:
4043bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4053bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("  %s(%s%s)= %d ", ippGetName(attr),
4063bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
4073bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)), ippGetInteger(attr, i));
4083bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4103bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_BOOLEAN:
4113bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4123bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    if (ippGetBoolean(attr, i)) {
4133bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        LOGD("  %s(%s%s)= true ", ippGetName(attr),
4143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                ippGetCount(attr) > 1 ? "1setOf " : "",
4153bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                ippTagString(ippGetValueTag(attr)));
4163bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    } else {
4173bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        LOGD("  %s(%s%s)= false ", ippGetName(attr),
4183bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                ippGetCount(attr) > 1 ? "1setOf " : "",
4193bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                ippTagString(ippGetValueTag(attr)));
4203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    }
4213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4223bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4233bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_NOVALUE:
4243bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("  %s(%s%s)= novalue", ippGetName(attr),
4253bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)));
4263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_RANGE:
4283bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4293bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    int lower, upper;
4303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    lower = ippGetRange(attr, i, &upper);
4313bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("  %s(%s%s)= %d-%d ", ippGetName(attr),
4323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
4333bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)), lower, upper);
4343bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4353bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4363bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_RESOLUTION:
4373bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4383bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ipp_res_t units;
4393bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    int xres, yres;
4403bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    xres = ippGetResolution(attr, i, &yres, &units);
4413bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("  %s(%s%s)= %dx%d%s ", ippGetName(attr),
4423bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
4433bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)), xres, yres,
4443bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            units == IPP_RES_PER_INCH ? "dpi" : "dpc");
4453bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4463bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4473bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_STRING:
4483bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_TEXT:
4493bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_NAME:
4503bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_KEYWORD:
4513bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_CHARSET:
4523bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_URI:
4533bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_MIMETYPE:
4543bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_LANGUAGE:
4553bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4563bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("  %s(%s%s)= \"%s\" ", ippGetName(attr),
4573bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
4583bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)), ippGetString(attr, i, NULL));
4593bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4603bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4613bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_TEXTLANG:
4623bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_NAMELANG:
4633bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    const char *charset;
4653bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    const char *text;
4663bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    text = ippGetString(attr, i, &charset);
4673bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("  %s(%s%s)= \"%s\",%s ", ippGetName(attr),
4683bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
4693bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)), text, charset);
4703bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4713bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4723bf66744d61d18c66d46f2608de0467ad3df0268Mopria            case IPP_TAG_BEGIN_COLLECTION:
4733bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < ippGetCount(attr); i++) {
4743bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    print_col(ippGetCollection(attr, i));
4753bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
4763bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4773bf66744d61d18c66d46f2608de0467ad3df0268Mopria            default:
4783bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
4793bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
4803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
4813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("}");
4823bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
4833bf66744d61d18c66d46f2608de0467ad3df0268Mopria
4843bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid print_attr(ipp_attribute_t *attr) {
4853bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
4863bf66744d61d18c66d46f2608de0467ad3df0268Mopria
4873bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (ippGetName(attr) == NULL) {
4883bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return;
4893bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
4903bf66744d61d18c66d46f2608de0467ad3df0268Mopria
4913bf66744d61d18c66d46f2608de0467ad3df0268Mopria    switch (ippGetValueTag(attr)) {
4923bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_INTEGER:
4933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_ENUM:
4943bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
4953bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("%s (%s%s) = %d ", ippGetName(attr), ippGetCount(attr) > 1 ? "1setOf " : "",
4963bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippTagString(ippGetValueTag(attr)), ippGetInteger(attr, i));
4973bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
4983bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
4993bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_BOOLEAN:
5003bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
5013bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (ippGetBoolean(attr, i)) {
5023bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("%s (%s%s) = true ", ippGetName(attr),
5033bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
5043bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)));
5053bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else {
5063bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("%s (%s%s) = false ", ippGetName(attr),
5073bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippGetCount(attr) > 1 ? "1setOf " : "",
5083bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            ippTagString(ippGetValueTag(attr)));
5093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
5103bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
5113bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5123bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_NOVALUE:
5133bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("%s (%s%s) = novalue", ippGetName(attr),
5143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)));
5153bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5163bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_RANGE:
5173bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
5183bf66744d61d18c66d46f2608de0467ad3df0268Mopria                int lower, upper;
5193bf66744d61d18c66d46f2608de0467ad3df0268Mopria                lower = ippGetRange(attr, i, &upper);
5203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("%s (%s%s) = %d-%d ", ippGetName(attr), ippGetCount(attr) > 1 ? "1setOf " : "",
5213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippTagString(ippGetValueTag(attr)), lower, upper);
5223bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
5233bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5243bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_RESOLUTION:
5253bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
5263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                ipp_res_t units;
5273bf66744d61d18c66d46f2608de0467ad3df0268Mopria                int xres, yres;
5283bf66744d61d18c66d46f2608de0467ad3df0268Mopria                xres = ippGetResolution(attr, i, &yres, &units);
5293bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("%s (%s%s) = %dx%d%s ", ippGetName(attr),
5303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetCount(attr) > 1 ? "1setOf " : "",
5313bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippTagString(ippGetValueTag(attr)), xres, yres,
5323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        units == IPP_RES_PER_INCH ? "dpi" : "dpc");
5333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
5343bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5353bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_STRING:
5363bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_TEXT:
5373bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_NAME:
5383bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_KEYWORD:
5393bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_CHARSET:
5403bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_URI:
5413bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_MIMETYPE:
5423bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_LANGUAGE:
5433bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
5443bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("%s (%s%s) = \"%s\" ", ippGetName(attr),
5453bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetCount(attr) > 1 ? "1setOf " : "",
5463bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippTagString(ippGetValueTag(attr)), ippGetString(attr, i, NULL));
5473bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
5483bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5493bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_TEXTLANG:
5503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_NAMELANG:
5513bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
5523bf66744d61d18c66d46f2608de0467ad3df0268Mopria                const char *charset;
5533bf66744d61d18c66d46f2608de0467ad3df0268Mopria                const char *text;
5543bf66744d61d18c66d46f2608de0467ad3df0268Mopria                text = ippGetString(attr, i, &charset);
5553bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("%s (%s%s) = \"%s\",%s ", ippGetName(attr),
5563bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetCount(attr) > 1 ? "1setOf " : "",
5573bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippTagString(ippGetValueTag(attr)), text, charset);
5583bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
5593bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5603bf66744d61d18c66d46f2608de0467ad3df0268Mopria
5613bf66744d61d18c66d46f2608de0467ad3df0268Mopria        case IPP_TAG_BEGIN_COLLECTION:
5623bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attr); i++) {
5633bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("%s (%s%s): IPP_TAG_BEGIN_COLLECTION", ippGetName(attr),
5643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)));
5653bf66744d61d18c66d46f2608de0467ad3df0268Mopria                print_col(ippGetCollection(attr, i));
5663bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
5673bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("%s (%s%s): IPP_TAG_END_COLLECTION", ippGetName(attr),
5683bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)));
5693bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5703bf66744d61d18c66d46f2608de0467ad3df0268Mopria
5713bf66744d61d18c66d46f2608de0467ad3df0268Mopria        default:
5723bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
5733bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
5743bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
5753bf66744d61d18c66d46f2608de0467ad3df0268Mopria
5763bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid parse_IPPVersions(ipp_t *response, ipp_version_supported_t *ippVersions) {
5773bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
5783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_attribute_t *attrptr;
5793bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char ipp10[] = "1.0";
5803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char ipp11[] = "1.1";
5813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char ipp20[] = "2.0";
5823bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD(" Entered IPPVersions");
5833bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (ippVersions != NULL) {
5843bf66744d61d18c66d46f2608de0467ad3df0268Mopria        memset(ippVersions, 0, sizeof(ipp_version_supported_t));
5853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD(" in get_supportedIPPVersions");
5863bf66744d61d18c66d46f2608de0467ad3df0268Mopria        attrptr = ippFindAttribute(response, "ipp-versions-supported", IPP_TAG_KEYWORD);
5873bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (attrptr != NULL) {
5883bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD(" in get_supportedIPPVersions: %d", ippGetCount(attrptr));
5893bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (i = 0; i < ippGetCount(attrptr); i++) {
5903bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (strcmp(ipp10, ippGetString(attrptr, i, NULL)) == 0) {
5913bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ippVersions->supportsIpp10 = 1;
5923bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strcmp(ipp11, ippGetString(attrptr, i, NULL)) == 0) {
5933bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ippVersions->supportsIpp11 = 1;
5943bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strcmp(ipp20, ippGetString(attrptr, i, NULL)) == 0) {
5953bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    ippVersions->supportsIpp20 = 1;
5963bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else {
5973bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("found another ipp version. %s", ippGetString(attrptr, i, NULL));
5983bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
5993bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
6003bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
6013bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6023bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
6033bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6043bf66744d61d18c66d46f2608de0467ad3df0268Mopriaconst char *mapDFMediaToIPPKeyword(media_size_t media_size) {
6053bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
6063bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
6073bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (SupportedMediaSizes[i].media_size == (media_size_t) media_size) {
6083bf66744d61d18c66d46f2608de0467ad3df0268Mopria            return (SupportedMediaSizes[i].PWGName);
6093bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
6103bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6113bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return (SupportedMediaSizes[0].PWGName);
6123bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
6133bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6143bf66744d61d18c66d46f2608de0467ad3df0268Mopriaint ipp_find_media_size(const char *ipp_media_keyword, media_size_t *media_size) {
6153bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
6163bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("ipp_find_media_size entry is %s", ipp_media_keyword);
6173bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
6183bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (strcmp(SupportedMediaSizes[i].PWGName, ipp_media_keyword) == 0) {
6193bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD(" mediaArraySize: match string  %s  PT_size: %d",
6203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    SupportedMediaSizes[i].PWGName, SupportedMediaSizes[i].media_size);
6213bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
6223bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
6233bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (i < SUPPORTED_MEDIA_SIZE_COUNT) {
6253bf66744d61d18c66d46f2608de0467ad3df0268Mopria        *media_size = SupportedMediaSizes[i].media_size;
6263bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return i;
6273bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
6283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return -1;
6293bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6303bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return -1;
6313bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
6323bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6333bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
6343bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Return a freshly allocated string copied from another string
6353bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
6363bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic char *substring(const char *string, int position, int length) {
6373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *pointer;
6383bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int c;
6393bf66744d61d18c66d46f2608de0467ad3df0268Mopria    pointer = malloc(length + 1);
6403bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (pointer == NULL) {
6413bf66744d61d18c66d46f2608de0467ad3df0268Mopria        exit(EXIT_FAILURE);
6423bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6433bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6443bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (c = 0; c < position - 1; c++) {
6453bf66744d61d18c66d46f2608de0467ad3df0268Mopria        string++;
6463bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6473bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6483bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (c = 0; c < length; c++) {
6493bf66744d61d18c66d46f2608de0467ad3df0268Mopria        *(pointer + c) = *string;
6503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        string++;
6513bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6523bf66744d61d18c66d46f2608de0467ad3df0268Mopria    *(pointer + c) = '\0';
6533bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return pointer;
6543bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
6553bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6563bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
6573bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Parse and IPP media size and return dimensions in millimeters.
6583bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Format is region_name_#x#<unit> or format is custom_(min\max)_#x#<unit>
6593bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
6603bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic int getMediaDimensions_mm(const char *mediaSize, media_dimension_mm_t *media_dimensions) {
6613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *tempMediaSize = NULL;
6623bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *um;
6633bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *buf = NULL; // custom
6643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *dim = NULL; // min
6653bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *upper = NULL; // 8.5
6663bf66744d61d18c66d46f2608de0467ad3df0268Mopria    const char t[2] = "_";
6673bf66744d61d18c66d46f2608de0467ad3df0268Mopria    const char x[2] = "x";
6683bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char in[3] = "in";
6693bf66744d61d18c66d46f2608de0467ad3df0268Mopria    double inch_to_mm = 25.4;
6703bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6713bf66744d61d18c66d46f2608de0467ad3df0268Mopria    tempMediaSize = malloc(strlen(mediaSize) + 1);
6723bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (tempMediaSize == NULL) {
6733bf66744d61d18c66d46f2608de0467ad3df0268Mopria        exit(EXIT_FAILURE);
6743bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6753bf66744d61d18c66d46f2608de0467ad3df0268Mopria    strcpy(tempMediaSize, mediaSize);
6763bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("getMediaDimensions_mm Start media:%s", tempMediaSize);
6773bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    um = substring(mediaSize, strlen(tempMediaSize) - 1, 2);
6793bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("getMediaDimensions um=%s", um);
6803bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // fill in buf with what we need to work with
6823bf66744d61d18c66d46f2608de0467ad3df0268Mopria    buf = strtok(tempMediaSize, t); // custom
6833bf66744d61d18c66d46f2608de0467ad3df0268Mopria    while (buf != NULL) {
6843bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (dim != NULL) {
6853bf66744d61d18c66d46f2608de0467ad3df0268Mopria            free(dim);
6863bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
6873bf66744d61d18c66d46f2608de0467ad3df0268Mopria        dim = malloc(strlen(buf) + 1);
6883bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (dim == NULL) {
6893bf66744d61d18c66d46f2608de0467ad3df0268Mopria            exit(EXIT_FAILURE);
6903bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
6913bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strcpy(dim, buf);
6923bf66744d61d18c66d46f2608de0467ad3df0268Mopria        buf = strtok(NULL, t);
6933bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
6943bf66744d61d18c66d46f2608de0467ad3df0268Mopria
6953bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (dim != NULL) {
6963bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("getMediaDimensions part2=%s", dim);
6973bf66744d61d18c66d46f2608de0467ad3df0268Mopria        media_dimensions->Lower = atof(strtok(dim, x));
6983bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("getMediaDimensions lower=%g", media_dimensions->Lower);
6993bf66744d61d18c66d46f2608de0467ad3df0268Mopria        upper = strtok(NULL, x);
7003bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (upper != NULL) {
7013bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // Finally the upper bound
7023bf66744d61d18c66d46f2608de0467ad3df0268Mopria            char *tempStr = substring(upper, 1, strlen(upper) - 2);
7033bf66744d61d18c66d46f2608de0467ad3df0268Mopria            media_dimensions->Upper = atof(tempStr);
7043bf66744d61d18c66d46f2608de0467ad3df0268Mopria            free(tempStr);
7053bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7063bf66744d61d18c66d46f2608de0467ad3df0268Mopria            tempStr = substring(upper, 1, strlen(upper) - 2);
7073bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("getMediaDimensions part4=%s", tempStr);
7083bf66744d61d18c66d46f2608de0467ad3df0268Mopria            free(tempStr);
7093bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7103bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("getMediaDimensions upper=%g", media_dimensions->Upper);
7113bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // finally make sure we are in mm
7123bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp(um, in) == 0) {
7133bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("getMediaDimensions part5");
7143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                media_dimensions->Lower = media_dimensions->Lower * inch_to_mm;
7153bf66744d61d18c66d46f2608de0467ad3df0268Mopria                media_dimensions->Upper = media_dimensions->Upper * inch_to_mm;
7163bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
7173bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7183bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (media_dimensions->Lower > 0 && media_dimensions->Upper > 0) {
7193bf66744d61d18c66d46f2608de0467ad3df0268Mopria                double dTemp = 0;
7203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (media_dimensions->Lower > media_dimensions->Upper) {
7213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    dTemp = media_dimensions->Lower;
7223bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    media_dimensions->Lower = media_dimensions->Upper;
7233bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    media_dimensions->Upper = dTemp;
7243bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
7253bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("getMediaDimensions final lower=%g", media_dimensions->Lower);
7263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("getMediaDimensions final upper=%g", media_dimensions->Upper);
7273bf66744d61d18c66d46f2608de0467ad3df0268Mopria                free(tempMediaSize);
7283bf66744d61d18c66d46f2608de0467ad3df0268Mopria                free(dim);
7293bf66744d61d18c66d46f2608de0467ad3df0268Mopria                free(um);
7303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                return 1;
7313bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
7323bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
7333bf66744d61d18c66d46f2608de0467ad3df0268Mopria        free(dim);
7343bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
7353bf66744d61d18c66d46f2608de0467ad3df0268Mopria    free(um);
7363bf66744d61d18c66d46f2608de0467ad3df0268Mopria    free(tempMediaSize);
7373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return 0;
7383bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
7393bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7403bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid parse_getMediaSupported(ipp_t *response, media_supported_t *media_supported,
7413bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_capabilities_t *capabilities) {
7423bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
7433bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_attribute_t *attrptr;
7443bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int sizes_idx = 0;
7453bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char custom_min[] = "custom_min";
7463bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char custom_max[] = "custom_max";
7473bf66744d61d18c66d46f2608de0467ad3df0268Mopria    bool apply_custom_min_max = true;
7483bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int iterate = 0;
7493bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7503bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *optout_manufacture_list[7] = {"Brother", "Epson", "Fuji Xerox", "Konica Minolta",
7513bf66744d61d18c66d46f2608de0467ad3df0268Mopria            "Kyocera", "Canon", "UTAX_TA"};
7523bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int manufacturerlist_size = (sizeof(optout_manufacture_list) /
7533bf66744d61d18c66d46f2608de0467ad3df0268Mopria            sizeof(*optout_manufacture_list));
7543bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7553bf66744d61d18c66d46f2608de0467ad3df0268Mopria    media_dimension_mm_t custom_min_dim;
7563bf66744d61d18c66d46f2608de0467ad3df0268Mopria    media_dimension_mm_t custom_max_dim;
7573bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int rCustomMin = 0;
7583bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int rCustomMax = 0;
7593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char *tempMediaSize = NULL;
7603bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char manufacturername_from_model[256];
7623bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD(" Entered getMediaSupported");
7633bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    media_size_t media_sizeTemp;
7653bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int idx = 0;
7663bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7673bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // First check printer-device-id for manufacturer exception
7683bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-device-id", IPP_TAG_TEXT)) != NULL) {
7693bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strlcpy(capabilities->make, ippGetString(attrptr, 0, NULL), sizeof(capabilities->make));
7703bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("manufacturer_from_deviceid: %s", capabilities->make);
7713bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (iterate = 0; iterate < manufacturerlist_size; iterate++) {
7723bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcasestr(capabilities->make, optout_manufacture_list[iterate]) != NULL) {
7733bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("printer device id cmp: %s", strcasestr(capabilities->make,
7743bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        optout_manufacture_list[iterate]));
7753bf66744d61d18c66d46f2608de0467ad3df0268Mopria                apply_custom_min_max = false;
7763bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
7773bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
7783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
7793bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Second check printer-make-and-model for manufacturer exception
7813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (apply_custom_min_max) {
7823bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Get manufacturer name using  printer-make-and-model
7833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        attrptr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT);
7843bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (attrptr != NULL) {
7853bf66744d61d18c66d46f2608de0467ad3df0268Mopria            strlcpy(manufacturername_from_model, ippGetString(attrptr, 0, NULL),
7863bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    sizeof(manufacturername_from_model));
7873bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("manufacturer_from_make_model: %s", manufacturername_from_model);
7883bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (iterate = 0; iterate < manufacturerlist_size; iterate++) {
7893bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (strcasestr(manufacturername_from_model, optout_manufacture_list[iterate]) !=
7903bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        NULL) {
7913bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    LOGD("printer make model cmp: %s", strcasestr(manufacturername_from_model,
7923bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    optout_manufacture_list[iterate]));
7933bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    apply_custom_min_max = false;
7943bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
7953bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
7963bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
7973bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
7983bf66744d61d18c66d46f2608de0467ad3df0268Mopria
7993bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-supported", IPP_TAG_KEYWORD)) != NULL) {
8003bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("media-supported  found; number of values %d", ippGetCount(attrptr));
8013bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
8023bf66744d61d18c66d46f2608de0467ad3df0268Mopria            idx = ipp_find_media_size(ippGetString(attrptr, i, NULL), &media_sizeTemp);
8033bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD(" Temp - i: %d  idx %d keyword: %s PT_size %d", i, idx, ippGetString(
8043bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    attrptr, i, NULL), media_sizeTemp);
8053bf66744d61d18c66d46f2608de0467ad3df0268Mopria
8063bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // Modified since anytime the find media size returned 0 it could either mean
8073bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // NOT found or na_letter.
8083bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (idx >= 0) {
8093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                media_supported->media_size[sizes_idx] = media_sizeTemp;
8103bf66744d61d18c66d46f2608de0467ad3df0268Mopria                media_supported->idxKeywordTranTable[sizes_idx] = idx;
8113bf66744d61d18c66d46f2608de0467ad3df0268Mopria                sizes_idx++;
8123bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
8133bf66744d61d18c66d46f2608de0467ad3df0268Mopria
8143bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (idx == -1) { // it might be a custom range
8153bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (tempMediaSize != NULL) {
8163bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    free(tempMediaSize);
8173bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
8183bf66744d61d18c66d46f2608de0467ad3df0268Mopria                tempMediaSize = malloc(strlen(ippGetString(attrptr, i, NULL)) + 1);
8193bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (tempMediaSize == NULL) {
8203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    exit(EXIT_FAILURE);
8213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
8223bf66744d61d18c66d46f2608de0467ad3df0268Mopria                strcpy(tempMediaSize, ippGetString(attrptr, i, NULL));
8233bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (strstr(tempMediaSize, custom_min) != NULL) {
8243bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    rCustomMin = getMediaDimensions_mm(tempMediaSize, &custom_min_dim);
8253bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
8263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (strstr(tempMediaSize, custom_max) != NULL) {
8273bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    rCustomMax = getMediaDimensions_mm(tempMediaSize, &custom_max_dim);
8283bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
8293bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
8303bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
8313bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // if value equal to particular manufacture condition goes here
8323bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (apply_custom_min_max) {
8333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("*****apply custom range for this manufacture");
8343bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // Now add in custom sizes if there is a custom min max range
8353bf66744d61d18c66d46f2608de0467ad3df0268Mopria            media_dimension_mm_t media_dim;
8363bf66744d61d18c66d46f2608de0467ad3df0268Mopria            int rMediaDim = 0;
8373bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("rCustomMin:%d rCustomMax:%d", rCustomMin, rCustomMax);
8383bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (rCustomMin > 0 && rCustomMax > 0) { // we have custom support
8393bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("CustomRange minLower:%g minUpper:%g maxLower:%g maxUpper:%g",
8403bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        custom_min_dim.Lower, custom_min_dim.Upper, custom_max_dim.Lower,
8413bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        custom_max_dim.Upper);
8423bf66744d61d18c66d46f2608de0467ad3df0268Mopria                media_dim.Lower = 0;
8433bf66744d61d18c66d46f2608de0467ad3df0268Mopria                media_dim.Upper = 0;
8443bf66744d61d18c66d46f2608de0467ad3df0268Mopria                for (i = 0; i < SUPPORTED_MEDIA_SIZE_COUNT; i++) {
8453bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    int found;
8463bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    int j;
8473bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    found = 0;
8483bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    int sizes_idx_start = sizes_idx - 1;
8493bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    for (j = 0; j < sizes_idx_start; j++) {
8503bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        if (i == media_supported->idxKeywordTranTable[j]) {
8513bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            found = 1;
8523bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            break;
8533bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        }
8543bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    }
8553bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    if (found == 0) {
8563bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        // check custom
8573bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        if (tempMediaSize != NULL) {
8583bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            free(tempMediaSize);
8593bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        }
8603bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        tempMediaSize = malloc(strlen(SupportedMediaSizes[i].PWGName) + 1);
8613bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        if (tempMediaSize == NULL) {
8623bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            exit(EXIT_FAILURE);
8633bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        }
8643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        strcpy(tempMediaSize, SupportedMediaSizes[i].PWGName);
8653bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        LOGD("NOT FOUND CHECKING CUSTOM:%s", tempMediaSize);
8663bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        rMediaDim = getMediaDimensions_mm(tempMediaSize, &media_dim);
8673bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        if (rMediaDim > 0) {
8683bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            LOGD("CustomRange minLower:%g minUpper:%g maxLower:%g maxUpper:%g"
8693bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    "lower:%g upper:%g",
8703bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    custom_min_dim.Lower, custom_min_dim.Upper,
8713bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    custom_max_dim.Lower,
8723bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    custom_max_dim.Upper, media_dim.Lower, media_dim.Upper);
8733bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            if (media_dim.Lower >= custom_min_dim.Lower &&
8743bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    media_dim.Lower <= custom_max_dim.Lower
8753bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    && media_dim.Upper >= custom_min_dim.Upper &&
8763bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                    media_dim.Upper <= custom_max_dim.Upper) {
8773bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                LOGD("Add Media Size %s!!", tempMediaSize);
8783bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                media_supported->media_size[sizes_idx] =
8793bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                        SupportedMediaSizes[i].media_size;
8803bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                media_supported->idxKeywordTranTable[sizes_idx] = i;
8813bf66744d61d18c66d46f2608de0467ad3df0268Mopria                                sizes_idx++;
8823bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            }
8833bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        }
8843bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    }
8853bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
8863bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (tempMediaSize != NULL) {
8873bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    free(tempMediaSize);
8883bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    tempMediaSize = NULL;
8893bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
8903bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
8913bf66744d61d18c66d46f2608de0467ad3df0268Mopria        } else {
8923bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("*****Dont apply custom range for this manufacture");
8933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
8943bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
8953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("media-supported not found");
8963bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
8973bf66744d61d18c66d46f2608de0467ad3df0268Mopria
8983bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (tempMediaSize) {
8993bf66744d61d18c66d46f2608de0467ad3df0268Mopria        free(tempMediaSize);
9003bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9013bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
9023bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9033bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic void get_supportedPrinterResolutions(ipp_attribute_t *attrptr,
9043bf66744d61d18c66d46f2608de0467ad3df0268Mopria        printer_capabilities_t *capabilities) {
9053bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int idx = 0;
9063bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
9073bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (i = 0; i < ippGetCount(attrptr); i++) {
9083bf66744d61d18c66d46f2608de0467ad3df0268Mopria        ipp_res_t units;
9093bf66744d61d18c66d46f2608de0467ad3df0268Mopria        int xres, yres;
9103bf66744d61d18c66d46f2608de0467ad3df0268Mopria        xres = ippGetResolution(attrptr, i, &yres, &units);
9113bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (units == IPP_RES_PER_INCH) {
9123bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if ((idx < MAX_RESOLUTIONS_SUPPORTED) && (xres == yres)) {
9133bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->supportedResolutions[idx] = xres;
9143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                idx++;
9153bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
9163bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
9173bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9183bf66744d61d18c66d46f2608de0467ad3df0268Mopria    capabilities->numSupportedResolutions = idx;
9193bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
9203bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9213bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid getResourceFromURI(const char *uri, char *resource, int resourcelen) {
9223bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char scheme[1024];
9233bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char username[1024];
9243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char host[1024];
9253bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int port;
9263bf66744d61d18c66d46f2608de0467ad3df0268Mopria    httpSeparateURI(0, uri, scheme, 1024, username, 1024, host, 1024, &port, resource, resourcelen);
9273bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
9283bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9293bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
9303bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Add a new media type to a printer's collection of supported media types
9313bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
9323bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic void addMediaType(printer_capabilities_t *capabilities, media_type_t mediaType) {
9333bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int index;
9343bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (index = 0; index < capabilities->numSupportedMediaTypes; index++) {
9353bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Skip if already present
9363bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (capabilities->supportedMediaTypes[index] == mediaType) return;
9373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9383bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9393bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Add if not found and not too many
9403bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (capabilities->numSupportedMediaTypes < MAX_MEDIA_TYPES_SUPPORTED) {
9413bf66744d61d18c66d46f2608de0467ad3df0268Mopria        capabilities->supportedMediaTypes[capabilities->numSupportedMediaTypes++] = mediaType;
9423bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
9433bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGI("Hit MAX_MEDIA_TYPES_SUPPORTED while adding %d", mediaType);
9443bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9453bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
9463bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9473bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid parse_printerAttributes(ipp_t *response, printer_capabilities_t *capabilities) {
9483bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i, j;
9493bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_attribute_t *attrptr;
9503bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9513bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("Entered parse_printerAttributes");
9523bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9533bf66744d61d18c66d46f2608de0467ad3df0268Mopria    media_supported_t media_supported;
9543bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (i = 0; i <= PAGE_STATUS_MAX - 1; i++) {
9553bf66744d61d18c66d46f2608de0467ad3df0268Mopria        media_supported.media_size[i] = 0;
9563bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9573bf66744d61d18c66d46f2608de0467ad3df0268Mopria    parse_getMediaSupported(response, &media_supported, capabilities);
9583bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    parse_printerUris(response, capabilities);
9603bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("Media Supported: ");
9623bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int idx = 0;
9633bf66744d61d18c66d46f2608de0467ad3df0268Mopria    capabilities->numSupportedMediaTypes = 0;
9643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (i = 0; i <= PAGE_STATUS_MAX - 1; i++) {
9653bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (media_supported.media_size[i] != 0) {
9663bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->supportedMediaSizes[capabilities->numSupportedMediaSizes++] =
9673bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    media_supported.media_size[i];
9683bf66744d61d18c66d46f2608de0467ad3df0268Mopria            idx = media_supported.idxKeywordTranTable[i];
9693bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD(" i %d, \tPT_Size: %d  \tidx %d \tKeyword: %s", i, media_supported.media_size[i],
9703bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    idx, SupportedMediaSizes[idx].PWGName);
9713bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
9723bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9733bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("");
9743bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9753bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL) {
9763bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("printer-name: %s", ippGetString(attrptr, 0, NULL));
9773bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strlcpy(capabilities->name, ippGetString(attrptr, 0, NULL), sizeof(capabilities->name));
9783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9793bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT)) != NULL) {
9813bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strlcpy(capabilities->make, ippGetString(attrptr, 0, NULL), sizeof(capabilities->make));
9823bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9833bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9843bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-uuid", IPP_TAG_URI)) != NULL) {
9853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strlcpy(capabilities->uuid, ippGetString(attrptr, 0, NULL), sizeof(capabilities->uuid));
9863bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9873bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9883bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT)) != NULL) {
9893bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strlcpy(capabilities->location, ippGetString(attrptr, 0, NULL),
9903bf66744d61d18c66d46f2608de0467ad3df0268Mopria                sizeof(capabilities->location));
9913bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9923bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9933bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-default", IPP_TAG_KEYWORD)) != NULL) {
9943bf66744d61d18c66d46f2608de0467ad3df0268Mopria        strlcpy(capabilities->mediaDefault, ippGetString(attrptr, 0, NULL),
9953bf66744d61d18c66d46f2608de0467ad3df0268Mopria                sizeof(capabilities->mediaDefault));
9963bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
9973bf66744d61d18c66d46f2608de0467ad3df0268Mopria
9983bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "color-supported", IPP_TAG_BOOLEAN)) != NULL) {
9993bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (ippGetBoolean(attrptr, 0)) {
10003bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->color = 1;
10013bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10023bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10033bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "copies-supported", IPP_TAG_RANGE)) != NULL) {
10043bf66744d61d18c66d46f2608de0467ad3df0268Mopria        int upper = 0;
10053bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
10063bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ippGetRange(attrptr, i, &upper);
10073bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10083bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (upper > 1) {
10093bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->canCopy = 1;
10103bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10113bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10123bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "print-color-mode-supported", IPP_TAG_KEYWORD)) !=
10133bf66744d61d18c66d46f2608de0467ad3df0268Mopria            NULL) {
10143bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
10153bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp("color", ippGetString(attrptr, i, NULL)) == 0) {
10163bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->color = 1;
10173bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
10183bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10193bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10203bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10213bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char imagePCLm[] = "application/PCLm";
10223bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char imagePWG[] = "image/pwg-raster";
10233bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char imagePDF[] = "image/pdf";
10243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char applicationPDF[] = "application/pdf";
10253bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10263bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "document-format-supported", IPP_TAG_MIMETYPE))
10273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            != NULL) {
10283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
10293bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp(imagePDF, ippGetString(attrptr, i, NULL)) == 0) {
10303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->canPrintPDF = 1;
10313bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(applicationPDF, ippGetString(attrptr, i, NULL)) == 0) {
10323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->canPrintPDF = 1;
10333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(imagePCLm, ippGetString(attrptr, i, NULL)) == 0) {
10343bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->canPrintPCLm = 1;
10353bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(applicationPDF, ippGetString(attrptr, i, NULL)) == 0) {
10363bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->canPrintPDF = 1;
10373bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(imagePWG, ippGetString(attrptr, i, NULL)) == 0) {
10383bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->canPrintPWG = 1;
10393bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
10403bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10413bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10423bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10433bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "sides-supported", IPP_TAG_KEYWORD)) != NULL) {
10443bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
10453bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp(IPP_SIDES_TWO_SIDED_SHORT_EDGE, ippGetString(attrptr, i, NULL)) == 0) {
10463bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->duplex = 1;
10473bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(IPP_SIDES_TWO_SIDED_LONG_EDGE, ippGetString(attrptr, i, NULL)) == 0) {
10483bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->duplex = 1;
10493bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
10503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10513bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10523bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10533bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Look up supported media types
10543bf66744d61d18c66d46f2608de0467ad3df0268Mopria    capabilities->numSupportedMediaTypes = 0;
10553bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (((attrptr = ippFindAttribute(response, "media-type-supported", IPP_TAG_KEYWORD)) != NULL)
10563bf66744d61d18c66d46f2608de0467ad3df0268Mopria            || ((attrptr = ippFindAttribute(response, "media-type-supported", IPP_TAG_NAME))
10573bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    != NULL)) {
10583bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
10593bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcasestr(ippGetString(attrptr, i, NULL), "photographic-glossy")) {
10603bf66744d61d18c66d46f2608de0467ad3df0268Mopria                addMediaType(capabilities, MEDIA_PHOTO_GLOSSY);
10613bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcasestr(ippGetString(attrptr, i, NULL), "photo")) {
10623bf66744d61d18c66d46f2608de0467ad3df0268Mopria                addMediaType(capabilities, MEDIA_PHOTO);
10633bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcasestr(ippGetString(attrptr, i, NULL), "stationery")) {
10643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                addMediaType(capabilities, MEDIA_PLAIN);
10653bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
10663bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
10673bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10683bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10693bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (capabilities->numSupportedMediaTypes == 0) {
10703bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // If no recognized media types were found, fall back to all 3 just in case
10713bf66744d61d18c66d46f2608de0467ad3df0268Mopria        addMediaType(capabilities, MEDIA_PLAIN);
10723bf66744d61d18c66d46f2608de0467ad3df0268Mopria        addMediaType(capabilities, MEDIA_PHOTO);
10733bf66744d61d18c66d46f2608de0467ad3df0268Mopria        addMediaType(capabilities, MEDIA_PHOTO_GLOSSY);
10743bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10753bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10763bf66744d61d18c66d46f2608de0467ad3df0268Mopria    capabilities->numSupportedResolutions = 0;
10773bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // only appears that SMM supports the pclm-source-resolution-supported attribute
10783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // if that is not present, use the printer-resolution-supported attribute to determine
10793bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // if 300DPI is supported
10803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "pclm-source-resolution-supported",
10813bf66744d61d18c66d46f2608de0467ad3df0268Mopria            IPP_TAG_RESOLUTION)) != NULL) {
10823bf66744d61d18c66d46f2608de0467ad3df0268Mopria        get_supportedPrinterResolutions(attrptr, capabilities);
10833bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if ((attrptr = ippFindAttribute(response, "printer-resolution-supported",
10843bf66744d61d18c66d46f2608de0467ad3df0268Mopria            IPP_TAG_RESOLUTION)) != NULL) {
10853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        get_supportedPrinterResolutions(attrptr, capabilities);
10863bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
10873bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10883bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char ipp10[] = "1.0";
10893bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char ipp11[] = "1.1";
10903bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char ipp20[] = "2.0";
10913bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10923bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "ipp-versions-supported", IPP_TAG_KEYWORD)) != NULL) {
10933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        unsigned char supportsIpp20 = 0;
10943bf66744d61d18c66d46f2608de0467ad3df0268Mopria        unsigned char supportsIpp11 = 0;
10953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        unsigned char supportsIpp10 = 0;
10963bf66744d61d18c66d46f2608de0467ad3df0268Mopria
10973bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
10983bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp(ipp10, ippGetString(attrptr, i, NULL)) == 0) {
10993bf66744d61d18c66d46f2608de0467ad3df0268Mopria                supportsIpp10 = 1;
11003bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(ipp11, ippGetString(attrptr, i, NULL)) == 0) {
11013bf66744d61d18c66d46f2608de0467ad3df0268Mopria                supportsIpp11 = 1;
11023bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp(ipp20, ippGetString(attrptr, i, NULL)) == 0) {
11033bf66744d61d18c66d46f2608de0467ad3df0268Mopria                supportsIpp20 = 1;
11043bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else {
11053bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("found another ipp version. %s", ippGetString(attrptr, i, NULL));
11063bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
11073bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (supportsIpp20) {
11083bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMajor = 2;
11093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMinor = 0;
11103bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (supportsIpp11) {
11113bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMajor = 1;
11123bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMinor = 1;
11133bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (supportsIpp10) {
11143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMajor = 1;
11153bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMinor = 0;
11163bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else {
11173bf66744d61d18c66d46f2608de0467ad3df0268Mopria                // default to 1.0
11183bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMajor = 1;
11193bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ippVersionMinor = 0;
11203bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
11213bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
11223bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
11233bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    char epcl10[] = "1.0";
11253bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "epcl-version-supported", IPP_TAG_KEYWORD)) != NULL) {
11263bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
11273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("setting epcl_ipp_version (KEYWORD) %s", ippGetString(attrptr, i, NULL));
11283bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11293bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // substring match because different devices implemented spec differently
11303bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strstr(ippGetString(attrptr, i, NULL), epcl10) != NULL) {
11313bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("setting epcl_ipp_version = 1");
11323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ePclIppVersion = 1;
11333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
11343bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
11353bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
11363bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "epcl-version-supported", IPP_TAG_TEXT)) != NULL) {
11383bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
11393bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("setting epcl_ipp_verion (TEXT) %s", ippGetString(attrptr, i, NULL));
11403bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11413bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // substring match because different devices implemented spec differently
11423bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strstr(ippGetString(attrptr, i, NULL), epcl10) != NULL) {
11433bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("setting epcl_ipp_verion = 1");
11443bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->ePclIppVersion = 1;
11453bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
11463bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
11473bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
11483bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11493bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-col-default", IPP_TAG_BEGIN_COLLECTION)) !=
11503bf66744d61d18c66d46f2608de0467ad3df0268Mopria            NULL) {
11513bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
11523bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("Gathering margins supported");
11533bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11543bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ipp_t *collection = ippGetCollection(attrptr, i);
11553bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11563bf66744d61d18c66d46f2608de0467ad3df0268Mopria            for (j = 0, attrptr = ippFirstAttribute(collection);
11573bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    (j < 4) && (attrptr != NULL); attrptr = ippNextAttribute(collection)) {
11583bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (strcmp("media-top-margin", ippGetName(attrptr)) == 0) {
11593bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    capabilities->printerTopMargin = ippGetInteger(attrptr, 0);
11603bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strcmp("media-bottom-margin", ippGetName(attrptr)) == 0) {
11613bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    capabilities->printerBottomMargin = ippGetInteger(attrptr, 0);
11623bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strcmp("media-left-margin", ippGetName(attrptr)) == 0) {
11633bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    capabilities->printerLeftMargin = ippGetInteger(attrptr, 0);
11643bf66744d61d18c66d46f2608de0467ad3df0268Mopria                } else if (strcmp("media-right-margin", ippGetName(attrptr)) == 0) {
11653bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    capabilities->printerRightMargin = ippGetInteger(attrptr, 0);
11663bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
11673bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
11683bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
11693bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
11703bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11713bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-size-name", IPP_TAG_KEYWORD)) != NULL) {
11723bf66744d61d18c66d46f2608de0467ad3df0268Mopria        capabilities->isMediaSizeNameSupported = true;
11733bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
11743bf66744d61d18c66d46f2608de0467ad3df0268Mopria        capabilities->isMediaSizeNameSupported = false;
11753bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
11763bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11773bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // is strip length supported? if so, stored in capabilities
11783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "pclm-strip-height-preferred",
11793bf66744d61d18c66d46f2608de0467ad3df0268Mopria            IPP_TAG_INTEGER)) != NULL) {
11803bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("pclm-strip-height-preferred=%d", ippGetInteger(attrptr, 0));
11813bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11823bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // if the strip height is 0, the device wants us to send the entire page in one band
11833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // (according to ePCL spec). Since our code doesn't currently support generating an entire
11843bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // page in one band, set the strip height to the default value every device *should* support
11853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // also, for some reason our code crashes when it attempts to generate strips at 512 or
11863bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // above. Therefore, limiting the upper bound strip height to 256
11873bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (ippGetInteger(attrptr, 0) == 0 || ippGetInteger(attrptr, 0) > 256) {
11883bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->stripHeight = STRIPE_HEIGHT;
11893bf66744d61d18c66d46f2608de0467ad3df0268Mopria        } else {
11903bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->stripHeight = ippGetInteger(attrptr, 0);
11913bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
11923bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
11933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        capabilities->stripHeight = STRIPE_HEIGHT;
11943bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
11953bf66744d61d18c66d46f2608de0467ad3df0268Mopria
11963bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // what is the preferred compression method - jpeg, flate, rle
11973bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "pclm-compression-method-preferred",
11983bf66744d61d18c66d46f2608de0467ad3df0268Mopria            IPP_TAG_KEYWORD)) != NULL) {
11993bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("pclm-compression-method-preferred=%s", ippGetString(attrptr, 0, NULL));
12003bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12013bf66744d61d18c66d46f2608de0467ad3df0268Mopria
12023bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // is device able to rotate back page for duplex jobs?
12033bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "pclm-raster-back-side", IPP_TAG_KEYWORD)) != NULL) {
12043bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("pclm-raster-back-side=%s", ippGetString(attrptr, 0, NULL));
12053bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (strcmp(ippGetString(attrptr, 0, NULL), "rotated") == 0) {
12063bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->canRotateDuplexBackPage = 0;
12073bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("Device cannot rotate back page for duplex jobs.");
12083bf66744d61d18c66d46f2608de0467ad3df0268Mopria        } else {
12093bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->canRotateDuplexBackPage = 1;
12103bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12113bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12123bf66744d61d18c66d46f2608de0467ad3df0268Mopria
12133bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // look for full-bleed supported by looking for 0 on all margins
12143bf66744d61d18c66d46f2608de0467ad3df0268Mopria    bool topsupported = false, bottomsupported = false, rightsupported = false,
12153bf66744d61d18c66d46f2608de0467ad3df0268Mopria            leftsupported = false;
12163bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-top-margin-supported", IPP_TAG_INTEGER)) !=
12173bf66744d61d18c66d46f2608de0467ad3df0268Mopria            NULL) {
12183bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
12193bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ippGetInteger(attrptr, i) == 0) {
12203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("Top Margin Supported");
12213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                topsupported = true;
12223bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
12233bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
12243bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12253bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12263bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-bottom-margin-supported", IPP_TAG_INTEGER)) !=
12273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            NULL) {
12283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
12293bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ippGetInteger(attrptr, i) == 0) {
12303bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("Bottom Margin Supported");
12313bf66744d61d18c66d46f2608de0467ad3df0268Mopria                bottomsupported = true;
12323bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
12333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
12343bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12353bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12363bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-right-margin-supported", IPP_TAG_INTEGER)) !=
12373bf66744d61d18c66d46f2608de0467ad3df0268Mopria            NULL) {
12383bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
12393bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ippGetInteger(attrptr, i) == 0) {
12403bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("Right Margin Supported");
12413bf66744d61d18c66d46f2608de0467ad3df0268Mopria                rightsupported = true;
12423bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
12433bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
12443bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12453bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12463bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "media-left-margin-supported", IPP_TAG_INTEGER)) !=
12473bf66744d61d18c66d46f2608de0467ad3df0268Mopria            NULL) {
12483bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
12493bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ippGetInteger(attrptr, i) == 0) {
12503bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("Left Margin Supported");
12513bf66744d61d18c66d46f2608de0467ad3df0268Mopria                leftsupported = true;
12523bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
12533bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
12543bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12553bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12563bf66744d61d18c66d46f2608de0467ad3df0268Mopria
12573bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (topsupported && bottomsupported && rightsupported && leftsupported) {
12583bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("full-bleed is supported");
12593bf66744d61d18c66d46f2608de0467ad3df0268Mopria        capabilities->borderless = 1;
12603bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
12613bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("full-bleed is NOT supported");
12623bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12633bf66744d61d18c66d46f2608de0467ad3df0268Mopria
12643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-device-id", IPP_TAG_TEXT)) != NULL) {
12653bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (strstr(ippGetString(attrptr, 0, NULL), "PCL3GUI") != NULL) {
12663bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->inkjet = 1;
12673bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12683bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (capabilities->borderless == 1) {
12693bf66744d61d18c66d46f2608de0467ad3df0268Mopria        capabilities->inkjet = 1;
12703bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12713bf66744d61d18c66d46f2608de0467ad3df0268Mopria
12723bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // determine if device prints pages face-down
12733bf66744d61d18c66d46f2608de0467ad3df0268Mopria    capabilities->faceDownTray = 1;
12743bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "output-bin-supported", IPP_TAG_KEYWORD)) != NULL) {
12753bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (strstr(ippGetString(attrptr, 0, NULL), "face-up") != NULL) {
12763bf66744d61d18c66d46f2608de0467ad3df0268Mopria            capabilities->faceDownTray = 0;
12773bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12793bf66744d61d18c66d46f2608de0467ad3df0268Mopria
12803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Determine supported document format details
12813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "document-format-details-supported",
12823bf66744d61d18c66d46f2608de0467ad3df0268Mopria            IPP_TAG_KEYWORD)) != NULL) {
12833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < ippGetCount(attrptr); i++) {
12843bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp("document-source-application-name", ippGetString(attrptr, i, NULL)) == 0) {
12853bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->docSourceAppName = 1;
12863bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (
12873bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strcmp("document-source-application-version", ippGetString(attrptr, i, NULL)) ==
12883bf66744d61d18c66d46f2608de0467ad3df0268Mopria                            0) {
12893bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->docSourceAppVersion = 1;
12903bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp("document-source-os-name", ippGetString(attrptr, i, NULL)) == 0) {
12913bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->docSourceOsName = 1;
12923bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (strcmp("document-source-os-version", ippGetString(attrptr, i, NULL)) == 0) {
12933bf66744d61d18c66d46f2608de0467ad3df0268Mopria                capabilities->docSourceOsVersion = 1;
12943bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
12953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
12963bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
12973bf66744d61d18c66d46f2608de0467ad3df0268Mopria    debuglist_printerCapabilities(capabilities);
12983bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
12993bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13003bf66744d61d18c66d46f2608de0467ad3df0268Mopria// Used in parse_printerUris
13013bf66744d61d18c66d46f2608de0467ad3df0268Mopria#define MAX_URIS 10
13023bf66744d61d18c66d46f2608de0467ad3df0268Mopriatypedef struct {
13033bf66744d61d18c66d46f2608de0467ad3df0268Mopria    const char *uri;
13043bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int valid;
13053bf66744d61d18c66d46f2608de0467ad3df0268Mopria} parsed_uri_t;
13063bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13073bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic void parse_printerUris(ipp_t *response, printer_capabilities_t *capabilities) {
13083bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_attribute_t *attrptr;
13093bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int i;
13103bf66744d61d18c66d46f2608de0467ad3df0268Mopria    parsed_uri_t uris[MAX_URIS] = {0};
13113bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13123bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) {
13133bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < MIN(ippGetCount(attrptr), MAX_URIS); i++) {
13143bf66744d61d18c66d46f2608de0467ad3df0268Mopria            uris[i].uri = ippGetString(attrptr, i, NULL);
13153bf66744d61d18c66d46f2608de0467ad3df0268Mopria            uris[i].valid = true;
13163bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
13173bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
13183bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13193bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // If security or authentication is required (non-"none") at any URI, mark it invalid
13203bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13213bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "uri-security-supported", IPP_TAG_KEYWORD)) != NULL) {
13223bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < MIN(ippGetCount(attrptr), MAX_URIS); i++) {
13233bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp("none", ippGetString(attrptr, i, NULL)) != 0) {
13243bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("parse_printerUris %s invalid because sec=%s", uris[i].uri,
13253bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetString(attrptr, i, NULL));
13263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                uris[i].valid = false;
13273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
13283bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
13293bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
13303bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13313bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((attrptr = ippFindAttribute(response, "uri-authentication-supported", IPP_TAG_KEYWORD))
13323bf66744d61d18c66d46f2608de0467ad3df0268Mopria            != NULL) {
13333bf66744d61d18c66d46f2608de0467ad3df0268Mopria        for (i = 0; i < MIN(ippGetCount(attrptr), MAX_URIS); i++) {
13343bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // Allow "none" and "requesting-user-name" only
13353bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (strcmp("none", ippGetString(attrptr, i, NULL)) != 0 &&
13363bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    strcmp("requesting-user-name", ippGetString(attrptr, i, NULL)) != 0) {
13373bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("parse_printerUris %s invalid because auth=%s", uris[i].uri,
13383bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        ippGetString(attrptr, i, NULL));
13393bf66744d61d18c66d46f2608de0467ad3df0268Mopria                uris[i].valid = false;
13403bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
13413bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
13423bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
13433bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13443bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Find a valid URI and copy it into place.
13453bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (i = 0; i < MAX_URIS; i++) {
13463bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (uris[i].valid) {
13473bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("parse_printerUris found %s", uris[i].uri);
13483bf66744d61d18c66d46f2608de0467ad3df0268Mopria            strlcpy(capabilities->printerUri, uris[i].uri, sizeof(capabilities->printerUri));
13493bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
13503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
13513bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
13523bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
13533bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13543bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid debuglist_printerCapabilities(printer_capabilities_t *capabilities) {
13553bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("printer make: %s", capabilities->make);
13563bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("printer default media: %s", capabilities->mediaDefault);
13573bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("canPrintPDF: %d", capabilities->canPrintPDF);
13583bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("duplex: %d", capabilities->duplex);
13593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("canRotateDuplexBackPage: %d", capabilities->canRotateDuplexBackPage);
13603bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("color: %d", capabilities->color);
13613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("canCopy: %d", capabilities->canCopy);
13623bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("ippVersionMajor: %d", capabilities->ippVersionMajor);
13633bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("ippVersionMinor: %d", capabilities->ippVersionMinor);
13643bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("strip height: %d", capabilities->stripHeight);
13653bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("faceDownTray: %d", capabilities->faceDownTray);
13663bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
13673bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13683bf66744d61d18c66d46f2608de0467ad3df0268Mopriavoid debuglist_printerStatus(printer_state_dyn_t *printer_state_dyn) {
13693bf66744d61d18c66d46f2608de0467ad3df0268Mopria    const char *decoded = "unknown";
13703bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (printer_state_dyn->printer_status == PRINT_STATUS_INITIALIZING) {
13713bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Initializing";
13723bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_SHUTTING_DOWN) {
13733bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Shutting Down";
13743bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_UNABLE_TO_CONNECT) {
13753bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Unable To Connect";
13763bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_UNKNOWN) {
13773bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Unknown";
13783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_OFFLINE) {
13793bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Offline";
13803bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_IDLE) {
13813bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Idle";
13823bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_PRINTING) {
13833bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Printing";
13843bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_OUT_OF_PAPER) {
13853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Out Of Paper";
13863bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_OUT_OF_INK) {
13873bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Out Of Ink";
13883bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_JAMMED) {
13893bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Jammed";
13903bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_DOOR_OPEN) {
13913bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Door Open";
13923bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else if (printer_state_dyn->printer_status == PRINT_STATUS_SVC_REQUEST) {
13933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        decoded = "Service Request";
13943bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
13953bf66744d61d18c66d46f2608de0467ad3df0268Mopria    LOGD("printer status: %d (%s)", printer_state_dyn->printer_status, decoded);
13963bf66744d61d18c66d46f2608de0467ad3df0268Mopria
13973bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int idx = 0;
13983bf66744d61d18c66d46f2608de0467ad3df0268Mopria    for (idx = 0; idx < (PRINT_STATUS_MAX_STATE + 1); idx++) {
13993bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (PRINT_STATUS_MAX_STATE != printer_state_dyn->printer_reasons[idx]) {
14003bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("printer_reasons (%d): %d", idx, printer_state_dyn->printer_reasons[idx]);
14013bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
14023bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
14033bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
14043bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14053bf66744d61d18c66d46f2608de0467ad3df0268Mopriahttp_t *ipp_cups_connect(const wprint_connect_info_t *connect_info, char *printer_uri,
14063bf66744d61d18c66d46f2608de0467ad3df0268Mopria        unsigned int uriLength) {
14073bf66744d61d18c66d46f2608de0467ad3df0268Mopria    const char *uri_path;
14083bf66744d61d18c66d46f2608de0467ad3df0268Mopria    http_t *curl_http = NULL;
14093bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14103bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if ((connect_info->uri_path == NULL) || (strlen(connect_info->uri_path) == 0)) {
14113bf66744d61d18c66d46f2608de0467ad3df0268Mopria        uri_path = DEFAULT_IPP_URI_RESOURCE;
14123bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } else {
14133bf66744d61d18c66d46f2608de0467ad3df0268Mopria        uri_path = connect_info->uri_path;
14143bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
14153bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14163bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int ippPortNumber = ((connect_info->port_num == IPP_PORT) ? ippPort() : connect_info->port_num);
14173bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14183bf66744d61d18c66d46f2608de0467ad3df0268Mopria    curl_http = httpConnect(connect_info->printer_addr, ippPortNumber);
14193bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14203bf66744d61d18c66d46f2608de0467ad3df0268Mopria    httpSetTimeout(curl_http, DEFAULT_IPP_TIMEOUT, NULL, 0);
14213bf66744d61d18c66d46f2608de0467ad3df0268Mopria    httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, uriLength, connect_info->uri_scheme, NULL,
14223bf66744d61d18c66d46f2608de0467ad3df0268Mopria            connect_info->printer_addr, ippPortNumber, uri_path);
14233bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14243bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (curl_http == NULL) {
14253bf66744d61d18c66d46f2608de0467ad3df0268Mopria        LOGD("ipp_cups_connect failed addr=%s port=%d", connect_info->printer_addr, ippPortNumber);
14263bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
14273bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return curl_http;
14283bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
14293bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14303bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
14313bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Send a request using cupsSendRequest(). Loop if we get NULL or CONTINUE. Does not delete
14323bf66744d61d18c66d46f2608de0467ad3df0268Mopria * the request.
14333bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
14343bf66744d61d18c66d46f2608de0467ad3df0268Mopriastatic ipp_t *ippSendRequest(http_t *http, ipp_t *request, char *resource) {
14353bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_t *response = NULL;
14363bf66744d61d18c66d46f2608de0467ad3df0268Mopria    http_status_t result;
14373bf66744d61d18c66d46f2608de0467ad3df0268Mopria    bool retry;
14383bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14393bf66744d61d18c66d46f2608de0467ad3df0268Mopria    do {
14403bf66744d61d18c66d46f2608de0467ad3df0268Mopria        retry = false;
14413bf66744d61d18c66d46f2608de0467ad3df0268Mopria        result = cupsSendRequest(http, request, resource, ippLength(request));
14423bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (result != HTTP_ERROR) {
14433bf66744d61d18c66d46f2608de0467ad3df0268Mopria            response = cupsGetResponse(http, resource);
14443bf66744d61d18c66d46f2608de0467ad3df0268Mopria            result = httpGetStatus(http);
14453bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
14463bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14473bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (result == HTTP_CONTINUE && response == NULL) {
14483bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // We need to retry when this happens.
14493bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGD("ippSendRequest: (Continue with NULL response) Retry");
14503bf66744d61d18c66d46f2608de0467ad3df0268Mopria            retry = true;
14513bf66744d61d18c66d46f2608de0467ad3df0268Mopria        } else if (result == HTTP_ERROR || result >= HTTP_BAD_REQUEST) {
14523bf66744d61d18c66d46f2608de0467ad3df0268Mopria            _cupsSetHTTPError(result);
14533bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
14543bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
14553bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14563bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (http->state != HTTP_WAITING) {
14573bf66744d61d18c66d46f2608de0467ad3df0268Mopria            httpFlush(http);
14583bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
14593bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } while (retry);
14603bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14613bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return response;
14623bf66744d61d18c66d46f2608de0467ad3df0268Mopria}
14633bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14643bf66744d61d18c66d46f2608de0467ad3df0268Mopria/*
14653bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Call ippDoCupsIORequest, repeating if a failure occurs based on failure conditions, and
14663bf66744d61d18c66d46f2608de0467ad3df0268Mopria * returning the response (or NULL if it failed).
14673bf66744d61d18c66d46f2608de0467ad3df0268Mopria *
14683bf66744d61d18c66d46f2608de0467ad3df0268Mopria * Does not free the request, and the caller must call ippDelete to free any valid response.
14693bf66744d61d18c66d46f2608de0467ad3df0268Mopria */
14703bf66744d61d18c66d46f2608de0467ad3df0268Mopriaipp_t *ipp_doCupsRequest(http_t *http, ipp_t *request, char *http_resource, char *printer_uri) {
14713bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_status_t ipp_status;
14723bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_t *response = NULL;
14733bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int service_unavailable_retry_count = 0;
14743bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int bad_request_retry_count = 0;
14753bf66744d61d18c66d46f2608de0467ad3df0268Mopria    int internal_error_retry_count = 0;
14763bf66744d61d18c66d46f2608de0467ad3df0268Mopria    ipp_version_state ipp_version_supported = IPP_VERSION_RESOLVED;
14773bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14783bf66744d61d18c66d46f2608de0467ad3df0268Mopria    // Fail if any of these parameters are NULL
14793bf66744d61d18c66d46f2608de0467ad3df0268Mopria    if (http == NULL || request == NULL || http_resource == NULL || printer_uri == NULL) {
14803bf66744d61d18c66d46f2608de0467ad3df0268Mopria        return NULL;
14813bf66744d61d18c66d46f2608de0467ad3df0268Mopria    }
14823bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14833bf66744d61d18c66d46f2608de0467ad3df0268Mopria    do {
14843bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // Give up immediately if wprint is done.
14853bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (!wprintIsRunning()) return NULL;
14863bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14873bf66744d61d18c66d46f2608de0467ad3df0268Mopria        // This is a no-op until we hit the error IPP_VERSION_NOT_SUPPORTED and retry.
14883bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (set_ipp_version(request, printer_uri, http, ipp_version_supported) != 0) {
14893bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // We tried to find the correct IPP version by doing a series of get attribute
14903bf66744d61d18c66d46f2608de0467ad3df0268Mopria            // requests but they all failed... we give up.
14913bf66744d61d18c66d46f2608de0467ad3df0268Mopria            LOGE("ipp_doCupsRequest: set_ipp_version!=0, version not set");
14923bf66744d61d18c66d46f2608de0467ad3df0268Mopria            break;
14933bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
14943bf66744d61d18c66d46f2608de0467ad3df0268Mopria
14953bf66744d61d18c66d46f2608de0467ad3df0268Mopria        response = ippSendRequest(http, request, http_resource);
14963bf66744d61d18c66d46f2608de0467ad3df0268Mopria        if (response == NULL) {
14973bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ipp_status = cupsLastError();
14983bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ipp_status == IPP_INTERNAL_ERROR || ipp_status == HTTP_ERROR) {
14993bf66744d61d18c66d46f2608de0467ad3df0268Mopria                internal_error_retry_count++;
15003bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (internal_error_retry_count > IPP_INTERNAL_ERROR_MAX_RETRIES) {
15013bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    break;
15023bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
15033bf66744d61d18c66d46f2608de0467ad3df0268Mopria
15043bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("ipp_doCupsRequest: %s %d received, retry %d of %d",
15053bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_uri, ipp_status, internal_error_retry_count,
15063bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        IPP_INTERNAL_ERROR_MAX_RETRIES);
15073bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
15083bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ipp_status == IPP_SERVICE_UNAVAILABLE) {
15093bf66744d61d18c66d46f2608de0467ad3df0268Mopria                service_unavailable_retry_count++;
15103bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (service_unavailable_retry_count > IPP_SERVICE_ERROR_MAX_RETRIES) {
15113bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    break;
15123bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
15133bf66744d61d18c66d46f2608de0467ad3df0268Mopria
15143bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("ipp_doCupsRequest: %s IPP_SERVICE_UNAVAILABLE received, retrying %d of %d",
15153bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_uri, service_unavailable_retry_count,
15163bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        IPP_SERVICE_ERROR_MAX_RETRIES);
15173bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
15183bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ipp_status == IPP_BAD_REQUEST) {
15193bf66744d61d18c66d46f2608de0467ad3df0268Mopria                bad_request_retry_count++;
15203bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (bad_request_retry_count > IPP_BAD_REQUEST_MAX_RETRIES) {
15213bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    break;
15223bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
15233bf66744d61d18c66d46f2608de0467ad3df0268Mopria
15243bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGD("ipp_doCupsRequest: %s IPP_BAD_REQUEST received. retry (%d) of (%d)",
15253bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_uri, bad_request_retry_count, IPP_BAD_REQUEST_MAX_RETRIES);
15263bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
15273bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ipp_status == IPP_NOT_FOUND) {
15283bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("ipp_doCupsRequest: %s IPP_NOT_FOUND received.", printer_uri);
15293bf66744d61d18c66d46f2608de0467ad3df0268Mopria                break;
15303bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
15313bf66744d61d18c66d46f2608de0467ad3df0268Mopria        } else {
15323bf66744d61d18c66d46f2608de0467ad3df0268Mopria            ipp_status = cupsLastError();
15333bf66744d61d18c66d46f2608de0467ad3df0268Mopria            if (ipp_status == IPP_BAD_REQUEST) {
15343bf66744d61d18c66d46f2608de0467ad3df0268Mopria                bad_request_retry_count++;
15353bf66744d61d18c66d46f2608de0467ad3df0268Mopria                LOGE("ipp_doCupsRequest: %s IPP_BAD_REQUEST received. retry (%d) of (%d)",
15363bf66744d61d18c66d46f2608de0467ad3df0268Mopria                        printer_uri, bad_request_retry_count, IPP_BAD_REQUEST_MAX_RETRIES);
15373bf66744d61d18c66d46f2608de0467ad3df0268Mopria                if (bad_request_retry_count > IPP_BAD_REQUEST_MAX_RETRIES) {
15383bf66744d61d18c66d46f2608de0467ad3df0268Mopria                    break;
15393bf66744d61d18c66d46f2608de0467ad3df0268Mopria                }
15403bf66744d61d18c66d46f2608de0467ad3df0268Mopria
15413bf66744d61d18c66d46f2608de0467ad3df0268Mopria                ippDelete(response);
15423bf66744d61d18c66d46f2608de0467ad3df0268Mopria                response = NULL;
15433bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
15443bf66744d61d18c66d46f2608de0467ad3df0268Mopria            } else if (ipp_status == IPP_VERSION_NOT_SUPPORTED) {
15453bf66744d61d18c66d46f2608de0467ad3df0268Mopria                ipp_version_supported = IPP_VERSION_UNSUPPORTED;
15463bf66744d61d18c66d46f2608de0467ad3df0268Mopria                ippDelete(response);
15473bf66744d61d18c66d46f2608de0467ad3df0268Mopria                response = NULL;
15483bf66744d61d18c66d46f2608de0467ad3df0268Mopria                continue;
15493bf66744d61d18c66d46f2608de0467ad3df0268Mopria            }
15503bf66744d61d18c66d46f2608de0467ad3df0268Mopria        }
15513bf66744d61d18c66d46f2608de0467ad3df0268Mopria        break;
15523bf66744d61d18c66d46f2608de0467ad3df0268Mopria    } while (1);
15533bf66744d61d18c66d46f2608de0467ad3df0268Mopria
15543bf66744d61d18c66d46f2608de0467ad3df0268Mopria    return response;
15553bf66744d61d18c66d46f2608de0467ad3df0268Mopria}