8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / print / libipp-core / common / write.c
blobaef693a365df73f062fc26aa8acbec80aec8d2a3
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 /* $Id: write.c 146 2006-03-24 00:26:54Z njacobs $ */
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/types.h>
36 #include <netinet/in.h>
37 #include <inttypes.h>
39 #include <papi.h>
40 #include <ipp.h>
42 static int8_t
43 papi_attribute_to_ipp_type(papi_attribute_value_type_t type)
45 switch (type) {
46 case PAPI_INTEGER:
47 return (VTAG_INTEGER);
48 case PAPI_BOOLEAN:
49 return (VTAG_BOOLEAN);
50 case PAPI_RANGE:
51 return (VTAG_RANGE_OF_INTEGER);
52 case PAPI_RESOLUTION:
53 return (VTAG_RESOLUTION);
54 case PAPI_DATETIME:
55 return (VTAG_DATE_TIME);
56 case PAPI_STRING:
57 return (VTAG_TEXT_WITHOUT_LANGUAGE);
60 return (0);
63 static papi_status_t
64 papi_ipp_type_match(papi_attribute_value_type_t papi, int8_t ipp)
66 switch (papi) {
67 case PAPI_STRING:
68 switch (ipp) {
69 case VTAG_URI:
70 case VTAG_OCTET_STRING:
71 case VTAG_TEXT_WITHOUT_LANGUAGE:
72 case VTAG_URI_SCHEME:
73 case VTAG_CHARSET:
74 case VTAG_NATURAL_LANGUAGE:
75 case VTAG_MIME_MEDIA_TYPE:
76 case VTAG_NAME_WITHOUT_LANGUAGE:
77 case VTAG_KEYWORD:
78 break;
79 default:
80 return (PAPI_CONFLICT);
82 break;
83 case PAPI_INTEGER:
84 switch (ipp) {
85 case VTAG_ENUM:
86 case VTAG_INTEGER:
87 break;
88 default:
89 return (PAPI_CONFLICT);
91 break;
92 case PAPI_BOOLEAN:
93 if (ipp != VTAG_BOOLEAN)
94 return (PAPI_CONFLICT);
95 break;
96 case PAPI_RANGE:
97 if (ipp != VTAG_RANGE_OF_INTEGER)
98 return (PAPI_CONFLICT);
99 break;
100 case PAPI_RESOLUTION:
101 if (ipp != VTAG_RESOLUTION)
102 return (PAPI_CONFLICT);
103 break;
104 case PAPI_DATETIME:
105 if (ipp != VTAG_DATE_TIME)
106 return (PAPI_CONFLICT);
107 break;
108 case PAPI_COLLECTION:
109 /* don't need to match */
110 break;
113 return (PAPI_OK);
116 static papi_status_t
117 ipp_write_attribute(ipp_writer_t iwrite, void *fd, papi_attribute_t *attribute)
119 papi_status_t status;
120 papi_attribute_value_t **values;
121 int8_t type;
122 int i;
123 char *name;
125 name = attribute->name;
126 values = attribute->values;
128 if ((type = name_to_ipp_type(name)) == 0)
129 type = papi_attribute_to_ipp_type(attribute->type);
131 /* The types don't match, so don't send the attribute */
132 if ((status = papi_ipp_type_match(attribute->type, type)) != PAPI_OK)
133 return (status);
135 if (values == NULL) {
136 uint16_t length;
138 type = VTAG_UNSUPPORTED;
139 if (iwrite(fd, &type, 1) != 1)
140 return (PAPI_DEVICE_ERROR);
142 if (name != NULL) { /* first value gets named */
143 length = (uint16_t)htons(strlen(name));
145 if (iwrite(fd, &length, 2) != 2)
146 return (PAPI_DEVICE_ERROR);
147 if (iwrite(fd, name, strlen(name)) != strlen(name))
148 return (PAPI_DEVICE_ERROR);
151 length = (uint16_t)htons(0);
152 if (iwrite(fd, &length, 2) != 2)
153 return (PAPI_DEVICE_ERROR);
155 return (PAPI_OK);
160 for (i = 0; values[i] != NULL; i++) {
161 papi_attribute_value_t *value = values[i];
162 uint16_t length = 0;
164 if (iwrite(fd, &type, 1) != 1)
165 return (PAPI_DEVICE_ERROR);
167 if (name != NULL) { /* first value gets named */
168 length = (uint16_t)htons(strlen(name));
170 if (iwrite(fd, &length, 2) != 2)
171 return (PAPI_DEVICE_ERROR);
172 if (iwrite(fd, name, strlen(name)) != strlen(name))
173 return (PAPI_DEVICE_ERROR);
174 name = NULL;
175 } else {
176 length = (uint16_t)htons(0);
178 if (iwrite(fd, &length, 2) != 2)
179 return (PAPI_DEVICE_ERROR);
182 switch (attribute->type) {
183 case PAPI_STRING: {
184 char *v = (char *)value->string;
186 if (v != NULL) {
187 size_t str_length = strlen(v);
190 * if the length is more than 16 bits can
191 * express, send what can be represented
192 * in 16 bits. IPP "strings" can only be
193 * that large.
195 if (str_length > 0xFFFF)
196 str_length = 0xFFFF;
198 length = (uint16_t)htons(str_length);
199 if (iwrite(fd, &length, 2) != 2)
200 return (PAPI_DEVICE_ERROR);
201 if (iwrite(fd, v, str_length) != str_length)
202 return (PAPI_DEVICE_ERROR);
203 } else
204 if (iwrite(fd, &length, 2) != 2)
205 return (PAPI_DEVICE_ERROR);
207 break;
208 case PAPI_BOOLEAN: {
209 int8_t v = (int8_t)value->boolean;
211 length = (uint16_t)htons(1);
212 if (iwrite(fd, &length, 2) != 2)
213 return (PAPI_DEVICE_ERROR);
214 if (iwrite(fd, &v, 1) != 1)
215 return (PAPI_DEVICE_ERROR);
217 break;
218 case PAPI_INTEGER: {
219 int32_t v = (int32_t)value->integer;
221 length = (uint16_t)htons(4);
222 v = (int32_t)htonl(v);
223 if (iwrite(fd, &length, 2) != 2)
224 return (PAPI_DEVICE_ERROR);
225 if (iwrite(fd, &v, 4) != 4)
226 return (PAPI_DEVICE_ERROR);
228 break;
229 case PAPI_RANGE: {
230 int32_t min = (int32_t)htonl((int)(value->range).lower),
231 max = (int32_t)htonl((int)(value->range).upper);
233 length = (uint16_t)htons(8);
234 if (iwrite(fd, &length, 2) != 2)
235 return (PAPI_DEVICE_ERROR);
236 if (iwrite(fd, &min, 4) != 4)
237 return (PAPI_DEVICE_ERROR);
238 if (iwrite(fd, &max, 4) != 4)
239 return (PAPI_DEVICE_ERROR);
241 break;
242 case PAPI_RESOLUTION: {
243 int32_t x = (int)(value->resolution).xres,
244 y = (int)(value->resolution).yres;
245 int8_t units = (int8_t)(value->resolution).units;
247 length = (uint16_t)htons(9);
248 x = (int32_t)htonl(x);
249 y = (int32_t)htonl(y);
251 if (iwrite(fd, &length, 2) != 2)
252 return (PAPI_DEVICE_ERROR);
253 if (iwrite(fd, &x, 4) != 4)
254 return (PAPI_DEVICE_ERROR);
255 if (iwrite(fd, &y, 4) != 4)
256 return (PAPI_DEVICE_ERROR);
257 if (iwrite(fd, &units, 1) != 1)
258 return (PAPI_DEVICE_ERROR);
260 break;
261 case PAPI_DATETIME: {
262 struct tm *v = gmtime(&value->datetime);
263 int8_t c;
264 uint16_t s;
266 length = (uint16_t)htons(11);
267 if (iwrite(fd, &length, 2) != 2)
268 return (PAPI_DEVICE_ERROR);
269 s = (uint16_t)htons(v->tm_year + 1900);
270 if (iwrite(fd, &s, 2) != 2)
271 return (PAPI_DEVICE_ERROR);
272 c = v->tm_mon + 1;
273 if (iwrite(fd, &c, 1) != 1)
274 return (PAPI_DEVICE_ERROR);
275 c = v->tm_mday;
276 if (iwrite(fd, &c, 1) != 1)
277 return (PAPI_DEVICE_ERROR);
278 c = v->tm_hour;
279 if (iwrite(fd, &c, 1) != 1)
280 return (PAPI_DEVICE_ERROR);
281 c = v->tm_min;
282 if (iwrite(fd, &c, 1) != 1)
283 return (PAPI_DEVICE_ERROR);
284 c = v->tm_sec;
285 if (iwrite(fd, &c, 1) != 1)
286 return (PAPI_DEVICE_ERROR);
287 c = /* v->deciseconds */ 0;
288 if (iwrite(fd, &c, 1) != 1)
289 return (PAPI_DEVICE_ERROR);
290 c = /* v->utc_dir */ 0;
291 if (iwrite(fd, &c, 1) != 1)
292 return (PAPI_DEVICE_ERROR);
293 c = /* v->utc_hours */ 0;
294 if (iwrite(fd, &c, 1) != 1)
295 return (PAPI_DEVICE_ERROR);
296 c = /* v->utc_minutes */ 0;
297 if (iwrite(fd, &c, 1) != 1)
298 return (PAPI_DEVICE_ERROR);
300 break;
301 default: {
303 * If there is a value, it is not one of our
304 * types, so we couldn't use it anyway. We assume
305 * that it was an OOB type with no value
307 length = (uint16_t)htons(0);
308 if (iwrite(fd, &length, 2) != 2)
309 return (PAPI_DEVICE_ERROR);
311 break;
315 return (PAPI_OK);
318 static papi_status_t
319 ipp_write_attribute_group(ipp_writer_t iwrite, void *fd, int8_t type,
320 papi_attribute_t **attributes)
322 papi_status_t result = PAPI_OK;
323 int i;
325 /* write group tag */
326 if (iwrite(fd, &type, 1) != 1)
327 return (PAPI_DEVICE_ERROR);
329 /* write values */
330 for (i = 0; ((attributes[i] != NULL) && (result == PAPI_OK)); i++)
331 result = ipp_write_attribute(iwrite, fd, attributes[i]);
333 return (result);
336 static papi_status_t
337 ipp_write_attribute_groups(ipp_writer_t iwrite, void *fd,
338 papi_attribute_t **groups)
340 papi_status_t result = PAPI_OK;
341 int8_t c;
343 for (c = DTAG_MIN; c <= DTAG_MAX; c++) {
344 papi_status_t status;
345 papi_attribute_t **group = NULL;
346 void *iter = NULL;
347 char name[32];
349 (void) ipp_tag_string(c, name, sizeof (name));
350 for (status = papiAttributeListGetCollection(groups, &iter,
351 name, &group);
352 ((status == PAPI_OK) && (result == PAPI_OK));
353 status = papiAttributeListGetCollection(groups, &iter,
354 NULL, &group))
355 result = ipp_write_attribute_group(iwrite, fd,
356 c, group);
359 c = DTAG_END_OF_ATTRIBUTES;
360 if (iwrite(fd, &c, 1) != 1)
361 result = PAPI_DEVICE_ERROR;
363 return (result);
366 static papi_status_t
367 ipp_write_message_header(ipp_writer_t iwrite, void *fd,
368 papi_attribute_t **message)
370 int tmp;
371 int8_t c;
372 uint16_t s;
373 int32_t i;
375 /* write the version */
376 papiAttributeListGetInteger(message, NULL, "version-major", &tmp);
377 c = tmp;
378 if (iwrite(fd, &c, 1) != 1)
379 return (PAPI_DEVICE_ERROR);
381 papiAttributeListGetInteger(message, NULL, "version-minor", &tmp);
382 c = tmp;
383 if (iwrite(fd, &c, 1) != 1)
384 return (PAPI_DEVICE_ERROR);
386 /* write the request/status code */
387 papiAttributeListGetInteger(message, NULL, "status-code", &tmp);
388 papiAttributeListGetInteger(message, NULL, "operation-id", &tmp);
389 s = (uint16_t)htons(tmp);
390 if (iwrite(fd, &s, 2) != 2)
391 return (PAPI_DEVICE_ERROR);
393 /* write the request id */
394 papiAttributeListGetInteger(message, NULL, "request-id", &tmp);
395 i = (uint32_t)htonl(tmp);
396 if (iwrite(fd, &i, 4) != 4)
397 return (PAPI_DEVICE_ERROR);
399 return (PAPI_OK);
402 papi_status_t
403 ipp_write_message(ipp_writer_t iwrite, void *fd, papi_attribute_t **message)
405 papi_status_t result;
407 if ((iwrite == NULL) || (fd == NULL) || (message == NULL))
408 return (PAPI_BAD_ARGUMENT);
410 result = ipp_write_message_header(iwrite, fd, message);
411 if (result == PAPI_OK)
412 result = ipp_write_attribute_groups(iwrite, fd, message);
414 return (result);