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-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 67static void _init(const ifc_printer_capabilities_t *this_p, 68 const wprint_connect_info_t *info); 69 70static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p, 71 printer_capabilities_t *capabilities); 72 73static void _destroy(const ifc_printer_capabilities_t *this_p); 74 75static ifc_printer_capabilities_t _capabilities_ifc = { 76 .init = _init, .get_capabilities = _get_capabilities, .get_margins = NULL, 77 .destroy = _destroy, 78}; 79 80typedef struct { 81 http_t *http; 82 printer_capabilities_t printer_caps; 83 ifc_printer_capabilities_t ifc; 84} ipp_capabilities_t; 85 86const 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 100static 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 124static 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 208static 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}