4 * SNMP supplies functions for the Common UNIX Printing System (CUPS).
6 * Copyright 2008-2009 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 */
44 typedef struct /**** Printer supply data ****/
46 char name
[CUPS_SNMP_MAX_STRING
], /* Name of supply */
47 color
[8]; /* Color: "#RRGGBB" or "none" */
48 int colorant
, /* Colorant index */
49 type
, /* Supply type */
50 max_capacity
, /* Maximum capacity */
51 level
; /* Current level value */
54 typedef struct /**** Printer state table ****/
56 int bit
; /* State bit */
57 const char *keyword
; /* IPP printer-state-reasons keyword */
65 static http_addr_t current_addr
; /* Current address */
66 static int current_state
= -1;
67 /* Current device state bits */
68 static int charset
= -1; /* Character set for supply names */
69 static int laser_printer
= -1,
70 /* Laser printer with toner? */
72 /* Number of supplies found */
73 static backend_supplies_t supplies
[CUPS_MAX_SUPPLIES
];
74 /* Supply information */
76 static const int hrDeviceDescr
[] =
77 { CUPS_OID_hrDeviceDescr
, 1, -1 };
78 /* Device description OID */
79 static const int hrPrinterStatus
[] =
80 { CUPS_OID_hrPrinterStatus
, 1, -1 };
81 /* Current state OID */
82 static const int hrPrinterDetectedErrorState
[] =
83 { CUPS_OID_hrPrinterDetectedErrorState
, 1, -1 };
84 /* Current printer state bits OID */
85 static const int prtGeneralCurrentLocalization
[] =
86 { CUPS_OID_prtGeneralCurrentLocalization
, 1, -1 };
87 static const int prtLocalizationCharacterSet
[] =
88 { CUPS_OID_prtLocalizationCharacterSet
, 1, 1, -1 },
89 prtLocalizationCharacterSetOffset
=
90 (sizeof(prtLocalizationCharacterSet
) /
91 sizeof(prtLocalizationCharacterSet
[0]));
92 static const int prtMarkerColorantValue
[] =
93 { CUPS_OID_prtMarkerColorantValue
, -1 },
95 prtMarkerColorantValueOffset
=
96 (sizeof(prtMarkerColorantValue
) /
97 sizeof(prtMarkerColorantValue
[0]));
98 /* Offset to colorant index */
99 static const int prtMarkerLifeCount
[] =
100 { CUPS_OID_prtMarkerLifeCount
, 1, 1, -1 };
101 /* Page counter OID */
102 static const int prtMarkerSuppliesEntry
[] =
103 { CUPS_OID_prtMarkerSuppliesEntry
, -1 };
105 static const int prtMarkerSuppliesColorantIndex
[] =
106 { CUPS_OID_prtMarkerSuppliesColorantIndex
, -1 },
107 /* Colorant index OID */
108 prtMarkerSuppliesColorantIndexOffset
=
109 (sizeof(prtMarkerSuppliesColorantIndex
) /
110 sizeof(prtMarkerSuppliesColorantIndex
[0]));
111 /* Offset to supply index */
112 static const int prtMarkerSuppliesDescription
[] =
113 { CUPS_OID_prtMarkerSuppliesDescription
, -1 },
114 /* Description OID */
115 prtMarkerSuppliesDescriptionOffset
=
116 (sizeof(prtMarkerSuppliesDescription
) /
117 sizeof(prtMarkerSuppliesDescription
[0]));
118 /* Offset to supply index */
119 static const int prtMarkerSuppliesLevel
[] =
120 { CUPS_OID_prtMarkerSuppliesLevel
, -1 },
122 prtMarkerSuppliesLevelOffset
=
123 (sizeof(prtMarkerSuppliesLevel
) /
124 sizeof(prtMarkerSuppliesLevel
[0]));
125 /* Offset to supply index */
126 static const int prtMarkerSuppliesMaxCapacity
[] =
127 { CUPS_OID_prtMarkerSuppliesMaxCapacity
, -1 },
128 /* Max capacity OID */
129 prtMarkerSuppliesMaxCapacityOffset
=
130 (sizeof(prtMarkerSuppliesMaxCapacity
) /
131 sizeof(prtMarkerSuppliesMaxCapacity
[0]));
132 /* Offset to supply index */
133 static const int prtMarkerSuppliesType
[] =
134 { CUPS_OID_prtMarkerSuppliesType
, -1 },
136 prtMarkerSuppliesTypeOffset
=
137 (sizeof(prtMarkerSuppliesType
) /
138 sizeof(prtMarkerSuppliesType
[0]));
139 /* Offset to supply index */
141 static const backend_state_t
const printer_states
[] =
143 { CUPS_TC_lowPaper
, "media-low-report" },
144 { CUPS_TC_noPaper
| CUPS_TC_inputTrayEmpty
, "media-empty-warning" },
145 { CUPS_TC_lowToner
, "toner-low-report" },
146 { CUPS_TC_noToner
, "toner-empty-warning" },
147 { CUPS_TC_doorOpen
, "door-open-report" },
148 { CUPS_TC_jammed
, "media-jam-warning" },
149 /* { CUPS_TC_offline, "offline-report" }, */ /* unreliable */
150 /* { CUPS_TC_serviceRequested | CUPS_TC_overduePreventMaint, "service-needed-warning" }, */ /* unreliable */
151 { CUPS_TC_inputTrayMissing
, "input-tray-missing-warning" },
152 { CUPS_TC_outputTrayMissing
, "output-tray-missing-warning" },
153 { CUPS_TC_markerSupplyMissing
, "marker-supply-missing-warning" },
154 { CUPS_TC_outputNearFull
, "output-area-almost-full-report" },
155 { CUPS_TC_outputFull
, "output-area-full-warning" }
163 static void backend_init_supplies(int snmp_fd
, http_addr_t
*addr
);
164 static void backend_walk_cb(cups_snmp_t
*packet
, void *data
);
165 static void utf16_to_utf8(cups_utf8_t
*dst
, const unsigned char *src
,
166 size_t srcsize
, size_t dstsize
, int le
);
170 * 'backendSNMPSupplies()' - Get the current supplies for a device.
173 int /* O - 0 on success, -1 on error */
175 int snmp_fd
, /* I - SNMP socket */
176 http_addr_t
*addr
, /* I - Printer address */
177 int *page_count
, /* O - Page count */
178 int *printer_state
) /* O - Printer state */
180 if (!httpAddrEqual(addr
, ¤t_addr
))
181 backend_init_supplies(snmp_fd
, addr
);
182 else if (num_supplies
> 0)
183 _cupsSNMPWalk(snmp_fd
, ¤t_addr
, CUPS_SNMP_VERSION_1
,
184 _cupsSNMPDefaultCommunity(), prtMarkerSuppliesLevel
,
185 CUPS_SUPPLY_TIMEOUT
, backend_walk_cb
, NULL
);
193 if (num_supplies
> 0)
195 int i
, /* Looping var */
196 new_state
, /* New state value */
197 change_state
; /* State change */
198 char value
[CUPS_MAX_SUPPLIES
* 4],
199 /* marker-levels value string */
200 *ptr
; /* Pointer into value string */
201 cups_snmp_t packet
; /* SNMP response packet */
204 * Generate the marker-levels value string...
207 for (i
= 0, ptr
= value
; i
< num_supplies
; i
++, ptr
+= strlen(ptr
))
212 if (supplies
[i
].max_capacity
> 0)
213 sprintf(ptr
, "%d", 100 * supplies
[i
].level
/ supplies
[i
].max_capacity
);
218 fprintf(stderr
, "ATTR: marker-levels=%s\n", value
);
221 * Get the current printer status bits...
224 if (!_cupsSNMPWrite(snmp_fd
, addr
, CUPS_SNMP_VERSION_1
,
225 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST
, 1,
226 hrPrinterDetectedErrorState
))
229 if (!_cupsSNMPRead(snmp_fd
, &packet
, CUPS_SUPPLY_TIMEOUT
) ||
230 packet
.object_type
!= CUPS_ASN1_OCTET_STRING
)
233 if (packet
.object_value
.string
.num_bytes
== 2)
234 new_state
= (packet
.object_value
.string
.bytes
[0] << 8) |
235 packet
.object_value
.string
.bytes
[1];
236 else if (packet
.object_value
.string
.num_bytes
== 1)
237 new_state
= (packet
.object_value
.string
.bytes
[0] << 8);
241 if (current_state
< 0)
242 change_state
= 0xffff;
244 change_state
= current_state
^ new_state
;
246 fprintf(stderr
, "DEBUG: new_state=%x, change_state=%x, laser_printer=%d\n",
247 new_state
, change_state
, laser_printer
);
250 i
< (int)(sizeof(printer_states
) / sizeof(printer_states
[0]));
252 if (change_state
& printer_states
[i
].bit
)
254 if (!laser_printer
&& !strncmp(printer_states
[i
].keyword
, "toner-", 6))
257 * Map toner-xxx to marker-supply-xxx to avoid confusing "out of toner"
258 * messages on inkjet print queues...
261 if (printer_states
[i
].bit
== CUPS_TC_lowToner
)
262 fprintf(stderr
, "STATE: %cmarker-supply-low-report\n",
263 (new_state
& CUPS_TC_lowToner
) ? '+' : '-');
265 fprintf(stderr
, "STATE: %cmarker-supply-empty-warning\n",
266 (new_state
& CUPS_TC_noToner
) ? '+' : '-');
269 fprintf(stderr
, "STATE: %c%s\n",
270 (new_state
& printer_states
[i
].bit
) ? '+' : '-',
271 printer_states
[i
].keyword
);
274 current_state
= new_state
;
277 * Get the current printer state...
282 if (!_cupsSNMPWrite(snmp_fd
, addr
, CUPS_SNMP_VERSION_1
,
283 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST
, 1,
287 if (!_cupsSNMPRead(snmp_fd
, &packet
, CUPS_SUPPLY_TIMEOUT
) ||
288 packet
.object_type
!= CUPS_ASN1_INTEGER
)
291 *printer_state
= packet
.object_value
.integer
;
295 * Get the current page count...
300 if (!_cupsSNMPWrite(snmp_fd
, addr
, CUPS_SNMP_VERSION_1
,
301 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST
, 1,
305 if (!_cupsSNMPRead(snmp_fd
, &packet
, CUPS_SUPPLY_TIMEOUT
) ||
306 packet
.object_type
!= CUPS_ASN1_COUNTER
)
309 *page_count
= packet
.object_value
.counter
;
320 * 'backend_init_supplies()' - Initialize the supplies list.
324 backend_init_supplies(
325 int snmp_fd
, /* I - SNMP socket */
326 http_addr_t
*addr
) /* I - Printer address */
328 int i
, /* Looping var */
329 type
; /* Current marker type */
330 cups_file_t
*cachefile
; /* Cache file */
331 const char *cachedir
; /* CUPS_CACHEDIR value */
332 char addrstr
[1024], /* Address string */
333 cachefilename
[1024], /* Cache filename */
334 description
[CUPS_SNMP_MAX_STRING
],
335 /* Device description string */
336 value
[CUPS_MAX_SUPPLIES
* (CUPS_SNMP_MAX_STRING
* 2 + 3)],
338 *ptr
, /* Pointer into value string */
339 *name_ptr
; /* Pointer into name string */
340 cups_snmp_t packet
; /* SNMP response packet */
341 ppd_file_t
*ppd
; /* PPD file for this queue */
342 ppd_attr_t
*ppdattr
; /* cupsSNMPSupplies attribute */
343 static const char * const types
[] = /* Supply types */
383 * Reset state information...
386 current_addr
= *addr
;
391 memset(supplies
, 0, sizeof(supplies
));
394 * See if we should be getting supply levels via SNMP...
397 if ((ppd
= ppdOpenFile(getenv("PPD"))) != NULL
&&
398 (ppdattr
= ppdFindAttr(ppd
, "cupsSNMPSupplies", NULL
)) != NULL
&&
399 ppdattr
->value
&& strcasecmp(ppdattr
->value
, "true"))
408 * Get the device description...
411 if (!_cupsSNMPWrite(snmp_fd
, addr
, CUPS_SNMP_VERSION_1
,
412 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST
, 1,
416 if (!_cupsSNMPRead(snmp_fd
, &packet
, CUPS_SUPPLY_TIMEOUT
) ||
417 packet
.object_type
!= CUPS_ASN1_OCTET_STRING
)
419 strlcpy(description
, "Unknown", sizeof(description
));
423 strlcpy(description
, (char *)packet
.object_value
.string
.bytes
,
424 sizeof(description
));
426 fprintf(stderr
, "DEBUG2: hrDeviceDesc=\"%s\"\n", description
);
429 * See if we have already queried this device...
432 httpAddrString(addr
, addrstr
, sizeof(addrstr
));
434 if ((cachedir
= getenv("CUPS_CACHEDIR")) == NULL
)
435 cachedir
= CUPS_CACHEDIR
;
437 snprintf(cachefilename
, sizeof(cachefilename
), "%s/%s.snmp", cachedir
,
440 if ((cachefile
= cupsFileOpen(cachefilename
, "r")) != NULL
)
443 * Yes, read the cache file:
445 * 2 num_supplies charset
447 * supply structures...
450 if (cupsFileGets(cachefile
, value
, sizeof(value
)))
452 if (sscanf(value
, "2 %d%d", &num_supplies
, &charset
) == 2 &&
453 num_supplies
<= CUPS_MAX_SUPPLIES
&&
454 cupsFileGets(cachefile
, value
, sizeof(value
)))
456 if (!strcmp(description
, value
))
457 cupsFileRead(cachefile
, (char *)supplies
,
458 num_supplies
* sizeof(backend_supplies_t
));
472 cupsFileClose(cachefile
);
476 * If the cache information isn't correct, scan for supplies...
482 * Get the configured character set...
485 int oid
[CUPS_SNMP_MAX_OID
]; /* OID for character set */
488 if (!_cupsSNMPWrite(snmp_fd
, ¤t_addr
, CUPS_SNMP_VERSION_1
,
489 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST
, 1,
490 prtGeneralCurrentLocalization
))
493 if (!_cupsSNMPRead(snmp_fd
, &packet
, CUPS_SUPPLY_TIMEOUT
) ||
494 packet
.object_type
!= CUPS_ASN1_INTEGER
)
497 "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n",
498 packet
.object_type
, CUPS_ASN1_INTEGER
);
502 fprintf(stderr
, "DEBUG2: prtGeneralCurrentLocalization=%d\n",
503 packet
.object_value
.integer
);
505 _cupsSNMPCopyOID(oid
, prtLocalizationCharacterSet
, CUPS_SNMP_MAX_OID
);
506 oid
[prtLocalizationCharacterSetOffset
- 2] = packet
.object_value
.integer
;
509 if (!_cupsSNMPWrite(snmp_fd
, ¤t_addr
, CUPS_SNMP_VERSION_1
,
510 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST
, 1,
514 if (!_cupsSNMPRead(snmp_fd
, &packet
, CUPS_SUPPLY_TIMEOUT
) ||
515 packet
.object_type
!= CUPS_ASN1_INTEGER
)
518 "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n",
519 packet
.object_type
, CUPS_ASN1_INTEGER
);
523 fprintf(stderr
, "DEBUG2: prtLocalizationCharacterSet=%d\n",
524 packet
.object_value
.integer
);
525 charset
= packet
.object_value
.integer
;
528 if (num_supplies
< 0)
531 * Walk the printer configuration information...
534 _cupsSNMPWalk(snmp_fd
, ¤t_addr
, CUPS_SNMP_VERSION_1
,
535 _cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry
,
536 CUPS_SUPPLY_TIMEOUT
, backend_walk_cb
, NULL
);
540 * Save the cached information...
543 if (num_supplies
< 0)
546 if ((cachefile
= cupsFileOpen(cachefilename
, "w")) != NULL
)
548 cupsFilePrintf(cachefile
, "2 %d %d\n", num_supplies
, charset
);
549 cupsFilePrintf(cachefile
, "%s\n", description
);
551 if (num_supplies
> 0)
552 cupsFileWrite(cachefile
, (char *)supplies
,
553 num_supplies
* sizeof(backend_supplies_t
));
555 cupsFileClose(cachefile
);
558 if (num_supplies
<= 0)
565 for (i
= 0; i
< num_supplies
; i
++)
566 strcpy(supplies
[i
].color
, "none");
568 _cupsSNMPWalk(snmp_fd
, ¤t_addr
, CUPS_SNMP_VERSION_1
,
569 _cupsSNMPDefaultCommunity(), prtMarkerColorantValue
,
570 CUPS_SUPPLY_TIMEOUT
, backend_walk_cb
, NULL
);
573 * Output the marker-colors attribute...
576 for (i
= 0, ptr
= value
; i
< num_supplies
; i
++, ptr
+= strlen(ptr
))
581 strcpy(ptr
, supplies
[i
].color
);
584 fprintf(stderr
, "ATTR: marker-colors=%s\n", value
);
587 * Output the marker-names attribute...
590 for (i
= 0, ptr
= value
; i
< num_supplies
; i
++)
596 for (name_ptr
= supplies
[i
].name
; *name_ptr
;)
598 if (*name_ptr
== '\\' || *name_ptr
== '\"')
601 *ptr
++ = *name_ptr
++;
608 fprintf(stderr
, "ATTR: marker-names=%s\n", value
);
611 * Output the marker-types attribute...
616 for (i
= 0, ptr
= value
; i
< num_supplies
; i
++, ptr
+= strlen(ptr
))
621 type
= supplies
[i
].type
;
623 if (type
== CUPS_TC_toner
)
626 if (type
< CUPS_TC_other
|| type
> CUPS_TC_covers
)
627 strcpy(ptr
, "unknown");
629 strcpy(ptr
, types
[type
- CUPS_TC_other
]);
632 fprintf(stderr
, "ATTR: marker-types=%s\n", value
);
637 * 'backend_walk_cb()' - Interpret the supply value responses.
641 backend_walk_cb(cups_snmp_t
*packet
, /* I - SNMP packet */
642 void *data
) /* I - User data (unused) */
644 int i
, j
, k
; /* Looping vars */
645 static const char * const colors
[8][2] =
646 { /* Standard color names */
647 { "black", "#000000" },
648 { "blue", "#0000FF" },
649 { "cyan", "#00FFFF" },
650 { "green", "#00FF00" },
651 { "magenta", "#FF00FF" },
652 { "red", "#FF0000" },
653 { "white", "#FFFFFF" },
654 { "yellow", "#FFFF00" }
660 if (_cupsSNMPIsOIDPrefixed(packet
, prtMarkerColorantValue
) &&
661 packet
->object_type
== CUPS_ASN1_OCTET_STRING
)
667 i
= packet
->object_name
[prtMarkerColorantValueOffset
];
669 fprintf(stderr
, "DEBUG2: prtMarkerColorantValue.1.%d = \"%s\"\n", i
,
670 (char *)packet
->object_value
.string
.bytes
);
672 for (j
= 0; j
< num_supplies
; j
++)
673 if (supplies
[j
].colorant
== i
)
675 for (k
= 0; k
< (int)(sizeof(colors
) / sizeof(colors
[0])); k
++)
676 if (!strcmp(colors
[k
][0], (char *)packet
->object_value
.string
.bytes
))
678 strcpy(supplies
[j
].color
, colors
[k
][1]);
683 else if (_cupsSNMPIsOIDPrefixed(packet
, prtMarkerSuppliesColorantIndex
))
686 * Get colorant index...
689 i
= packet
->object_name
[prtMarkerSuppliesColorantIndexOffset
];
690 if (i
< 1 || i
> CUPS_MAX_SUPPLIES
||
691 packet
->object_type
!= CUPS_ASN1_INTEGER
)
694 fprintf(stderr
, "DEBUG2: prtMarkerSuppliesColorantIndex.1.%d = %d\n", i
,
695 packet
->object_value
.integer
);
697 if (i
> num_supplies
)
700 supplies
[i
- 1].colorant
= packet
->object_value
.integer
;
702 else if (_cupsSNMPIsOIDPrefixed(packet
, prtMarkerSuppliesDescription
))
705 * Get supply name/description...
708 i
= packet
->object_name
[prtMarkerSuppliesDescriptionOffset
];
709 if (i
< 1 || i
> CUPS_MAX_SUPPLIES
||
710 packet
->object_type
!= CUPS_ASN1_OCTET_STRING
)
713 if (i
> num_supplies
)
718 case CUPS_TC_csASCII
:
719 case CUPS_TC_csUTF8
:
720 case CUPS_TC_csUnicodeASCII
:
721 strlcpy(supplies
[i
- 1].name
,
722 (char *)packet
->object_value
.string
.bytes
,
723 sizeof(supplies
[0].name
));
726 case CUPS_TC_csISOLatin1
:
727 case CUPS_TC_csUnicodeLatin1
:
728 cupsCharsetToUTF8((cups_utf8_t
*)supplies
[i
- 1].name
,
729 (char *)packet
->object_value
.string
.bytes
,
730 sizeof(supplies
[0].name
), CUPS_ISO8859_1
);
733 case CUPS_TC_csShiftJIS
:
734 cupsCharsetToUTF8((cups_utf8_t
*)supplies
[i
- 1].name
,
735 (char *)packet
->object_value
.string
.bytes
,
736 sizeof(supplies
[0].name
), CUPS_JIS_X0213
);
739 case CUPS_TC_csUCS4
:
740 case CUPS_TC_csUTF32
:
741 case CUPS_TC_csUTF32BE
:
742 case CUPS_TC_csUTF32LE
:
743 cupsUTF32ToUTF8((cups_utf8_t
*)supplies
[i
- 1].name
,
744 (cups_utf32_t
*)packet
->object_value
.string
.bytes
,
745 sizeof(supplies
[0].name
));
748 case CUPS_TC_csUnicode
:
749 case CUPS_TC_csUTF16BE
:
750 case CUPS_TC_csUTF16LE
:
751 utf16_to_utf8((cups_utf8_t
*)supplies
[i
- 1].name
,
752 packet
->object_value
.string
.bytes
,
753 packet
->object_value
.string
.num_bytes
,
754 sizeof(supplies
[0].name
), charset
== CUPS_TC_csUTF16LE
);
759 * If we get here, the printer is using an unknown character set and
760 * we just want to copy characters that look like ASCII...
764 char *src
, *dst
; /* Pointers into strings */
768 * Loop safe because both the object_value and supplies char arrays
769 * are CUPS_SNMP_MAX_STRING elements long.
772 for (src
= (char *)packet
->object_value
.string
.bytes
,
773 dst
= supplies
[i
- 1].name
;
777 if ((*src
& 0x80) || *src
< ' ' || *src
== 0x7f)
788 fprintf(stderr
, "DEBUG2: prtMarkerSuppliesDescription.1.%d = \"%s\"\n", i
,
789 supplies
[i
- 1].name
);
792 else if (_cupsSNMPIsOIDPrefixed(packet
, prtMarkerSuppliesLevel
))
798 i
= packet
->object_name
[prtMarkerSuppliesLevelOffset
];
799 if (i
< 1 || i
> CUPS_MAX_SUPPLIES
||
800 packet
->object_type
!= CUPS_ASN1_INTEGER
)
803 fprintf(stderr
, "DEBUG2: prtMarkerSuppliesLevel.1.%d = %d\n", i
,
804 packet
->object_value
.integer
);
806 if (i
> num_supplies
)
809 supplies
[i
- 1].level
= packet
->object_value
.integer
;
811 else if (_cupsSNMPIsOIDPrefixed(packet
, prtMarkerSuppliesMaxCapacity
))
814 * Get max capacity...
817 i
= packet
->object_name
[prtMarkerSuppliesMaxCapacityOffset
];
818 if (i
< 1 || i
> CUPS_MAX_SUPPLIES
||
819 packet
->object_type
!= CUPS_ASN1_INTEGER
)
822 fprintf(stderr
, "DEBUG2: prtMarkerSuppliesMaxCapacity.1.%d = %d\n", i
,
823 packet
->object_value
.integer
);
825 if (i
> num_supplies
)
828 supplies
[i
- 1].max_capacity
= packet
->object_value
.integer
;
830 else if (_cupsSNMPIsOIDPrefixed(packet
, prtMarkerSuppliesType
))
836 i
= packet
->object_name
[prtMarkerSuppliesTypeOffset
];
837 if (i
< 1 || i
> CUPS_MAX_SUPPLIES
||
838 packet
->object_type
!= CUPS_ASN1_INTEGER
)
841 fprintf(stderr
, "DEBUG2: prtMarkerSuppliesType.1.%d = %d\n", i
,
842 packet
->object_value
.integer
);
844 if (i
> num_supplies
)
847 supplies
[i
- 1].type
= packet
->object_value
.integer
;
853 * 'utf16_to_utf8()' - Convert UTF-16 text to UTF-8.
858 cups_utf8_t
*dst
, /* I - Destination buffer */
859 const unsigned char *src
, /* I - Source string */
860 size_t srcsize
, /* I - Size of source string */
861 size_t dstsize
, /* I - Size of destination buffer */
862 int le
) /* I - Source is little-endian? */
864 cups_utf32_t ch
, /* Current character */
865 temp
[CUPS_SNMP_MAX_STRING
],
867 *ptr
; /* Pointer into UTF-32 string */
870 for (ptr
= temp
; srcsize
>= 2;)
873 ch
= src
[0] | (src
[1] << 8);
875 ch
= (src
[0] << 8) | src
[1];
880 if (ch
>= 0xd800 && ch
<= 0xdbff && srcsize
>= 2)
883 * Multi-word UTF-16 char...
886 int lch
; /* Lower word */
890 lch
= src
[0] | (src
[1] << 8);
892 lch
= (src
[0] << 8) | src
[1];
894 if (lch
>= 0xdc00 && lch
<= 0xdfff)
899 ch
= (((ch
& 0x3ff) << 10) | (lch
& 0x3ff)) + 0x10000;
903 if (ptr
< (temp
+ CUPS_SNMP_MAX_STRING
- 1))
909 cupsUTF32ToUTF8(dst
, temp
, dstsize
);