2 * "$Id: snmp-supplies.c 10262 2012-02-12 05:48:09Z mike $"
4 * SNMP supplies functions for CUPS.
6 * Copyright 2008-2012 by Apple Inc.
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged, see the license at "http://www.cups.org/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * backendSNMPSupplies() - Get the current supplies for a device.
19 * backend_init_supplies() - Initialize the supplies list.
20 * backend_walk_cb() - Interpret the supply value responses.
21 * utf16_to_utf8() - Convert UTF-16 text to UTF-8.
25 * Include necessary headers.
28 #include "backend-private.h"
29 #include <cups/array.h>
36 #define CUPS_MAX_SUPPLIES 32 /* Maximum number of supplies for a printer */
37 #define CUPS_SUPPLY_TIMEOUT 2.0 /* Timeout for SNMP lookups */
39 #define CUPS_DEVELOPER_LOW 1
40 #define CUPS_DEVELOPER_EMPTY 2
41 #define CUPS_MARKER_SUPPLY_LOW 4
42 #define CUPS_MARKER_SUPPLY_EMPTY 8
43 #define CUPS_OPC_NEAR_EOL 16
44 #define CUPS_OPC_LIFE_OVER 32
45 #define CUPS_TONER_LOW 64
46 #define CUPS_TONER_EMPTY 128
53 typedef struct /**** Printer supply data ****/
55 char name[CUPS_SNMP_MAX_STRING], /* Name of supply */
56 color[8]; /* Color: "#RRGGBB" or "none" */
57 int colorant, /* Colorant index */
58 type, /* Supply type */
59 max_capacity, /* Maximum capacity */
60 level; /* Current level value */
63 typedef struct /**** Printer state table ****/
65 int bit; /* State bit */
66 const char *keyword; /* IPP printer-state-reasons keyword */
74 static http_addr_t current_addr; /* Current address */
75 static int current_state = -1;
76 /* Current device state bits */
77 static int charset = -1; /* Character set for supply names */
78 static int num_supplies = 0;
79 /* Number of supplies found */
80 static backend_supplies_t supplies[CUPS_MAX_SUPPLIES];
81 /* Supply information */
82 static int supply_state = -1;
83 /* Supply state info */
85 static const int hrDeviceDescr[] =
86 { CUPS_OID_hrDeviceDescr, 1, -1 };
87 /* Device description OID */
88 static const int hrPrinterStatus[] =
89 { CUPS_OID_hrPrinterStatus, 1, -1 };
90 /* Current state OID */
91 static const int hrPrinterDetectedErrorState[] =
92 { CUPS_OID_hrPrinterDetectedErrorState, 1, -1 };
93 /* Current printer state bits OID */
94 static const int prtGeneralCurrentLocalization[] =
95 { CUPS_OID_prtGeneralCurrentLocalization, 1, -1 };
96 static const int prtLocalizationCharacterSet[] =
97 { CUPS_OID_prtLocalizationCharacterSet, 1, 1, -1 },
98 prtLocalizationCharacterSetOffset =
99 (sizeof(prtLocalizationCharacterSet) /
100 sizeof(prtLocalizationCharacterSet[0]));
101 static const int prtMarkerColorantValue[] =
102 { CUPS_OID_prtMarkerColorantValue, -1 },
104 prtMarkerColorantValueOffset =
105 (sizeof(prtMarkerColorantValue) /
106 sizeof(prtMarkerColorantValue[0]));
107 /* Offset to colorant index */
108 static const int prtMarkerLifeCount[] =
109 { CUPS_OID_prtMarkerLifeCount, 1, 1, -1 };
110 /* Page counter OID */
111 static const int prtMarkerSuppliesEntry[] =
112 { CUPS_OID_prtMarkerSuppliesEntry, -1 };
114 static const int prtMarkerSuppliesColorantIndex[] =
115 { CUPS_OID_prtMarkerSuppliesColorantIndex, -1 },
116 /* Colorant index OID */
117 prtMarkerSuppliesColorantIndexOffset =
118 (sizeof(prtMarkerSuppliesColorantIndex) /
119 sizeof(prtMarkerSuppliesColorantIndex[0]));
120 /* Offset to supply index */
121 static const int prtMarkerSuppliesDescription[] =
122 { CUPS_OID_prtMarkerSuppliesDescription, -1 },
123 /* Description OID */
124 prtMarkerSuppliesDescriptionOffset =
125 (sizeof(prtMarkerSuppliesDescription) /
126 sizeof(prtMarkerSuppliesDescription[0]));
127 /* Offset to supply index */
128 static const int prtMarkerSuppliesLevel[] =
129 { CUPS_OID_prtMarkerSuppliesLevel, -1 },
131 prtMarkerSuppliesLevelOffset =
132 (sizeof(prtMarkerSuppliesLevel) /
133 sizeof(prtMarkerSuppliesLevel[0]));
134 /* Offset to supply index */
135 static const int prtMarkerSuppliesMaxCapacity[] =
136 { CUPS_OID_prtMarkerSuppliesMaxCapacity, -1 },
137 /* Max capacity OID */
138 prtMarkerSuppliesMaxCapacityOffset =
139 (sizeof(prtMarkerSuppliesMaxCapacity) /
140 sizeof(prtMarkerSuppliesMaxCapacity[0]));
141 /* Offset to supply index */
142 static const int prtMarkerSuppliesType[] =
143 { CUPS_OID_prtMarkerSuppliesType, -1 },
145 prtMarkerSuppliesTypeOffset =
146 (sizeof(prtMarkerSuppliesType) /
147 sizeof(prtMarkerSuppliesType[0]));
148 /* Offset to supply index */
150 static const backend_state_t const printer_states[] =
152 { CUPS_TC_lowPaper, "media-low-report" },
153 { CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty, "media-empty-warning" },
154 /* { CUPS_TC_lowToner, "toner-low-report" }, */ /* now use prtMarkerSupplies */
155 /* { CUPS_TC_noToner, "toner-empty-warning" }, */ /* now use prtMarkerSupplies */
156 { CUPS_TC_doorOpen, "door-open-report" },
157 { CUPS_TC_jammed, "media-jam-warning" },
158 /* { CUPS_TC_offline, "offline-report" }, */ /* unreliable */
159 /* { CUPS_TC_serviceRequested | CUPS_TC_overduePreventMaint, "service-needed-warning" }, */ /* unreliable */
160 { CUPS_TC_inputTrayMissing, "input-tray-missing-warning" },
161 { CUPS_TC_outputTrayMissing, "output-tray-missing-warning" },
162 { CUPS_TC_markerSupplyMissing, "marker-supply-missing-warning" },
163 { CUPS_TC_outputNearFull, "output-area-almost-full-report" },
164 { CUPS_TC_outputFull, "output-area-full-warning" }
167 static const backend_state_t const supply_states[] =
169 { CUPS_DEVELOPER_LOW, "developer-low-report" },
170 { CUPS_DEVELOPER_EMPTY, "developer-empty-warning" },
171 { CUPS_MARKER_SUPPLY_LOW, "marker-supply-low-report" },
172 { CUPS_MARKER_SUPPLY_EMPTY, "marker-supply-empty-warning" },
173 { CUPS_OPC_NEAR_EOL, "opc-near-eol-report" },
174 { CUPS_OPC_LIFE_OVER, "opc-life-over-warning" },
175 { CUPS_TONER_LOW, "toner-low-report" },
176 { CUPS_TONER_EMPTY, "toner-empty-warning" }
184 static void backend_init_supplies(int snmp_fd, http_addr_t *addr);
185 static void backend_walk_cb(cups_snmp_t *packet, void *data);
186 static void utf16_to_utf8(cups_utf8_t *dst, const unsigned char *src,
187 size_t srcsize, size_t dstsize, int le);
191 * 'backendSNMPSupplies()' - Get the current supplies for a device.
194 int /* O - 0 on success, -1 on error */
196 int snmp_fd, /* I - SNMP socket */
197 http_addr_t *addr, /* I - Printer address */
198 int *page_count, /* O - Page count */
199 int *printer_state) /* O - Printer state */
201 if (!httpAddrEqual(addr, ¤t_addr))
202 backend_init_supplies(snmp_fd, addr);
203 else if (num_supplies > 0)
204 _cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1,
205 _cupsSNMPDefaultCommunity(), prtMarkerSuppliesLevel,
206 CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
214 if (num_supplies > 0)
216 int i, /* Looping var */
217 percent, /* Percent full */
218 new_state, /* New state value */
219 change_state, /* State change */
220 new_supply_state = 0; /* Supply state */
221 char value[CUPS_MAX_SUPPLIES * 4],
222 /* marker-levels value string */
223 *ptr; /* Pointer into value string */
224 cups_snmp_t packet; /* SNMP response packet */
227 * Generate the marker-levels value string...
230 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
232 if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
233 percent = 100 * supplies[i].level / supplies[i].max_capacity;
239 switch (supplies[i].type)
242 case CUPS_TC_tonerCartridge :
244 new_supply_state |= CUPS_TONER_EMPTY;
246 new_supply_state |= CUPS_TONER_LOW;
248 case CUPS_TC_wasteToner :
249 case CUPS_TC_wasteInk :
252 case CUPS_TC_inkCartridge :
253 case CUPS_TC_inkRibbon :
254 case CUPS_TC_solidWax :
255 case CUPS_TC_ribbonWax :
257 new_supply_state |= CUPS_MARKER_SUPPLY_EMPTY;
259 new_supply_state |= CUPS_MARKER_SUPPLY_LOW;
261 case CUPS_TC_developer :
263 new_supply_state |= CUPS_DEVELOPER_EMPTY;
265 new_supply_state |= CUPS_DEVELOPER_LOW;
267 case CUPS_TC_coronaWire :
270 case CUPS_TC_transferUnit :
272 new_supply_state |= CUPS_OPC_LIFE_OVER;
274 new_supply_state |= CUPS_OPC_NEAR_EOL;
282 if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
283 sprintf(ptr, "%d", percent);
288 fprintf(stderr, "ATTR: marker-levels=%s\n", value);
290 if (supply_state < 0)
291 change_state = 0xffff;
293 change_state = supply_state ^ new_supply_state;
295 fprintf(stderr, "DEBUG: new_supply_state=%x, change_state=%x\n",
296 new_supply_state, change_state);
299 i < (int)(sizeof(supply_states) / sizeof(supply_states[0]));
301 if (change_state & supply_states[i].bit)
303 fprintf(stderr, "STATE: %c%s\n",
304 (new_supply_state & supply_states[i].bit) ? '+' : '-',
305 supply_states[i].keyword);
308 supply_state = new_supply_state;
311 * Get the current printer status bits...
314 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
315 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
316 hrPrinterDetectedErrorState))
319 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
320 packet.object_type != CUPS_ASN1_OCTET_STRING)
323 if (packet.object_value.string.num_bytes == 2)
324 new_state = (packet.object_value.string.bytes[0] << 8) |
325 packet.object_value.string.bytes[1];
326 else if (packet.object_value.string.num_bytes == 1)
327 new_state = (packet.object_value.string.bytes[0] << 8);
331 if (current_state < 0)
332 change_state = 0xffff;
334 change_state = current_state ^ new_state;
336 fprintf(stderr, "DEBUG: new_state=%x, change_state=%x\n", new_state,
340 i < (int)(sizeof(printer_states) / sizeof(printer_states[0]));
342 if (change_state & printer_states[i].bit)
344 fprintf(stderr, "STATE: %c%s\n",
345 (new_state & printer_states[i].bit) ? '+' : '-',
346 printer_states[i].keyword);
349 current_state = new_state;
352 * Get the current printer state...
357 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
358 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
362 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
363 packet.object_type != CUPS_ASN1_INTEGER)
366 *printer_state = packet.object_value.integer;
370 * Get the current page count...
375 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
376 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
380 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
381 packet.object_type != CUPS_ASN1_COUNTER)
384 *page_count = packet.object_value.counter;
395 * 'backend_init_supplies()' - Initialize the supplies list.
399 backend_init_supplies(
400 int snmp_fd, /* I - SNMP socket */
401 http_addr_t *addr) /* I - Printer address */
403 int i, /* Looping var */
404 type; /* Current marker type */
405 cups_file_t *cachefile; /* Cache file */
406 const char *cachedir; /* CUPS_CACHEDIR value */
407 char addrstr[1024], /* Address string */
408 cachefilename[1024], /* Cache filename */
409 description[CUPS_SNMP_MAX_STRING],
410 /* Device description string */
411 value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 4 + 3)],
413 *ptr, /* Pointer into value string */
414 *name_ptr; /* Pointer into name string */
415 cups_snmp_t packet; /* SNMP response packet */
416 ppd_file_t *ppd; /* PPD file for this queue */
417 ppd_attr_t *ppdattr; /* cupsSNMPSupplies attribute */
418 static const char * const types[] = /* Supply types */
458 * Reset state information...
461 current_addr = *addr;
466 memset(supplies, 0, sizeof(supplies));
469 * See if we should be getting supply levels via SNMP...
472 if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL ||
473 ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
474 ppdattr->value && _cups_strcasecmp(ppdattr->value, "true")))
483 * Get the device description...
486 if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
487 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
491 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
492 packet.object_type != CUPS_ASN1_OCTET_STRING)
494 strlcpy(description, "Unknown", sizeof(description));
498 strlcpy(description, (char *)packet.object_value.string.bytes,
499 sizeof(description));
501 fprintf(stderr, "DEBUG2: hrDeviceDesc=\"%s\"\n", description);
504 * See if we have already queried this device...
507 httpAddrString(addr, addrstr, sizeof(addrstr));
509 if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
510 cachedir = CUPS_CACHEDIR;
512 snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir,
515 if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL)
518 * Yes, read the cache file:
520 * 2 num_supplies charset
522 * supply structures...
525 if (cupsFileGets(cachefile, value, sizeof(value)))
527 if (sscanf(value, "2 %d%d", &num_supplies, &charset) == 2 &&
528 num_supplies <= CUPS_MAX_SUPPLIES &&
529 cupsFileGets(cachefile, value, sizeof(value)))
531 if (!strcmp(description, value))
532 cupsFileRead(cachefile, (char *)supplies,
533 num_supplies * sizeof(backend_supplies_t));
547 cupsFileClose(cachefile);
551 * If the cache information isn't correct, scan for supplies...
557 * Get the configured character set...
560 int oid[CUPS_SNMP_MAX_OID]; /* OID for character set */
563 if (!_cupsSNMPWrite(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1,
564 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
565 prtGeneralCurrentLocalization))
568 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
569 packet.object_type != CUPS_ASN1_INTEGER)
572 "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n",
573 packet.object_type, CUPS_ASN1_INTEGER);
577 fprintf(stderr, "DEBUG2: prtGeneralCurrentLocalization=%d\n",
578 packet.object_value.integer);
580 _cupsSNMPCopyOID(oid, prtLocalizationCharacterSet, CUPS_SNMP_MAX_OID);
581 oid[prtLocalizationCharacterSetOffset - 2] = packet.object_value.integer;
584 if (!_cupsSNMPWrite(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1,
585 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
589 if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
590 packet.object_type != CUPS_ASN1_INTEGER)
593 "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n",
594 packet.object_type, CUPS_ASN1_INTEGER);
598 fprintf(stderr, "DEBUG2: prtLocalizationCharacterSet=%d\n",
599 packet.object_value.integer);
600 charset = packet.object_value.integer;
603 if (num_supplies < 0)
606 * Walk the printer configuration information...
609 _cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1,
610 _cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry,
611 CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
615 * Save the cached information...
618 if (num_supplies < 0)
621 if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
623 cupsFilePrintf(cachefile, "2 %d %d\n", num_supplies, charset);
624 cupsFilePrintf(cachefile, "%s\n", description);
626 if (num_supplies > 0)
627 cupsFileWrite(cachefile, (char *)supplies,
628 num_supplies * sizeof(backend_supplies_t));
630 cupsFileClose(cachefile);
633 if (num_supplies <= 0)
640 for (i = 0; i < num_supplies; i ++)
641 strcpy(supplies[i].color, "none");
643 _cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1,
644 _cupsSNMPDefaultCommunity(), prtMarkerColorantValue,
645 CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
648 * Output the marker-colors attribute...
651 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
656 strcpy(ptr, supplies[i].color);
659 fprintf(stderr, "ATTR: marker-colors=%s\n", value);
662 * Output the marker-names attribute (the double quoting is necessary to deal
663 * with embedded quotes and commas in the marker names...)
666 for (i = 0, ptr = value; i < num_supplies; i ++)
673 for (name_ptr = supplies[i].name; *name_ptr;)
675 if (*name_ptr == '\\' || *name_ptr == '\"' || *name_ptr == '\'')
682 *ptr++ = *name_ptr++;
690 fprintf(stderr, "ATTR: marker-names=%s\n", value);
693 * Output the marker-types attribute...
696 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
701 type = supplies[i].type;
703 if (type < CUPS_TC_other || type > CUPS_TC_covers)
704 strcpy(ptr, "unknown");
706 strcpy(ptr, types[type - CUPS_TC_other]);
709 fprintf(stderr, "ATTR: marker-types=%s\n", value);
714 * 'backend_walk_cb()' - Interpret the supply value responses.
718 backend_walk_cb(cups_snmp_t *packet, /* I - SNMP packet */
719 void *data) /* I - User data (unused) */
721 int i, j, k; /* Looping vars */
722 static const char * const colors[][2] =
723 { /* Standard color names */
724 { "black", "#000000" },
725 { "blue", "#0000FF" },
726 { "brown", "#A52A2A" },
727 { "cyan", "#00FFFF" },
728 { "dark-gray", "#404040" },
729 { "dark gray", "#404040" },
730 { "dark-yellow", "#FFCC00" },
731 { "dark yellow", "#FFCC00" },
732 { "gold", "#FFD700" },
733 { "gray", "#808080" },
734 { "green", "#00FF00" },
735 { "light-black", "#606060" },
736 { "light black", "#606060" },
737 { "light-cyan", "#E0FFFF" },
738 { "light cyan", "#E0FFFF" },
739 { "light-gray", "#D3D3D3" },
740 { "light gray", "#D3D3D3" },
741 { "light-magenta", "#FF77FF" },
742 { "light magenta", "#FF77FF" },
743 { "magenta", "#FF00FF" },
744 { "orange", "#FFA500" },
745 { "red", "#FF0000" },
746 { "silver", "#C0C0C0" },
747 { "white", "#FFFFFF" },
748 { "yellow", "#FFFF00" }
754 if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerColorantValue) &&
755 packet->object_type == CUPS_ASN1_OCTET_STRING)
761 i = packet->object_name[prtMarkerColorantValueOffset];
763 fprintf(stderr, "DEBUG2: prtMarkerColorantValue.1.%d = \"%s\"\n", i,
764 (char *)packet->object_value.string.bytes);
766 for (j = 0; j < num_supplies; j ++)
767 if (supplies[j].colorant == i)
769 for (k = 0; k < (int)(sizeof(colors) / sizeof(colors[0])); k ++)
770 if (!_cups_strcasecmp(colors[k][0],
771 (char *)packet->object_value.string.bytes))
773 strcpy(supplies[j].color, colors[k][1]);
778 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesColorantIndex))
781 * Get colorant index...
784 i = packet->object_name[prtMarkerSuppliesColorantIndexOffset];
785 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
786 packet->object_type != CUPS_ASN1_INTEGER)
789 fprintf(stderr, "DEBUG2: prtMarkerSuppliesColorantIndex.1.%d = %d\n", i,
790 packet->object_value.integer);
792 if (i > num_supplies)
795 supplies[i - 1].colorant = packet->object_value.integer;
797 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesDescription))
800 * Get supply name/description...
803 i = packet->object_name[prtMarkerSuppliesDescriptionOffset];
804 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
805 packet->object_type != CUPS_ASN1_OCTET_STRING)
808 if (i > num_supplies)
813 case CUPS_TC_csASCII :
814 case CUPS_TC_csUTF8 :
815 case CUPS_TC_csUnicodeASCII :
816 strlcpy(supplies[i - 1].name,
817 (char *)packet->object_value.string.bytes,
818 sizeof(supplies[0].name));
821 case CUPS_TC_csISOLatin1 :
822 case CUPS_TC_csUnicodeLatin1 :
823 cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
824 (char *)packet->object_value.string.bytes,
825 sizeof(supplies[0].name), CUPS_ISO8859_1);
828 case CUPS_TC_csShiftJIS :
829 case CUPS_TC_csWindows31J : /* Close enough for our purposes */
830 cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
831 (char *)packet->object_value.string.bytes,
832 sizeof(supplies[0].name), CUPS_JIS_X0213);
835 case CUPS_TC_csUCS4 :
836 case CUPS_TC_csUTF32 :
837 case CUPS_TC_csUTF32BE :
838 case CUPS_TC_csUTF32LE :
839 cupsUTF32ToUTF8((cups_utf8_t *)supplies[i - 1].name,
840 (cups_utf32_t *)packet->object_value.string.bytes,
841 sizeof(supplies[0].name));
844 case CUPS_TC_csUnicode :
845 case CUPS_TC_csUTF16BE :
846 case CUPS_TC_csUTF16LE :
847 utf16_to_utf8((cups_utf8_t *)supplies[i - 1].name,
848 packet->object_value.string.bytes,
849 packet->object_value.string.num_bytes,
850 sizeof(supplies[0].name), charset == CUPS_TC_csUTF16LE);
855 * If we get here, the printer is using an unknown character set and
856 * we just want to copy characters that look like ASCII...
860 char *src, *dst; /* Pointers into strings */
863 * Loop safe because both the object_value and supplies char arrays
864 * are CUPS_SNMP_MAX_STRING elements long.
867 for (src = (char *)packet->object_value.string.bytes,
868 dst = supplies[i - 1].name;
872 if ((*src & 0x80) || *src < ' ' || *src == 0x7f)
883 fprintf(stderr, "DEBUG2: prtMarkerSuppliesDescription.1.%d = \"%s\"\n", i,
884 supplies[i - 1].name);
887 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesLevel))
893 i = packet->object_name[prtMarkerSuppliesLevelOffset];
894 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
895 packet->object_type != CUPS_ASN1_INTEGER)
898 fprintf(stderr, "DEBUG2: prtMarkerSuppliesLevel.1.%d = %d\n", i,
899 packet->object_value.integer);
901 if (i > num_supplies)
904 supplies[i - 1].level = packet->object_value.integer;
906 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesMaxCapacity))
909 * Get max capacity...
912 i = packet->object_name[prtMarkerSuppliesMaxCapacityOffset];
913 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
914 packet->object_type != CUPS_ASN1_INTEGER)
917 fprintf(stderr, "DEBUG2: prtMarkerSuppliesMaxCapacity.1.%d = %d\n", i,
918 packet->object_value.integer);
920 if (i > num_supplies)
923 supplies[i - 1].max_capacity = packet->object_value.integer;
925 else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesType))
931 i = packet->object_name[prtMarkerSuppliesTypeOffset];
932 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
933 packet->object_type != CUPS_ASN1_INTEGER)
936 fprintf(stderr, "DEBUG2: prtMarkerSuppliesType.1.%d = %d\n", i,
937 packet->object_value.integer);
939 if (i > num_supplies)
942 supplies[i - 1].type = packet->object_value.integer;
948 * 'utf16_to_utf8()' - Convert UTF-16 text to UTF-8.
953 cups_utf8_t *dst, /* I - Destination buffer */
954 const unsigned char *src, /* I - Source string */
955 size_t srcsize, /* I - Size of source string */
956 size_t dstsize, /* I - Size of destination buffer */
957 int le) /* I - Source is little-endian? */
959 cups_utf32_t ch, /* Current character */
960 temp[CUPS_SNMP_MAX_STRING],
962 *ptr; /* Pointer into UTF-32 string */
965 for (ptr = temp; srcsize >= 2;)
968 ch = src[0] | (src[1] << 8);
970 ch = (src[0] << 8) | src[1];
975 if (ch >= 0xd800 && ch <= 0xdbff && srcsize >= 2)
978 * Multi-word UTF-16 char...
981 int lch; /* Lower word */
985 lch = src[0] | (src[1] << 8);
987 lch = (src[0] << 8) | src[1];
989 if (lch >= 0xdc00 && lch <= 0xdfff)
994 ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
998 if (ptr < (temp + CUPS_SNMP_MAX_STRING - 1))
1004 cupsUTF32ToUTF8(dst, temp, dstsize);
1009 * End of "$Id: snmp-supplies.c 10262 2012-02-12 05:48:09Z mike $".