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
ipp_status_get_capabilities_ifc(const ifc_wprint_t * wprint_ifc)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
_init(const ifc_printer_capabilities_t * this_p,const wprint_connect_info_t * connect_info)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
_get_capabilities(const ifc_printer_capabilities_t * this_p,printer_capabilities_t * capabilities)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
_destroy(const ifc_printer_capabilities_t * this_p)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 }