Home | History | Annotate | Download | only in ipphelper
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  * Copyright (C) 2016 Mopria Alliance, Inc.
      4  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *      http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 
     19 #include <stdint.h>
     20 #include <stdlib.h>
     21 #include <stdio.h>
     22 #include "lib_wprint.h"
     23 #include "ippstatus_capabilities.h"   // move these to above the calls to cups files
     24 #include "ipphelper.h"
     25 #include "cups.h"
     26 #include "http-private.h"
     27 #include "wprint_debug.h"
     28 
     29 #define TAG "ippstatus_capabilities"
     30 
     31 /*
     32  * Requested printer attributes
     33  */
     34 static const char *pattrs[] = {
     35         "ipp-versions-supported",
     36         "printer-make-and-model",
     37         "printer-name",
     38         "printer-location",
     39         "printer-uuid",
     40         "printer-uri-supported",
     41         "uri-security-supported",
     42         "uri-authentication-supported",
     43         "color-supported",
     44         "copies-supported",
     45         "document-format-supported",
     46         "media-col-default",
     47         "media-default",
     48         "media-left-margin-supported",
     49         "media-right-margin-supported",
     50         "media-top-margin-supported",
     51         "media-bottom-margin-supported",
     52         "media-supported",
     53         "media-type-supported",
     54         "output-bin-supported",
     55         "print-color-mode-supported",
     56         "printer-resolution-supported",
     57         "sides-supported",
     58         "printer-device-id",
     59         "epcl-version-supported",
     60         "pclm-raster-back-side",
     61         "pclm-strip-height-preferred",
     62         "pclm-compression-method-preferred",
     63         "pclm-source-resolution-supported",
     64         "document-format-details-supported"
     65 };
     66 
     67 static void _init(const ifc_printer_capabilities_t *this_p,
     68         const wprint_connect_info_t *info);
     69 
     70 static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p,
     71         printer_capabilities_t *capabilities);
     72 
     73 static void _destroy(const ifc_printer_capabilities_t *this_p);
     74 
     75 static ifc_printer_capabilities_t _capabilities_ifc = {
     76         .init = _init, .get_capabilities = _get_capabilities, .get_margins = NULL,
     77         .destroy = _destroy,
     78 };
     79 
     80 typedef struct {
     81     http_t *http;
     82     printer_capabilities_t printer_caps;
     83     ifc_printer_capabilities_t ifc;
     84 } ipp_capabilities_t;
     85 
     86 const ifc_printer_capabilities_t *ipp_status_get_capabilities_ifc(const ifc_wprint_t *wprint_ifc) {
     87     LOGD("ipp_status_get_capabilities_ifc: Enter");
     88     ipp_capabilities_t *caps = (ipp_capabilities_t *) malloc(sizeof(ipp_capabilities_t));
     89     if (caps == NULL) {
     90         return NULL;
     91     }
     92 
     93     memset(caps, 0, sizeof(ipp_capabilities_t));
     94     caps->http = NULL;
     95 
     96     memcpy(&caps->ifc, &_capabilities_ifc, sizeof(ifc_printer_capabilities_t));
     97     return &caps->ifc;
     98 }
     99 
    100 static void _init(const ifc_printer_capabilities_t *this_p,
    101         const wprint_connect_info_t *connect_info) {
    102     LOGD("_init: Enter");
    103     ipp_capabilities_t *caps;
    104     do {
    105         if (this_p == NULL) {
    106             continue;
    107         }
    108         caps = IMPL(ipp_capabilities_t, ifc, this_p);
    109 
    110         if (caps->http != NULL) {
    111             LOGD("_init(): http != NULL closing HTTP");
    112             httpClose(caps->http);
    113         }
    114 
    115         caps->http = ipp_cups_connect(connect_info, caps->printer_caps.printerUri,
    116                 sizeof(caps->printer_caps.printerUri));
    117         getResourceFromURI(caps->printer_caps.printerUri, caps->printer_caps.httpResource, 1024);
    118         if (caps->http == NULL) {
    119             LOGE("_init(): http is NULL ");
    120         }
    121     } while (0);
    122 }
    123 
    124 static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p,
    125         printer_capabilities_t *capabilities) {
    126     LOGD("_get_capabilities: Enter");
    127     status_t result = ERROR;
    128     ipp_capabilities_t *caps = NULL;
    129     ipp_t *request = NULL; // IPP request object
    130     ipp_t *response = NULL; // IPP response object
    131     ipp_attribute_t *attrptr; // Attribute pointer
    132     int op = IPP_GET_PRINTER_ATTRIBUTES;
    133 
    134     ipp_status_t ipp_status; // Status of IPP request
    135 
    136     if (capabilities != NULL) {
    137         memset(capabilities, 0, sizeof(printer_capabilities_t));
    138     }
    139 
    140     do {
    141         if (this_p == NULL) {
    142             break;
    143         }
    144 
    145         caps = IMPL(ipp_capabilities_t, ifc, this_p);
    146         if (caps->http == NULL) {
    147             LOGD("_get_capabilities: caps->http is NULL");
    148             break;
    149         }
    150 
    151         request = ippNewRequest(op);
    152 
    153         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
    154                 caps->printer_caps.printerUri);
    155 
    156         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes",
    157                 sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
    158 
    159         LOGD("IPP_GET_PRINTER_ATTRIBUTES %s request:", ippOpString(op));
    160         for (attrptr = ippFirstAttribute(request); attrptr; attrptr = ippNextAttribute(request)) {
    161             print_attr(attrptr);
    162         }
    163 
    164         response = ipp_doCupsRequest(caps->http, request, caps->printer_caps.httpResource,
    165                 caps->printer_caps.printerUri);
    166         if (response == NULL) {
    167             ipp_status = cupsLastError();
    168             LOGE("_get_capabilities: %s response is null:  ipp_status %d %s",
    169                     caps->printer_caps.printerUri, ipp_status, ippErrorString(ipp_status));
    170         } else {
    171             ipp_status = cupsLastError();
    172             LOGD("ipp CUPS last ERROR: %d, %s", ipp_status, ippErrorString(ipp_status));
    173             LOGD("%s received, now call parse_printerAttributes:", ippOpString(op));
    174             parse_printerAttributes(response, capabilities);
    175 
    176 #if LOG_LEVEL <= LEVEL_DEBUG
    177             for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(
    178                     response)) {
    179                 print_attr(attrptr);
    180             }
    181 #endif // LOG_LEVEL <= LEVEL_DEBUG
    182             if ((attrptr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) == NULL) {
    183                 LOGD("printer-state: null");
    184             } else {
    185                 LOGI("printer-state %d", (ipp_pstate_t) ippGetInteger(attrptr, 0));
    186             }
    187         }
    188 
    189         if (ipp_status >= IPP_OK && ipp_status < IPP_REDIRECTION_OTHER_SITE && response != NULL) {
    190             result = OK;
    191         } else {
    192             result = ERROR;
    193         }
    194     } while (0);
    195 
    196     ippDelete(response);
    197     ippDelete(request);
    198 
    199     if ((caps != NULL) && (capabilities != NULL)) {
    200         memcpy(capabilities->httpResource, caps->printer_caps.httpResource,
    201                 sizeof(capabilities->httpResource));
    202     }
    203 
    204     LOGI(" ippstatus_capabilities: _get_capabilities: returning %d:", result);
    205     return result;
    206 }
    207 
    208 static void _destroy(const ifc_printer_capabilities_t *this_p) {
    209     ipp_capabilities_t *caps;
    210     LOGD("_destroy(): enter");
    211     do {
    212         if (this_p == NULL) {
    213             continue;
    214         }
    215 
    216         caps = IMPL(ipp_capabilities_t, ifc, this_p);
    217         if (caps->http != NULL) {
    218             httpClose(caps->http);
    219         }
    220         free(caps);
    221     } while (0);
    222 }