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 }