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 */ 34static const char *pattrs[] = { 35 "ipp-versions-supported", 36 "printer-make-and-model", 37 "printer-info", 38 "printer-dns-sd-name", 39 "printer-name", 40 "printer-location", 41 "printer-uuid", 42 "printer-uri-supported", 43 "uri-security-supported", 44 "uri-authentication-supported", 45 "color-supported", 46 "copies-supported", 47 "document-format-supported", 48 "media-col-default", 49 "media-default", 50 "media-left-margin-supported", 51 "media-right-margin-supported", 52 "media-top-margin-supported", 53 "media-bottom-margin-supported", 54 "media-supported", 55 "media-type-supported", 56 "output-bin-supported", 57 "print-color-mode-supported", 58 "printer-resolution-supported", 59 "sides-supported", 60 "printer-device-id", 61 "epcl-version-supported", 62 "pclm-raster-back-side", 63 "pclm-strip-height-preferred", 64 "pclm-compression-method-preferred", 65 "pclm-source-resolution-supported", 66 "document-format-details-supported" 67}; 68 69static void _init(const ifc_printer_capabilities_t *this_p, 70 const wprint_connect_info_t *info); 71 72static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p, 73 printer_capabilities_t *capabilities); 74 75static void _destroy(const ifc_printer_capabilities_t *this_p); 76 77static ifc_printer_capabilities_t _capabilities_ifc = { 78 .init = _init, .get_capabilities = _get_capabilities, .get_margins = NULL, 79 .destroy = _destroy, 80}; 81 82typedef struct { 83 http_t *http; 84 printer_capabilities_t printer_caps; 85 ifc_printer_capabilities_t ifc; 86} ipp_capabilities_t; 87 88const ifc_printer_capabilities_t *ipp_status_get_capabilities_ifc(const ifc_wprint_t *wprint_ifc) { 89 LOGD("ipp_status_get_capabilities_ifc: Enter"); 90 ipp_capabilities_t *caps = (ipp_capabilities_t *) malloc(sizeof(ipp_capabilities_t)); 91 if (caps == NULL) { 92 return NULL; 93 } 94 95 memset(caps, 0, sizeof(ipp_capabilities_t)); 96 caps->http = NULL; 97 98 memcpy(&caps->ifc, &_capabilities_ifc, sizeof(ifc_printer_capabilities_t)); 99 return &caps->ifc; 100} 101 102static void _init(const ifc_printer_capabilities_t *this_p, 103 const wprint_connect_info_t *connect_info) { 104 LOGD("_init: Enter"); 105 ipp_capabilities_t *caps; 106 do { 107 if (this_p == NULL) { 108 continue; 109 } 110 caps = IMPL(ipp_capabilities_t, ifc, this_p); 111 112 if (caps->http != NULL) { 113 LOGD("_init(): http != NULL closing HTTP"); 114 httpClose(caps->http); 115 } 116 117 caps->http = ipp_cups_connect(connect_info, caps->printer_caps.printerUri, 118 sizeof(caps->printer_caps.printerUri)); 119 getResourceFromURI(caps->printer_caps.printerUri, caps->printer_caps.httpResource, 1024); 120 if (caps->http == NULL) { 121 LOGE("_init(): http is NULL "); 122 } 123 } while (0); 124} 125 126static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p, 127 printer_capabilities_t *capabilities) { 128 LOGD("_get_capabilities: Enter"); 129 status_t result = ERROR; 130 ipp_capabilities_t *caps = NULL; 131 ipp_t *request = NULL; // IPP request object 132 ipp_t *response = NULL; // IPP response object 133 ipp_attribute_t *attrptr; // Attribute pointer 134 int op = IPP_GET_PRINTER_ATTRIBUTES; 135 136 ipp_status_t ipp_status; // Status of IPP request 137 138 if (capabilities != NULL) { 139 memset(capabilities, 0, sizeof(printer_capabilities_t)); 140 } 141 142 do { 143 if (this_p == NULL) { 144 break; 145 } 146 147 caps = IMPL(ipp_capabilities_t, ifc, this_p); 148 if (caps->http == NULL) { 149 LOGD("_get_capabilities: caps->http is NULL"); 150 break; 151 } 152 153 request = ippNewRequest(op); 154 155 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, 156 caps->printer_caps.printerUri); 157 158 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", 159 sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs); 160 161 LOGD("IPP_GET_PRINTER_ATTRIBUTES %s request:", ippOpString(op)); 162 for (attrptr = ippFirstAttribute(request); attrptr; attrptr = ippNextAttribute(request)) { 163 print_attr(attrptr); 164 } 165 166 response = ipp_doCupsRequest(caps->http, request, caps->printer_caps.httpResource, 167 caps->printer_caps.printerUri); 168 if (response == NULL) { 169 ipp_status = cupsLastError(); 170 LOGE("_get_capabilities: %s response is null: ipp_status %d %s", 171 caps->printer_caps.printerUri, ipp_status, ippErrorString(ipp_status)); 172 } else { 173 ipp_status = cupsLastError(); 174 LOGD("ipp CUPS last ERROR: %d, %s", ipp_status, ippErrorString(ipp_status)); 175 LOGD("%s received, now call parse_printerAttributes:", ippOpString(op)); 176 parse_printerAttributes(response, capabilities); 177 178#if LOG_LEVEL <= LEVEL_DEBUG 179 for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute( 180 response)) { 181 print_attr(attrptr); 182 } 183#endif // LOG_LEVEL <= LEVEL_DEBUG 184 if ((attrptr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) == NULL) { 185 LOGD("printer-state: null"); 186 } else { 187 LOGI("printer-state %d", (ipp_pstate_t) ippGetInteger(attrptr, 0)); 188 } 189 } 190 191 if (ipp_status >= IPP_OK && ipp_status < IPP_REDIRECTION_OTHER_SITE && response != NULL) { 192 result = OK; 193 } else { 194 result = ERROR; 195 } 196 } while (0); 197 198 ippDelete(response); 199 ippDelete(request); 200 201 if ((caps != NULL) && (capabilities != NULL)) { 202 memcpy(capabilities->httpResource, caps->printer_caps.httpResource, 203 sizeof(capabilities->httpResource)); 204 } 205 206 LOGI(" ippstatus_capabilities: _get_capabilities: returning %d:", result); 207 return result; 208} 209 210static void _destroy(const ifc_printer_capabilities_t *this_p) { 211 ipp_capabilities_t *caps; 212 LOGD("_destroy(): enter"); 213 do { 214 if (this_p == NULL) { 215 continue; 216 } 217 218 caps = IMPL(ipp_capabilities_t, ifc, this_p); 219 if (caps->http != NULL) { 220 httpClose(caps->http); 221 } 222 free(caps); 223 } while (0); 224}