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 #include "com_android_bips_flags.h"
29
30 #define TAG "ippstatus_capabilities"
31
32 /*
33 * Requested printer attributes
34 */
35 static const char *pattrs[] = {
36 "ipp-versions-supported",
37 "printer-make-and-model",
38 "printer-info",
39 "printer-dns-sd-name",
40 "printer-name",
41 "printer-location",
42 "printer-uuid",
43 "printer-uri-supported",
44 "uri-security-supported",
45 "uri-authentication-supported",
46 "color-supported",
47 "copies-supported",
48 "document-format-supported",
49 "media-col-default",
50 "media-default",
51 "media-left-margin-supported",
52 "media-right-margin-supported",
53 "media-top-margin-supported",
54 "media-bottom-margin-supported",
55 "media-supported",
56 "media-type-supported",
57 "output-bin-supported",
58 "print-color-mode-supported",
59 "print-quality-supported",
60 "printer-output-tray",
61 "printer-resolution-supported",
62 "sides-supported",
63 "printer-device-id",
64 "epcl-version-supported",
65 "pclm-raster-back-side",
66 "pclm-strip-height-preferred",
67 "pclm-compression-method-preferred",
68 "pclm-source-resolution-supported",
69 "pwg-raster-document-sheet-back",
70 "document-format-details-supported",
71 "media-ready",
72 "media-col-ready",
73 "print-scaling-supported",
74 "print-scaling-default",
75 "job-pages-per-set-supported",
76 "mopria-certified"
77 };
78
79 /*
80 * Requested printer attributes including printer info
81 */
82 static const char *pattrs_printer_info[] = {
83 "ipp-versions-supported",
84 "printer-make-and-model",
85 "printer-info",
86 "printer-dns-sd-name",
87 "printer-name",
88 "printer-location",
89 "printer-uuid",
90 "printer-uri-supported",
91 "uri-security-supported",
92 "uri-authentication-supported",
93 "color-supported",
94 "copies-supported",
95 "document-format-supported",
96 "media-col-default",
97 "media-default",
98 "media-left-margin-supported",
99 "media-right-margin-supported",
100 "media-top-margin-supported",
101 "media-bottom-margin-supported",
102 "media-supported",
103 "media-type-supported",
104 "output-bin-supported",
105 "print-color-mode-supported",
106 "print-quality-supported",
107 "printer-output-tray",
108 "printer-resolution-supported",
109 "sides-supported",
110 "printer-device-id",
111 "epcl-version-supported",
112 "pclm-raster-back-side",
113 "pclm-strip-height-preferred",
114 "pclm-compression-method-preferred",
115 "pclm-source-resolution-supported",
116 "pwg-raster-document-sheet-back",
117 "document-format-details-supported",
118 "media-ready",
119 "media-col-ready",
120 "print-scaling-supported",
121 "print-scaling-default",
122 "job-pages-per-set-supported",
123 "mopria-certified",
124 "marker-colors",
125 "marker-high-levels",
126 "marker-levels",
127 "marker-low-levels",
128 "marker-names",
129 "marker-types",
130 "printer-icons"
131 };
132
133 static void _init(const ifc_printer_capabilities_t *this_p,
134 const wprint_connect_info_t *info);
135
136 static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p,
137 printer_capabilities_t *capabilities);
138
139 static void _destroy(const ifc_printer_capabilities_t *this_p);
140
141 static ifc_printer_capabilities_t _capabilities_ifc = {
142 .init = _init, .get_capabilities = _get_capabilities, .get_margins = NULL,
143 .destroy = _destroy,
144 };
145
146 typedef struct {
147 http_t *http;
148 printer_capabilities_t printer_caps;
149 ifc_printer_capabilities_t ifc;
150 } ipp_capabilities_t;
151
ipp_status_get_capabilities_ifc(const ifc_wprint_t * wprint_ifc)152 const ifc_printer_capabilities_t *ipp_status_get_capabilities_ifc(const ifc_wprint_t *wprint_ifc) {
153 LOGD("ipp_status_get_capabilities_ifc: Enter");
154 ipp_capabilities_t *caps = (ipp_capabilities_t *) malloc(sizeof(ipp_capabilities_t));
155 if (caps == NULL) {
156 return NULL;
157 }
158
159 memset(caps, 0, sizeof(ipp_capabilities_t));
160 caps->http = NULL;
161
162 memcpy(&caps->ifc, &_capabilities_ifc, sizeof(ifc_printer_capabilities_t));
163 return &caps->ifc;
164 }
165
_init(const ifc_printer_capabilities_t * this_p,const wprint_connect_info_t * connect_info)166 static void _init(const ifc_printer_capabilities_t *this_p,
167 const wprint_connect_info_t *connect_info) {
168 LOGD("_init: Enter");
169 ipp_capabilities_t *caps;
170 do {
171 if (this_p == NULL) {
172 continue;
173 }
174 caps = IMPL(ipp_capabilities_t, ifc, this_p);
175
176 if (caps->http != NULL) {
177 LOGD("_init(): http != NULL closing HTTP");
178 httpClose(caps->http);
179 }
180
181 caps->http = ipp_cups_connect(connect_info, caps->printer_caps.printerUri,
182 sizeof(caps->printer_caps.printerUri));
183 getResourceFromURI(caps->printer_caps.printerUri, caps->printer_caps.httpResource, 1024);
184 if (caps->http == NULL) {
185 LOGE("_init(): http is NULL ");
186 }
187 } while (0);
188 }
189
_get_capabilities(const ifc_printer_capabilities_t * this_p,printer_capabilities_t * capabilities)190 static status_t _get_capabilities(const ifc_printer_capabilities_t *this_p,
191 printer_capabilities_t *capabilities) {
192 LOGD("_get_capabilities: Enter");
193 status_t result = ERROR;
194 ipp_capabilities_t *caps = NULL;
195 ipp_t *request = NULL; // IPP request object
196 ipp_t *response = NULL; // IPP response object
197 ipp_attribute_t *attrptr; // Attribute pointer
198 int op = IPP_GET_PRINTER_ATTRIBUTES;
199
200 ipp_status_t ipp_status; // Status of IPP request
201
202 if (capabilities != NULL) {
203 memset(capabilities, 0, sizeof(printer_capabilities_t));
204 }
205
206 do {
207 if (this_p == NULL) {
208 break;
209 }
210
211 caps = IMPL(ipp_capabilities_t, ifc, this_p);
212 if (caps->http == NULL) {
213 LOGD("_get_capabilities: caps->http is NULL");
214 break;
215 }
216
217 request = ippNewRequest(op);
218
219 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
220 caps->printer_caps.printerUri);
221
222 if (com_android_bips_flags_printer_info_details()) {
223 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes",
224 sizeof(pattrs_printer_info) / sizeof(pattrs_printer_info[0]), NULL,
225 pattrs_printer_info);
226 } else {
227 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes",
228 sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs);
229 }
230
231 LOGD("IPP_GET_PRINTER_ATTRIBUTES %s request:", ippOpString(op));
232 for (attrptr = ippFirstAttribute(request); attrptr; attrptr = ippNextAttribute(request)) {
233 print_attr(attrptr);
234 }
235
236 response = ipp_doCupsRequest(caps->http, request, caps->printer_caps.httpResource,
237 caps->printer_caps.printerUri);
238 if (response == NULL) {
239 ipp_status = cupsLastError();
240 LOGE("_get_capabilities: %s response is null: ipp_status %d %s",
241 caps->printer_caps.printerUri, ipp_status, ippErrorString(ipp_status));
242 } else {
243 ipp_status = cupsLastError();
244 LOGD("ipp CUPS last ERROR: %d, %s", ipp_status, ippErrorString(ipp_status));
245 LOGD("%s received, now call parse_printerAttributes:", ippOpString(op));
246 parse_printerAttributes(response, capabilities);
247
248 #if LOG_LEVEL <= LEVEL_DEBUG
249 for (attrptr = ippFirstAttribute(response); attrptr; attrptr = ippNextAttribute(
250 response)) {
251 print_attr(attrptr);
252 }
253 #endif // LOG_LEVEL <= LEVEL_DEBUG
254 if ((attrptr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) == NULL) {
255 LOGD("printer-state: null");
256 } else {
257 LOGI("printer-state %d", (ipp_pstate_t) ippGetInteger(attrptr, 0));
258 }
259 }
260
261 if (ipp_status >= IPP_OK && ipp_status < IPP_REDIRECTION_OTHER_SITE && response != NULL) {
262 result = OK;
263 } else {
264 result = ERROR;
265 }
266 } while (0);
267
268 ippDelete(response);
269 ippDelete(request);
270
271 if ((caps != NULL) && (capabilities != NULL)) {
272 memcpy(capabilities->httpResource, caps->printer_caps.httpResource,
273 sizeof(capabilities->httpResource));
274 }
275
276 LOGI(" ippstatus_capabilities: _get_capabilities: returning %d:", result);
277 return result;
278 }
279
_destroy(const ifc_printer_capabilities_t * this_p)280 static void _destroy(const ifc_printer_capabilities_t *this_p) {
281 ipp_capabilities_t *caps;
282 LOGD("_destroy(): enter");
283 do {
284 if (this_p == NULL) {
285 continue;
286 }
287
288 caps = IMPL(ipp_capabilities_t, ifc, this_p);
289 if (caps->http != NULL) {
290 httpClose(caps->http);
291 }
292 free(caps);
293 } while (0);
294 }