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