xref: /aosp_15_r20/external/libcups/backend/snmp-supplies.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * SNMP supplies functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2008-2015 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  *
6*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
7*5e7646d2SAndroid Build Coastguard Worker  * information.
8*5e7646d2SAndroid Build Coastguard Worker  */
9*5e7646d2SAndroid Build Coastguard Worker 
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers.
12*5e7646d2SAndroid Build Coastguard Worker  */
13*5e7646d2SAndroid Build Coastguard Worker 
14*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include <cups/ppd-private.h>
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/array.h>
17*5e7646d2SAndroid Build Coastguard Worker 
18*5e7646d2SAndroid Build Coastguard Worker 
19*5e7646d2SAndroid Build Coastguard Worker /*
20*5e7646d2SAndroid Build Coastguard Worker  * Local constants...
21*5e7646d2SAndroid Build Coastguard Worker  */
22*5e7646d2SAndroid Build Coastguard Worker 
23*5e7646d2SAndroid Build Coastguard Worker #define CUPS_MAX_SUPPLIES	32	/* Maximum number of supplies for a printer */
24*5e7646d2SAndroid Build Coastguard Worker #define CUPS_SUPPLY_TIMEOUT	2.0	/* Timeout for SNMP lookups */
25*5e7646d2SAndroid Build Coastguard Worker 
26*5e7646d2SAndroid Build Coastguard Worker #define CUPS_DEVELOPER_LOW	0x0001
27*5e7646d2SAndroid Build Coastguard Worker #define CUPS_DEVELOPER_EMPTY	0x0002
28*5e7646d2SAndroid Build Coastguard Worker #define CUPS_MARKER_SUPPLY_LOW	0x0004
29*5e7646d2SAndroid Build Coastguard Worker #define CUPS_MARKER_SUPPLY_EMPTY 0x0008
30*5e7646d2SAndroid Build Coastguard Worker #define CUPS_OPC_NEAR_EOL	0x0010
31*5e7646d2SAndroid Build Coastguard Worker #define CUPS_OPC_LIFE_OVER	0x0020
32*5e7646d2SAndroid Build Coastguard Worker #define CUPS_TONER_LOW		0x0040
33*5e7646d2SAndroid Build Coastguard Worker #define CUPS_TONER_EMPTY	0x0080
34*5e7646d2SAndroid Build Coastguard Worker #define CUPS_WASTE_ALMOST_FULL	0x0100
35*5e7646d2SAndroid Build Coastguard Worker #define CUPS_WASTE_FULL		0x0200
36*5e7646d2SAndroid Build Coastguard Worker #define CUPS_CLEANER_NEAR_EOL	0x0400	/* Proposed JPS3 */
37*5e7646d2SAndroid Build Coastguard Worker #define CUPS_CLEANER_LIFE_OVER	0x0800	/* Proposed JPS3 */
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker #define CUPS_SNMP_NONE		0x0000
40*5e7646d2SAndroid Build Coastguard Worker #define CUPS_SNMP_CAPACITY	0x0001	/* Supply levels reported as percentages */
41*5e7646d2SAndroid Build Coastguard Worker 
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker /*
44*5e7646d2SAndroid Build Coastguard Worker  * Local structures...
45*5e7646d2SAndroid Build Coastguard Worker  */
46*5e7646d2SAndroid Build Coastguard Worker 
47*5e7646d2SAndroid Build Coastguard Worker typedef struct				/**** Printer supply data ****/
48*5e7646d2SAndroid Build Coastguard Worker {
49*5e7646d2SAndroid Build Coastguard Worker   char	name[CUPS_SNMP_MAX_STRING],	/* Name of supply */
50*5e7646d2SAndroid Build Coastguard Worker 	color[8];			/* Color: "#RRGGBB" or "none" */
51*5e7646d2SAndroid Build Coastguard Worker   int	colorant,			/* Colorant index */
52*5e7646d2SAndroid Build Coastguard Worker 	sclass,				/* Supply class */
53*5e7646d2SAndroid Build Coastguard Worker 	type,				/* Supply type */
54*5e7646d2SAndroid Build Coastguard Worker 	max_capacity,			/* Maximum capacity */
55*5e7646d2SAndroid Build Coastguard Worker 	level;				/* Current level value */
56*5e7646d2SAndroid Build Coastguard Worker } backend_supplies_t;
57*5e7646d2SAndroid Build Coastguard Worker 
58*5e7646d2SAndroid Build Coastguard Worker typedef struct				/**** Printer state table ****/
59*5e7646d2SAndroid Build Coastguard Worker {
60*5e7646d2SAndroid Build Coastguard Worker   int		bit;			/* State bit */
61*5e7646d2SAndroid Build Coastguard Worker   const char	*keyword;		/* IPP printer-state-reasons keyword */
62*5e7646d2SAndroid Build Coastguard Worker } backend_state_t;
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker 
65*5e7646d2SAndroid Build Coastguard Worker /*
66*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
67*5e7646d2SAndroid Build Coastguard Worker  */
68*5e7646d2SAndroid Build Coastguard Worker 
69*5e7646d2SAndroid Build Coastguard Worker static http_addr_t	current_addr;	/* Current address */
70*5e7646d2SAndroid Build Coastguard Worker static int		current_state = -1;
71*5e7646d2SAndroid Build Coastguard Worker 					/* Current device state bits */
72*5e7646d2SAndroid Build Coastguard Worker static int		charset = -1;	/* Character set for supply names */
73*5e7646d2SAndroid Build Coastguard Worker static unsigned		quirks = CUPS_SNMP_NONE;
74*5e7646d2SAndroid Build Coastguard Worker 					/* Quirks we have to work around */
75*5e7646d2SAndroid Build Coastguard Worker static int		num_supplies = 0;
76*5e7646d2SAndroid Build Coastguard Worker 					/* Number of supplies found */
77*5e7646d2SAndroid Build Coastguard Worker static backend_supplies_t supplies[CUPS_MAX_SUPPLIES];
78*5e7646d2SAndroid Build Coastguard Worker 					/* Supply information */
79*5e7646d2SAndroid Build Coastguard Worker static int		supply_state = -1;
80*5e7646d2SAndroid Build Coastguard Worker 					/* Supply state info */
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker static const int	hrDeviceDescr[] =
83*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_hrDeviceDescr, 1, -1 };
84*5e7646d2SAndroid Build Coastguard Worker 					/* Device description OID */
85*5e7646d2SAndroid Build Coastguard Worker static const int	hrPrinterStatus[] =
86*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_hrPrinterStatus, 1, -1 };
87*5e7646d2SAndroid Build Coastguard Worker 					/* Current state OID */
88*5e7646d2SAndroid Build Coastguard Worker static const int	hrPrinterDetectedErrorState[] =
89*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_hrPrinterDetectedErrorState, 1, -1 };
90*5e7646d2SAndroid Build Coastguard Worker 					/* Current printer state bits OID */
91*5e7646d2SAndroid Build Coastguard Worker static const int	prtGeneralCurrentLocalization[] =
92*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtGeneralCurrentLocalization, 1, -1 };
93*5e7646d2SAndroid Build Coastguard Worker static const int	prtLocalizationCharacterSet[] =
94*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtLocalizationCharacterSet, 1, 1, -1 },
95*5e7646d2SAndroid Build Coastguard Worker 			prtLocalizationCharacterSetOffset =
96*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtLocalizationCharacterSet) /
97*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtLocalizationCharacterSet[0]));
98*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerColorantValue[] =
99*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerColorantValue, -1 },
100*5e7646d2SAndroid Build Coastguard Worker 					/* Colorant OID */
101*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerColorantValueOffset =
102*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerColorantValue) /
103*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerColorantValue[0]));
104*5e7646d2SAndroid Build Coastguard Worker 					/* Offset to colorant index */
105*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerLifeCount[] =
106*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerLifeCount, 1, 1, -1 };
107*5e7646d2SAndroid Build Coastguard Worker 					/* Page counter OID */
108*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesEntry[] =
109*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesEntry, -1 };
110*5e7646d2SAndroid Build Coastguard Worker 					/* Supplies OID */
111*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesColorantIndex[] =
112*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesColorantIndex, -1 },
113*5e7646d2SAndroid Build Coastguard Worker 					/* Colorant index OID */
114*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesColorantIndexOffset =
115*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesColorantIndex) /
116*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesColorantIndex[0]));
117*5e7646d2SAndroid Build Coastguard Worker 			 		/* Offset to supply index */
118*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesDescription[] =
119*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesDescription, -1 },
120*5e7646d2SAndroid Build Coastguard Worker 					/* Description OID */
121*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesDescriptionOffset =
122*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesDescription) /
123*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesDescription[0]));
124*5e7646d2SAndroid Build Coastguard Worker 			 		/* Offset to supply index */
125*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesLevel[] =
126*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesLevel, -1 },
127*5e7646d2SAndroid Build Coastguard Worker 					/* Level OID */
128*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesLevelOffset =
129*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesLevel) /
130*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesLevel[0]));
131*5e7646d2SAndroid Build Coastguard Worker 			 		/* Offset to supply index */
132*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesMaxCapacity[] =
133*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesMaxCapacity, -1 },
134*5e7646d2SAndroid Build Coastguard Worker 					/* Max capacity OID */
135*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesMaxCapacityOffset =
136*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesMaxCapacity) /
137*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesMaxCapacity[0]));
138*5e7646d2SAndroid Build Coastguard Worker 			 		/* Offset to supply index */
139*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesClass[] =
140*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesClass, -1 },
141*5e7646d2SAndroid Build Coastguard Worker 					/* Class OID */
142*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesClassOffset =
143*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesClass) /
144*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesClass[0]));
145*5e7646d2SAndroid Build Coastguard Worker 			 		/* Offset to supply index */
146*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesType[] =
147*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesType, -1 },
148*5e7646d2SAndroid Build Coastguard Worker 					/* Type OID */
149*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesTypeOffset =
150*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesType) /
151*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesType[0]));
152*5e7646d2SAndroid Build Coastguard Worker 			 		/* Offset to supply index */
153*5e7646d2SAndroid Build Coastguard Worker static const int	prtMarkerSuppliesSupplyUnit[] =
154*5e7646d2SAndroid Build Coastguard Worker 			{ CUPS_OID_prtMarkerSuppliesSupplyUnit, -1 },
155*5e7646d2SAndroid Build Coastguard Worker 					/* Units OID */
156*5e7646d2SAndroid Build Coastguard Worker 			prtMarkerSuppliesSupplyUnitOffset =
157*5e7646d2SAndroid Build Coastguard Worker 			(sizeof(prtMarkerSuppliesSupplyUnit) /
158*5e7646d2SAndroid Build Coastguard Worker 			 sizeof(prtMarkerSuppliesSupplyUnit[0]));
159*5e7646d2SAndroid Build Coastguard Worker 					/* Offset to supply index */
160*5e7646d2SAndroid Build Coastguard Worker 
161*5e7646d2SAndroid Build Coastguard Worker static const backend_state_t printer_states[] =
162*5e7646d2SAndroid Build Coastguard Worker 			{
163*5e7646d2SAndroid Build Coastguard Worker 			  /* { CUPS_TC_lowPaper, "media-low-report" }, */
164*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty, "media-empty-warning" },
165*5e7646d2SAndroid Build Coastguard Worker 			  /* { CUPS_TC_lowToner, "toner-low-report" }, */ /* now use prtMarkerSupplies */
166*5e7646d2SAndroid Build Coastguard Worker 			  /* { CUPS_TC_noToner, "toner-empty-warning" }, */ /* now use prtMarkerSupplies */
167*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_doorOpen, "door-open-report" },
168*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_jammed, "media-jam-warning" },
169*5e7646d2SAndroid Build Coastguard Worker 			  /* { CUPS_TC_offline, "offline-report" }, */ /* unreliable */
170*5e7646d2SAndroid Build Coastguard Worker 			  /* { CUPS_TC_serviceRequested | CUPS_TC_overduePreventMaint, "service-needed-warning" }, */ /* unreliable */
171*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_inputTrayMissing, "input-tray-missing-warning" },
172*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_outputTrayMissing, "output-tray-missing-warning" },
173*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_markerSupplyMissing, "marker-supply-missing-warning" },
174*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_outputNearFull, "output-area-almost-full-report" },
175*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TC_outputFull, "output-area-full-warning" }
176*5e7646d2SAndroid Build Coastguard Worker 			};
177*5e7646d2SAndroid Build Coastguard Worker 
178*5e7646d2SAndroid Build Coastguard Worker static const backend_state_t supply_states[] =
179*5e7646d2SAndroid Build Coastguard Worker 			{
180*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_DEVELOPER_LOW, "developer-low-report" },
181*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_DEVELOPER_EMPTY, "developer-empty-warning" },
182*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_MARKER_SUPPLY_LOW, "marker-supply-low-report" },
183*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_MARKER_SUPPLY_EMPTY, "marker-supply-empty-warning" },
184*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_OPC_NEAR_EOL, "opc-near-eol-report" },
185*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_OPC_LIFE_OVER, "opc-life-over-warning" },
186*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TONER_LOW, "toner-low-report" },
187*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_TONER_EMPTY, "toner-empty-warning" },
188*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_WASTE_ALMOST_FULL, "waste-receptacle-almost-full-report" },
189*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_WASTE_FULL, "waste-receptacle-full-warning" },
190*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_CLEANER_NEAR_EOL, "cleaner-life-almost-over-report" },
191*5e7646d2SAndroid Build Coastguard Worker 			  { CUPS_CLEANER_LIFE_OVER, "cleaner-life-over-warning" },
192*5e7646d2SAndroid Build Coastguard Worker 			};
193*5e7646d2SAndroid Build Coastguard Worker 
194*5e7646d2SAndroid Build Coastguard Worker 
195*5e7646d2SAndroid Build Coastguard Worker /*
196*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
197*5e7646d2SAndroid Build Coastguard Worker  */
198*5e7646d2SAndroid Build Coastguard Worker 
199*5e7646d2SAndroid Build Coastguard Worker static void	backend_init_supplies(int snmp_fd, http_addr_t *addr);
200*5e7646d2SAndroid Build Coastguard Worker static void	backend_walk_cb(cups_snmp_t *packet, void *data);
201*5e7646d2SAndroid Build Coastguard Worker static void	utf16_to_utf8(cups_utf8_t *dst, const unsigned char *src,
202*5e7646d2SAndroid Build Coastguard Worker 			      size_t srcsize, size_t dstsize, int le);
203*5e7646d2SAndroid Build Coastguard Worker 
204*5e7646d2SAndroid Build Coastguard Worker 
205*5e7646d2SAndroid Build Coastguard Worker /*
206*5e7646d2SAndroid Build Coastguard Worker  * 'backendSNMPSupplies()' - Get the current supplies for a device.
207*5e7646d2SAndroid Build Coastguard Worker  */
208*5e7646d2SAndroid Build Coastguard Worker 
209*5e7646d2SAndroid Build Coastguard Worker int					/* O - 0 on success, -1 on error */
backendSNMPSupplies(int snmp_fd,http_addr_t * addr,int * page_count,int * printer_state)210*5e7646d2SAndroid Build Coastguard Worker backendSNMPSupplies(
211*5e7646d2SAndroid Build Coastguard Worker     int         snmp_fd,		/* I - SNMP socket */
212*5e7646d2SAndroid Build Coastguard Worker     http_addr_t *addr,			/* I - Printer address */
213*5e7646d2SAndroid Build Coastguard Worker     int         *page_count,		/* O - Page count */
214*5e7646d2SAndroid Build Coastguard Worker     int         *printer_state)		/* O - Printer state */
215*5e7646d2SAndroid Build Coastguard Worker {
216*5e7646d2SAndroid Build Coastguard Worker   if (!httpAddrEqual(addr, &current_addr))
217*5e7646d2SAndroid Build Coastguard Worker     backend_init_supplies(snmp_fd, addr);
218*5e7646d2SAndroid Build Coastguard Worker   else if (num_supplies > 0)
219*5e7646d2SAndroid Build Coastguard Worker     _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
220*5e7646d2SAndroid Build Coastguard Worker 		  _cupsSNMPDefaultCommunity(), prtMarkerSuppliesLevel,
221*5e7646d2SAndroid Build Coastguard Worker 		  CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
222*5e7646d2SAndroid Build Coastguard Worker 
223*5e7646d2SAndroid Build Coastguard Worker   if (page_count)
224*5e7646d2SAndroid Build Coastguard Worker     *page_count = -1;
225*5e7646d2SAndroid Build Coastguard Worker 
226*5e7646d2SAndroid Build Coastguard Worker   if (printer_state)
227*5e7646d2SAndroid Build Coastguard Worker     *printer_state = -1;
228*5e7646d2SAndroid Build Coastguard Worker 
229*5e7646d2SAndroid Build Coastguard Worker   if (num_supplies > 0)
230*5e7646d2SAndroid Build Coastguard Worker   {
231*5e7646d2SAndroid Build Coastguard Worker     int		i,			/* Looping var */
232*5e7646d2SAndroid Build Coastguard Worker 		percent,		/* Percent full */
233*5e7646d2SAndroid Build Coastguard Worker 		new_state,		/* New state value */
234*5e7646d2SAndroid Build Coastguard Worker 		change_state,		/* State change */
235*5e7646d2SAndroid Build Coastguard Worker 		new_supply_state = 0;	/* Supply state */
236*5e7646d2SAndroid Build Coastguard Worker     char	value[CUPS_MAX_SUPPLIES * 4],
237*5e7646d2SAndroid Build Coastguard Worker 					/* marker-levels value string */
238*5e7646d2SAndroid Build Coastguard Worker 		*ptr;			/* Pointer into value string */
239*5e7646d2SAndroid Build Coastguard Worker     cups_snmp_t	packet;			/* SNMP response packet */
240*5e7646d2SAndroid Build Coastguard Worker 
241*5e7646d2SAndroid Build Coastguard Worker    /*
242*5e7646d2SAndroid Build Coastguard Worker     * Generate the marker-levels value string...
243*5e7646d2SAndroid Build Coastguard Worker     */
244*5e7646d2SAndroid Build Coastguard Worker 
245*5e7646d2SAndroid Build Coastguard Worker     for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
246*5e7646d2SAndroid Build Coastguard Worker     {
247*5e7646d2SAndroid Build Coastguard Worker       if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
248*5e7646d2SAndroid Build Coastguard Worker 	percent = 100 * supplies[i].level / supplies[i].max_capacity;
249*5e7646d2SAndroid Build Coastguard Worker       else if (supplies[i].level >= 0 && supplies[i].level <= 100 &&
250*5e7646d2SAndroid Build Coastguard Worker                (quirks & CUPS_SNMP_CAPACITY))
251*5e7646d2SAndroid Build Coastguard Worker         percent = supplies[i].level;
252*5e7646d2SAndroid Build Coastguard Worker       else
253*5e7646d2SAndroid Build Coastguard Worker         percent = 50;
254*5e7646d2SAndroid Build Coastguard Worker 
255*5e7646d2SAndroid Build Coastguard Worker       if (supplies[i].sclass == CUPS_TC_receptacleThatIsFilled)
256*5e7646d2SAndroid Build Coastguard Worker         percent = 100 - percent;
257*5e7646d2SAndroid Build Coastguard Worker 
258*5e7646d2SAndroid Build Coastguard Worker       if (percent <= 5)
259*5e7646d2SAndroid Build Coastguard Worker       {
260*5e7646d2SAndroid Build Coastguard Worker         switch (supplies[i].type)
261*5e7646d2SAndroid Build Coastguard Worker         {
262*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_toner :
263*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_tonerCartridge :
264*5e7646d2SAndroid Build Coastguard Worker               if (percent <= 1)
265*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_TONER_EMPTY;
266*5e7646d2SAndroid Build Coastguard Worker               else
267*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_TONER_LOW;
268*5e7646d2SAndroid Build Coastguard Worker               break;
269*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_ink :
270*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_inkCartridge :
271*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_inkRibbon :
272*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_solidWax :
273*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_ribbonWax :
274*5e7646d2SAndroid Build Coastguard Worker               if (percent <= 1)
275*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_MARKER_SUPPLY_EMPTY;
276*5e7646d2SAndroid Build Coastguard Worker               else
277*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_MARKER_SUPPLY_LOW;
278*5e7646d2SAndroid Build Coastguard Worker               break;
279*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_developer :
280*5e7646d2SAndroid Build Coastguard Worker               if (percent <= 1)
281*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_DEVELOPER_EMPTY;
282*5e7646d2SAndroid Build Coastguard Worker               else
283*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_DEVELOPER_LOW;
284*5e7646d2SAndroid Build Coastguard Worker               break;
285*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_coronaWire :
286*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_fuser :
287*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_opc :
288*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_transferUnit :
289*5e7646d2SAndroid Build Coastguard Worker               if (percent <= 1)
290*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_OPC_LIFE_OVER;
291*5e7646d2SAndroid Build Coastguard Worker               else
292*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_OPC_NEAR_EOL;
293*5e7646d2SAndroid Build Coastguard Worker               break;
294*5e7646d2SAndroid Build Coastguard Worker #if 0 /* Because no two vendors report waste containers the same, disable SNMP reporting of same */
295*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_wasteInk :
296*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_wastePaper :
297*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_wasteToner :
298*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_wasteWater :
299*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_wasteWax :
300*5e7646d2SAndroid Build Coastguard Worker               if (percent <= 1)
301*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_WASTE_FULL;
302*5e7646d2SAndroid Build Coastguard Worker               else
303*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_WASTE_ALMOST_FULL;
304*5e7646d2SAndroid Build Coastguard Worker               break;
305*5e7646d2SAndroid Build Coastguard Worker #endif /* 0 */
306*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_cleanerUnit :
307*5e7646d2SAndroid Build Coastguard Worker           case CUPS_TC_fuserCleaningPad :
308*5e7646d2SAndroid Build Coastguard Worker               if (percent <= 1)
309*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_CLEANER_LIFE_OVER;
310*5e7646d2SAndroid Build Coastguard Worker               else
311*5e7646d2SAndroid Build Coastguard Worker                 new_supply_state |= CUPS_CLEANER_NEAR_EOL;
312*5e7646d2SAndroid Build Coastguard Worker               break;
313*5e7646d2SAndroid Build Coastguard Worker         }
314*5e7646d2SAndroid Build Coastguard Worker       }
315*5e7646d2SAndroid Build Coastguard Worker 
316*5e7646d2SAndroid Build Coastguard Worker       if (i)
317*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = ',';
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker       if ((supplies[i].max_capacity > 0 || (quirks & CUPS_SNMP_CAPACITY)) &&
320*5e7646d2SAndroid Build Coastguard Worker           supplies[i].level >= 0)
321*5e7646d2SAndroid Build Coastguard Worker         snprintf(ptr, sizeof(value) - (size_t)(ptr - value), "%d", percent);
322*5e7646d2SAndroid Build Coastguard Worker       else
323*5e7646d2SAndroid Build Coastguard Worker         strlcpy(ptr, "-1", sizeof(value) - (size_t)(ptr - value));
324*5e7646d2SAndroid Build Coastguard Worker     }
325*5e7646d2SAndroid Build Coastguard Worker 
326*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ATTR: marker-levels=%s\n", value);
327*5e7646d2SAndroid Build Coastguard Worker 
328*5e7646d2SAndroid Build Coastguard Worker     if (supply_state < 0)
329*5e7646d2SAndroid Build Coastguard Worker       change_state = 0xffff;
330*5e7646d2SAndroid Build Coastguard Worker     else
331*5e7646d2SAndroid Build Coastguard Worker       change_state = supply_state ^ new_supply_state;
332*5e7646d2SAndroid Build Coastguard Worker 
333*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: new_supply_state=%x, change_state=%x\n",
334*5e7646d2SAndroid Build Coastguard Worker             new_supply_state, change_state);
335*5e7646d2SAndroid Build Coastguard Worker 
336*5e7646d2SAndroid Build Coastguard Worker     for (i = 0;
337*5e7646d2SAndroid Build Coastguard Worker          i < (int)(sizeof(supply_states) / sizeof(supply_states[0]));
338*5e7646d2SAndroid Build Coastguard Worker          i ++)
339*5e7646d2SAndroid Build Coastguard Worker       if (change_state & supply_states[i].bit)
340*5e7646d2SAndroid Build Coastguard Worker       {
341*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "STATE: %c%s\n",
342*5e7646d2SAndroid Build Coastguard Worker 		(new_supply_state & supply_states[i].bit) ? '+' : '-',
343*5e7646d2SAndroid Build Coastguard Worker 		supply_states[i].keyword);
344*5e7646d2SAndroid Build Coastguard Worker       }
345*5e7646d2SAndroid Build Coastguard Worker 
346*5e7646d2SAndroid Build Coastguard Worker     supply_state = new_supply_state;
347*5e7646d2SAndroid Build Coastguard Worker 
348*5e7646d2SAndroid Build Coastguard Worker    /*
349*5e7646d2SAndroid Build Coastguard Worker     * Get the current printer status bits...
350*5e7646d2SAndroid Build Coastguard Worker     */
351*5e7646d2SAndroid Build Coastguard Worker 
352*5e7646d2SAndroid Build Coastguard Worker     if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
353*5e7646d2SAndroid Build Coastguard Worker                        _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
354*5e7646d2SAndroid Build Coastguard Worker                        hrPrinterDetectedErrorState))
355*5e7646d2SAndroid Build Coastguard Worker       return (-1);
356*5e7646d2SAndroid Build Coastguard Worker 
357*5e7646d2SAndroid Build Coastguard Worker     if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
358*5e7646d2SAndroid Build Coastguard Worker         packet.object_type != CUPS_ASN1_OCTET_STRING)
359*5e7646d2SAndroid Build Coastguard Worker       return (-1);
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker     if (packet.object_value.string.num_bytes == 2)
362*5e7646d2SAndroid Build Coastguard Worker       new_state = (packet.object_value.string.bytes[0] << 8) |
363*5e7646d2SAndroid Build Coastguard Worker 		  packet.object_value.string.bytes[1];
364*5e7646d2SAndroid Build Coastguard Worker     else if (packet.object_value.string.num_bytes == 1)
365*5e7646d2SAndroid Build Coastguard Worker       new_state = (packet.object_value.string.bytes[0] << 8);
366*5e7646d2SAndroid Build Coastguard Worker     else
367*5e7646d2SAndroid Build Coastguard Worker       new_state = 0;
368*5e7646d2SAndroid Build Coastguard Worker 
369*5e7646d2SAndroid Build Coastguard Worker     if (current_state < 0)
370*5e7646d2SAndroid Build Coastguard Worker       change_state = 0xffff;
371*5e7646d2SAndroid Build Coastguard Worker     else
372*5e7646d2SAndroid Build Coastguard Worker       change_state = current_state ^ new_state;
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: new_state=%x, change_state=%x\n", new_state,
375*5e7646d2SAndroid Build Coastguard Worker             change_state);
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker     for (i = 0;
378*5e7646d2SAndroid Build Coastguard Worker          i < (int)(sizeof(printer_states) / sizeof(printer_states[0]));
379*5e7646d2SAndroid Build Coastguard Worker          i ++)
380*5e7646d2SAndroid Build Coastguard Worker       if (change_state & printer_states[i].bit)
381*5e7646d2SAndroid Build Coastguard Worker       {
382*5e7646d2SAndroid Build Coastguard Worker 	fprintf(stderr, "STATE: %c%s\n",
383*5e7646d2SAndroid Build Coastguard Worker 		(new_state & printer_states[i].bit) ? '+' : '-',
384*5e7646d2SAndroid Build Coastguard Worker 		printer_states[i].keyword);
385*5e7646d2SAndroid Build Coastguard Worker       }
386*5e7646d2SAndroid Build Coastguard Worker 
387*5e7646d2SAndroid Build Coastguard Worker     current_state = new_state;
388*5e7646d2SAndroid Build Coastguard Worker 
389*5e7646d2SAndroid Build Coastguard Worker    /*
390*5e7646d2SAndroid Build Coastguard Worker     * Get the current printer state...
391*5e7646d2SAndroid Build Coastguard Worker     */
392*5e7646d2SAndroid Build Coastguard Worker 
393*5e7646d2SAndroid Build Coastguard Worker     if (printer_state)
394*5e7646d2SAndroid Build Coastguard Worker     {
395*5e7646d2SAndroid Build Coastguard Worker       if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
396*5e7646d2SAndroid Build Coastguard Worker 			 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
397*5e7646d2SAndroid Build Coastguard Worker 			 hrPrinterStatus))
398*5e7646d2SAndroid Build Coastguard Worker 	return (-1);
399*5e7646d2SAndroid Build Coastguard Worker 
400*5e7646d2SAndroid Build Coastguard Worker       if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
401*5e7646d2SAndroid Build Coastguard Worker 	  packet.object_type != CUPS_ASN1_INTEGER)
402*5e7646d2SAndroid Build Coastguard Worker 	return (-1);
403*5e7646d2SAndroid Build Coastguard Worker 
404*5e7646d2SAndroid Build Coastguard Worker       *printer_state = packet.object_value.integer;
405*5e7646d2SAndroid Build Coastguard Worker     }
406*5e7646d2SAndroid Build Coastguard Worker 
407*5e7646d2SAndroid Build Coastguard Worker    /*
408*5e7646d2SAndroid Build Coastguard Worker     * Get the current page count...
409*5e7646d2SAndroid Build Coastguard Worker     */
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker     if (page_count)
412*5e7646d2SAndroid Build Coastguard Worker     {
413*5e7646d2SAndroid Build Coastguard Worker       if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
414*5e7646d2SAndroid Build Coastguard Worker 			 _cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
415*5e7646d2SAndroid Build Coastguard Worker 			 prtMarkerLifeCount))
416*5e7646d2SAndroid Build Coastguard Worker 	return (-1);
417*5e7646d2SAndroid Build Coastguard Worker 
418*5e7646d2SAndroid Build Coastguard Worker       if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
419*5e7646d2SAndroid Build Coastguard Worker 	  packet.object_type != CUPS_ASN1_COUNTER)
420*5e7646d2SAndroid Build Coastguard Worker 	return (-1);
421*5e7646d2SAndroid Build Coastguard Worker 
422*5e7646d2SAndroid Build Coastguard Worker       *page_count = packet.object_value.counter;
423*5e7646d2SAndroid Build Coastguard Worker     }
424*5e7646d2SAndroid Build Coastguard Worker 
425*5e7646d2SAndroid Build Coastguard Worker     return (0);
426*5e7646d2SAndroid Build Coastguard Worker   }
427*5e7646d2SAndroid Build Coastguard Worker   else
428*5e7646d2SAndroid Build Coastguard Worker     return (-1);
429*5e7646d2SAndroid Build Coastguard Worker }
430*5e7646d2SAndroid Build Coastguard Worker 
431*5e7646d2SAndroid Build Coastguard Worker 
432*5e7646d2SAndroid Build Coastguard Worker /*
433*5e7646d2SAndroid Build Coastguard Worker  * 'backend_init_supplies()' - Initialize the supplies list.
434*5e7646d2SAndroid Build Coastguard Worker  */
435*5e7646d2SAndroid Build Coastguard Worker 
436*5e7646d2SAndroid Build Coastguard Worker static void
backend_init_supplies(int snmp_fd,http_addr_t * addr)437*5e7646d2SAndroid Build Coastguard Worker backend_init_supplies(
438*5e7646d2SAndroid Build Coastguard Worker     int         snmp_fd,		/* I - SNMP socket */
439*5e7646d2SAndroid Build Coastguard Worker     http_addr_t *addr)			/* I - Printer address */
440*5e7646d2SAndroid Build Coastguard Worker {
441*5e7646d2SAndroid Build Coastguard Worker   int		i,			/* Looping var */
442*5e7646d2SAndroid Build Coastguard Worker 		type;			/* Current marker type */
443*5e7646d2SAndroid Build Coastguard Worker   const char	*community;		/* SNMP community name */
444*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*cachefile;		/* Cache file */
445*5e7646d2SAndroid Build Coastguard Worker   const char	*cachedir;		/* CUPS_CACHEDIR value */
446*5e7646d2SAndroid Build Coastguard Worker   char		addrstr[1024],		/* Address string */
447*5e7646d2SAndroid Build Coastguard Worker 		cachefilename[1024],	/* Cache filename */
448*5e7646d2SAndroid Build Coastguard Worker 		description[CUPS_SNMP_MAX_STRING],
449*5e7646d2SAndroid Build Coastguard Worker 					/* Device description string */
450*5e7646d2SAndroid Build Coastguard Worker 		value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 4 + 3)],
451*5e7646d2SAndroid Build Coastguard Worker 					/* Value string */
452*5e7646d2SAndroid Build Coastguard Worker 		*ptr,			/* Pointer into value string */
453*5e7646d2SAndroid Build Coastguard Worker 		*name_ptr;		/* Pointer into name string */
454*5e7646d2SAndroid Build Coastguard Worker   cups_snmp_t	packet;			/* SNMP response packet */
455*5e7646d2SAndroid Build Coastguard Worker   ppd_file_t	*ppd;			/* PPD file for this queue */
456*5e7646d2SAndroid Build Coastguard Worker   ppd_attr_t	*ppdattr;		/* cupsSNMPSupplies attribute */
457*5e7646d2SAndroid Build Coastguard Worker   static const char * const types[] =	/* Supply types */
458*5e7646d2SAndroid Build Coastguard Worker 		{
459*5e7646d2SAndroid Build Coastguard Worker 		  "other",
460*5e7646d2SAndroid Build Coastguard Worker 		  "unknown",
461*5e7646d2SAndroid Build Coastguard Worker 		  "toner",
462*5e7646d2SAndroid Build Coastguard Worker 		  "waste-toner",
463*5e7646d2SAndroid Build Coastguard Worker 		  "ink",
464*5e7646d2SAndroid Build Coastguard Worker 		  "ink-cartridge",
465*5e7646d2SAndroid Build Coastguard Worker 		  "ink-ribbon",
466*5e7646d2SAndroid Build Coastguard Worker 		  "waste-ink",
467*5e7646d2SAndroid Build Coastguard Worker 		  "opc",
468*5e7646d2SAndroid Build Coastguard Worker 		  "developer",
469*5e7646d2SAndroid Build Coastguard Worker 		  "fuser-oil",
470*5e7646d2SAndroid Build Coastguard Worker 		  "solid-wax",
471*5e7646d2SAndroid Build Coastguard Worker 		  "ribbon-wax",
472*5e7646d2SAndroid Build Coastguard Worker 		  "waste-wax",
473*5e7646d2SAndroid Build Coastguard Worker 		  "fuser",
474*5e7646d2SAndroid Build Coastguard Worker 		  "corona-wire",
475*5e7646d2SAndroid Build Coastguard Worker 		  "fuser-oil-wick",
476*5e7646d2SAndroid Build Coastguard Worker 		  "cleaner-unit",
477*5e7646d2SAndroid Build Coastguard Worker 		  "fuser-cleaning-pad",
478*5e7646d2SAndroid Build Coastguard Worker 		  "transfer-unit",
479*5e7646d2SAndroid Build Coastguard Worker 		  "toner-cartridge",
480*5e7646d2SAndroid Build Coastguard Worker 		  "fuser-oiler",
481*5e7646d2SAndroid Build Coastguard Worker 		  "water",
482*5e7646d2SAndroid Build Coastguard Worker 		  "waste-water",
483*5e7646d2SAndroid Build Coastguard Worker 		  "glue-water-additive",
484*5e7646d2SAndroid Build Coastguard Worker 		  "waste-paper",
485*5e7646d2SAndroid Build Coastguard Worker 		  "binding-supply",
486*5e7646d2SAndroid Build Coastguard Worker 		  "banding-supply",
487*5e7646d2SAndroid Build Coastguard Worker 		  "stitching-wire",
488*5e7646d2SAndroid Build Coastguard Worker 		  "shrink-wrap",
489*5e7646d2SAndroid Build Coastguard Worker 		  "paper-wrap",
490*5e7646d2SAndroid Build Coastguard Worker 		  "staples",
491*5e7646d2SAndroid Build Coastguard Worker 		  "inserts",
492*5e7646d2SAndroid Build Coastguard Worker 		  "covers"
493*5e7646d2SAndroid Build Coastguard Worker 		};
494*5e7646d2SAndroid Build Coastguard Worker 
495*5e7646d2SAndroid Build Coastguard Worker 
496*5e7646d2SAndroid Build Coastguard Worker  /*
497*5e7646d2SAndroid Build Coastguard Worker   * Reset state information...
498*5e7646d2SAndroid Build Coastguard Worker   */
499*5e7646d2SAndroid Build Coastguard Worker 
500*5e7646d2SAndroid Build Coastguard Worker   current_addr  = *addr;
501*5e7646d2SAndroid Build Coastguard Worker   current_state = -1;
502*5e7646d2SAndroid Build Coastguard Worker   num_supplies  = -1;
503*5e7646d2SAndroid Build Coastguard Worker   charset       = -1;
504*5e7646d2SAndroid Build Coastguard Worker 
505*5e7646d2SAndroid Build Coastguard Worker   memset(supplies, 0, sizeof(supplies));
506*5e7646d2SAndroid Build Coastguard Worker 
507*5e7646d2SAndroid Build Coastguard Worker  /*
508*5e7646d2SAndroid Build Coastguard Worker   * See if we should be getting supply levels via SNMP...
509*5e7646d2SAndroid Build Coastguard Worker   */
510*5e7646d2SAndroid Build Coastguard Worker 
511*5e7646d2SAndroid Build Coastguard Worker   community = _cupsSNMPDefaultCommunity();
512*5e7646d2SAndroid Build Coastguard Worker   if (!*community)
513*5e7646d2SAndroid Build Coastguard Worker     return;
514*5e7646d2SAndroid Build Coastguard Worker 
515*5e7646d2SAndroid Build Coastguard Worker   if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL ||
516*5e7646d2SAndroid Build Coastguard Worker       ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL &&
517*5e7646d2SAndroid Build Coastguard Worker        ppdattr->value && _cups_strcasecmp(ppdattr->value, "true")))
518*5e7646d2SAndroid Build Coastguard Worker   {
519*5e7646d2SAndroid Build Coastguard Worker     ppdClose(ppd);
520*5e7646d2SAndroid Build Coastguard Worker     return;
521*5e7646d2SAndroid Build Coastguard Worker   }
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker   if ((ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL)
524*5e7646d2SAndroid Build Coastguard Worker   {
525*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(ppdattr->value, "capacity"))
526*5e7646d2SAndroid Build Coastguard Worker       quirks |= CUPS_SNMP_CAPACITY;
527*5e7646d2SAndroid Build Coastguard Worker   }
528*5e7646d2SAndroid Build Coastguard Worker 
529*5e7646d2SAndroid Build Coastguard Worker   ppdClose(ppd);
530*5e7646d2SAndroid Build Coastguard Worker 
531*5e7646d2SAndroid Build Coastguard Worker  /*
532*5e7646d2SAndroid Build Coastguard Worker   * Get the device description...
533*5e7646d2SAndroid Build Coastguard Worker   */
534*5e7646d2SAndroid Build Coastguard Worker 
535*5e7646d2SAndroid Build Coastguard Worker   if (!_cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
536*5e7646d2SAndroid Build Coastguard Worker 		     community, CUPS_ASN1_GET_REQUEST, 1,
537*5e7646d2SAndroid Build Coastguard Worker 		     hrDeviceDescr))
538*5e7646d2SAndroid Build Coastguard Worker     return;
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker   if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
541*5e7646d2SAndroid Build Coastguard Worker       packet.object_type != CUPS_ASN1_OCTET_STRING)
542*5e7646d2SAndroid Build Coastguard Worker   {
543*5e7646d2SAndroid Build Coastguard Worker     strlcpy(description, "Unknown", sizeof(description));
544*5e7646d2SAndroid Build Coastguard Worker     num_supplies = 0;
545*5e7646d2SAndroid Build Coastguard Worker   }
546*5e7646d2SAndroid Build Coastguard Worker   else
547*5e7646d2SAndroid Build Coastguard Worker     strlcpy(description, (char *)packet.object_value.string.bytes,
548*5e7646d2SAndroid Build Coastguard Worker             sizeof(description));
549*5e7646d2SAndroid Build Coastguard Worker 
550*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG2: hrDeviceDesc=\"%s\"\n", description);
551*5e7646d2SAndroid Build Coastguard Worker 
552*5e7646d2SAndroid Build Coastguard Worker  /*
553*5e7646d2SAndroid Build Coastguard Worker   * See if we have already queried this device...
554*5e7646d2SAndroid Build Coastguard Worker   */
555*5e7646d2SAndroid Build Coastguard Worker 
556*5e7646d2SAndroid Build Coastguard Worker   httpAddrString(addr, addrstr, sizeof(addrstr));
557*5e7646d2SAndroid Build Coastguard Worker 
558*5e7646d2SAndroid Build Coastguard Worker   if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
559*5e7646d2SAndroid Build Coastguard Worker     cachedir = CUPS_CACHEDIR;
560*5e7646d2SAndroid Build Coastguard Worker 
561*5e7646d2SAndroid Build Coastguard Worker   snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir,
562*5e7646d2SAndroid Build Coastguard Worker            addrstr);
563*5e7646d2SAndroid Build Coastguard Worker 
564*5e7646d2SAndroid Build Coastguard Worker   if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL)
565*5e7646d2SAndroid Build Coastguard Worker   {
566*5e7646d2SAndroid Build Coastguard Worker    /*
567*5e7646d2SAndroid Build Coastguard Worker     * Yes, read the cache file:
568*5e7646d2SAndroid Build Coastguard Worker     *
569*5e7646d2SAndroid Build Coastguard Worker     *     3 num_supplies charset
570*5e7646d2SAndroid Build Coastguard Worker     *     device description
571*5e7646d2SAndroid Build Coastguard Worker     *     supply structures...
572*5e7646d2SAndroid Build Coastguard Worker     */
573*5e7646d2SAndroid Build Coastguard Worker 
574*5e7646d2SAndroid Build Coastguard Worker     if (cupsFileGets(cachefile, value, sizeof(value)))
575*5e7646d2SAndroid Build Coastguard Worker     {
576*5e7646d2SAndroid Build Coastguard Worker       if (sscanf(value, "3 %d%d", &num_supplies, &charset) == 2 &&
577*5e7646d2SAndroid Build Coastguard Worker           num_supplies <= CUPS_MAX_SUPPLIES &&
578*5e7646d2SAndroid Build Coastguard Worker           cupsFileGets(cachefile, value, sizeof(value)))
579*5e7646d2SAndroid Build Coastguard Worker       {
580*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(description, value))
581*5e7646d2SAndroid Build Coastguard Worker 	  cupsFileRead(cachefile, (char *)supplies,
582*5e7646d2SAndroid Build Coastguard Worker 	               (size_t)num_supplies * sizeof(backend_supplies_t));
583*5e7646d2SAndroid Build Coastguard Worker         else
584*5e7646d2SAndroid Build Coastguard Worker 	{
585*5e7646d2SAndroid Build Coastguard Worker 	  num_supplies = -1;
586*5e7646d2SAndroid Build Coastguard Worker 	  charset      = -1;
587*5e7646d2SAndroid Build Coastguard Worker 	}
588*5e7646d2SAndroid Build Coastguard Worker       }
589*5e7646d2SAndroid Build Coastguard Worker       else
590*5e7646d2SAndroid Build Coastguard Worker       {
591*5e7646d2SAndroid Build Coastguard Worker         num_supplies = -1;
592*5e7646d2SAndroid Build Coastguard Worker 	charset      = -1;
593*5e7646d2SAndroid Build Coastguard Worker       }
594*5e7646d2SAndroid Build Coastguard Worker     }
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(cachefile);
597*5e7646d2SAndroid Build Coastguard Worker   }
598*5e7646d2SAndroid Build Coastguard Worker 
599*5e7646d2SAndroid Build Coastguard Worker  /*
600*5e7646d2SAndroid Build Coastguard Worker   * If the cache information isn't correct, scan for supplies...
601*5e7646d2SAndroid Build Coastguard Worker   */
602*5e7646d2SAndroid Build Coastguard Worker 
603*5e7646d2SAndroid Build Coastguard Worker   if (charset < 0)
604*5e7646d2SAndroid Build Coastguard Worker   {
605*5e7646d2SAndroid Build Coastguard Worker    /*
606*5e7646d2SAndroid Build Coastguard Worker     * Get the configured character set...
607*5e7646d2SAndroid Build Coastguard Worker     */
608*5e7646d2SAndroid Build Coastguard Worker 
609*5e7646d2SAndroid Build Coastguard Worker     int	oid[CUPS_SNMP_MAX_OID];		/* OID for character set */
610*5e7646d2SAndroid Build Coastguard Worker 
611*5e7646d2SAndroid Build Coastguard Worker 
612*5e7646d2SAndroid Build Coastguard Worker     if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
613*5e7646d2SAndroid Build Coastguard Worker 			community, CUPS_ASN1_GET_REQUEST, 1,
614*5e7646d2SAndroid Build Coastguard Worker 			prtGeneralCurrentLocalization))
615*5e7646d2SAndroid Build Coastguard Worker       return;
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker     if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
618*5e7646d2SAndroid Build Coastguard Worker 	packet.object_type != CUPS_ASN1_INTEGER)
619*5e7646d2SAndroid Build Coastguard Worker     {
620*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr,
621*5e7646d2SAndroid Build Coastguard Worker               "DEBUG: prtGeneralCurrentLocalization type is %x, expected %x!\n",
622*5e7646d2SAndroid Build Coastguard Worker 	      packet.object_type, CUPS_ASN1_INTEGER);
623*5e7646d2SAndroid Build Coastguard Worker       return;
624*5e7646d2SAndroid Build Coastguard Worker     }
625*5e7646d2SAndroid Build Coastguard Worker 
626*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtGeneralCurrentLocalization=%d\n",
627*5e7646d2SAndroid Build Coastguard Worker             packet.object_value.integer);
628*5e7646d2SAndroid Build Coastguard Worker 
629*5e7646d2SAndroid Build Coastguard Worker     _cupsSNMPCopyOID(oid, prtLocalizationCharacterSet, CUPS_SNMP_MAX_OID);
630*5e7646d2SAndroid Build Coastguard Worker     oid[prtLocalizationCharacterSetOffset - 2] = packet.object_value.integer;
631*5e7646d2SAndroid Build Coastguard Worker 
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker     if (!_cupsSNMPWrite(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
634*5e7646d2SAndroid Build Coastguard Worker 			community, CUPS_ASN1_GET_REQUEST, 1,
635*5e7646d2SAndroid Build Coastguard Worker 			oid))
636*5e7646d2SAndroid Build Coastguard Worker       return;
637*5e7646d2SAndroid Build Coastguard Worker 
638*5e7646d2SAndroid Build Coastguard Worker     if (!_cupsSNMPRead(snmp_fd, &packet, CUPS_SUPPLY_TIMEOUT) ||
639*5e7646d2SAndroid Build Coastguard Worker 	packet.object_type != CUPS_ASN1_INTEGER)
640*5e7646d2SAndroid Build Coastguard Worker     {
641*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr,
642*5e7646d2SAndroid Build Coastguard Worker               "DEBUG: prtLocalizationCharacterSet type is %x, expected %x!\n",
643*5e7646d2SAndroid Build Coastguard Worker 	      packet.object_type, CUPS_ASN1_INTEGER);
644*5e7646d2SAndroid Build Coastguard Worker       return;
645*5e7646d2SAndroid Build Coastguard Worker     }
646*5e7646d2SAndroid Build Coastguard Worker 
647*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtLocalizationCharacterSet=%d\n",
648*5e7646d2SAndroid Build Coastguard Worker 	    packet.object_value.integer);
649*5e7646d2SAndroid Build Coastguard Worker     charset = packet.object_value.integer;
650*5e7646d2SAndroid Build Coastguard Worker   }
651*5e7646d2SAndroid Build Coastguard Worker 
652*5e7646d2SAndroid Build Coastguard Worker   if (num_supplies < 0)
653*5e7646d2SAndroid Build Coastguard Worker   {
654*5e7646d2SAndroid Build Coastguard Worker    /*
655*5e7646d2SAndroid Build Coastguard Worker     * Walk the printer configuration information...
656*5e7646d2SAndroid Build Coastguard Worker     */
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker     _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
659*5e7646d2SAndroid Build Coastguard Worker 		  community, prtMarkerSuppliesEntry,
660*5e7646d2SAndroid Build Coastguard Worker 		  CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
661*5e7646d2SAndroid Build Coastguard Worker   }
662*5e7646d2SAndroid Build Coastguard Worker 
663*5e7646d2SAndroid Build Coastguard Worker  /*
664*5e7646d2SAndroid Build Coastguard Worker   * Save the cached information...
665*5e7646d2SAndroid Build Coastguard Worker   */
666*5e7646d2SAndroid Build Coastguard Worker 
667*5e7646d2SAndroid Build Coastguard Worker   if (num_supplies < 0)
668*5e7646d2SAndroid Build Coastguard Worker     num_supplies = 0;
669*5e7646d2SAndroid Build Coastguard Worker 
670*5e7646d2SAndroid Build Coastguard Worker   if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
671*5e7646d2SAndroid Build Coastguard Worker   {
672*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(cachefile, "3 %d %d\n", num_supplies, charset);
673*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(cachefile, "%s\n", description);
674*5e7646d2SAndroid Build Coastguard Worker 
675*5e7646d2SAndroid Build Coastguard Worker     if (num_supplies > 0)
676*5e7646d2SAndroid Build Coastguard Worker       cupsFileWrite(cachefile, (char *)supplies,
677*5e7646d2SAndroid Build Coastguard Worker                     (size_t)num_supplies * sizeof(backend_supplies_t));
678*5e7646d2SAndroid Build Coastguard Worker 
679*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(cachefile);
680*5e7646d2SAndroid Build Coastguard Worker   }
681*5e7646d2SAndroid Build Coastguard Worker 
682*5e7646d2SAndroid Build Coastguard Worker   if (num_supplies <= 0)
683*5e7646d2SAndroid Build Coastguard Worker     return;
684*5e7646d2SAndroid Build Coastguard Worker 
685*5e7646d2SAndroid Build Coastguard Worker  /*
686*5e7646d2SAndroid Build Coastguard Worker   * Get the colors...
687*5e7646d2SAndroid Build Coastguard Worker   */
688*5e7646d2SAndroid Build Coastguard Worker 
689*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < num_supplies; i ++)
690*5e7646d2SAndroid Build Coastguard Worker     strlcpy(supplies[i].color, "none", sizeof(supplies[i].color));
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker   _cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
693*5e7646d2SAndroid Build Coastguard Worker                 community, prtMarkerColorantValue,
694*5e7646d2SAndroid Build Coastguard Worker 	        CUPS_SUPPLY_TIMEOUT, backend_walk_cb, NULL);
695*5e7646d2SAndroid Build Coastguard Worker 
696*5e7646d2SAndroid Build Coastguard Worker  /*
697*5e7646d2SAndroid Build Coastguard Worker   * Output the marker-colors attribute...
698*5e7646d2SAndroid Build Coastguard Worker   */
699*5e7646d2SAndroid Build Coastguard Worker 
700*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
701*5e7646d2SAndroid Build Coastguard Worker   {
702*5e7646d2SAndroid Build Coastguard Worker     if (i)
703*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = ',';
704*5e7646d2SAndroid Build Coastguard Worker 
705*5e7646d2SAndroid Build Coastguard Worker     strlcpy(ptr, supplies[i].color, sizeof(value) - (size_t)(ptr - value));
706*5e7646d2SAndroid Build Coastguard Worker   }
707*5e7646d2SAndroid Build Coastguard Worker 
708*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "ATTR: marker-colors=%s\n", value);
709*5e7646d2SAndroid Build Coastguard Worker 
710*5e7646d2SAndroid Build Coastguard Worker  /*
711*5e7646d2SAndroid Build Coastguard Worker   * Output the marker-names attribute (the double quoting is necessary to deal
712*5e7646d2SAndroid Build Coastguard Worker   * with embedded quotes and commas in the marker names...)
713*5e7646d2SAndroid Build Coastguard Worker   */
714*5e7646d2SAndroid Build Coastguard Worker 
715*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, ptr = value; i < num_supplies; i ++)
716*5e7646d2SAndroid Build Coastguard Worker   {
717*5e7646d2SAndroid Build Coastguard Worker     if (i)
718*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = ',';
719*5e7646d2SAndroid Build Coastguard Worker 
720*5e7646d2SAndroid Build Coastguard Worker     *ptr++ = '\'';
721*5e7646d2SAndroid Build Coastguard Worker     *ptr++ = '\"';
722*5e7646d2SAndroid Build Coastguard Worker     for (name_ptr = supplies[i].name; *name_ptr;)
723*5e7646d2SAndroid Build Coastguard Worker     {
724*5e7646d2SAndroid Build Coastguard Worker       if (*name_ptr == '\\' || *name_ptr == '\"' || *name_ptr == '\'')
725*5e7646d2SAndroid Build Coastguard Worker       {
726*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = '\\';
727*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = '\\';
728*5e7646d2SAndroid Build Coastguard Worker         *ptr++ = '\\';
729*5e7646d2SAndroid Build Coastguard Worker       }
730*5e7646d2SAndroid Build Coastguard Worker 
731*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = *name_ptr++;
732*5e7646d2SAndroid Build Coastguard Worker     }
733*5e7646d2SAndroid Build Coastguard Worker     *ptr++ = '\"';
734*5e7646d2SAndroid Build Coastguard Worker     *ptr++ = '\'';
735*5e7646d2SAndroid Build Coastguard Worker   }
736*5e7646d2SAndroid Build Coastguard Worker 
737*5e7646d2SAndroid Build Coastguard Worker   *ptr = '\0';
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "ATTR: marker-names=%s\n", value);
740*5e7646d2SAndroid Build Coastguard Worker 
741*5e7646d2SAndroid Build Coastguard Worker  /*
742*5e7646d2SAndroid Build Coastguard Worker   * Output the marker-types attribute...
743*5e7646d2SAndroid Build Coastguard Worker   */
744*5e7646d2SAndroid Build Coastguard Worker 
745*5e7646d2SAndroid Build Coastguard Worker   for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
746*5e7646d2SAndroid Build Coastguard Worker   {
747*5e7646d2SAndroid Build Coastguard Worker     if (i)
748*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = ',';
749*5e7646d2SAndroid Build Coastguard Worker 
750*5e7646d2SAndroid Build Coastguard Worker     type = supplies[i].type;
751*5e7646d2SAndroid Build Coastguard Worker 
752*5e7646d2SAndroid Build Coastguard Worker     if (type < CUPS_TC_other || type > CUPS_TC_covers)
753*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ptr, "unknown", sizeof(value) - (size_t)(ptr - value));
754*5e7646d2SAndroid Build Coastguard Worker     else
755*5e7646d2SAndroid Build Coastguard Worker       strlcpy(ptr, types[type - CUPS_TC_other], sizeof(value) - (size_t)(ptr - value));
756*5e7646d2SAndroid Build Coastguard Worker   }
757*5e7646d2SAndroid Build Coastguard Worker 
758*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "ATTR: marker-types=%s\n", value);
759*5e7646d2SAndroid Build Coastguard Worker }
760*5e7646d2SAndroid Build Coastguard Worker 
761*5e7646d2SAndroid Build Coastguard Worker 
762*5e7646d2SAndroid Build Coastguard Worker /*
763*5e7646d2SAndroid Build Coastguard Worker  * 'backend_walk_cb()' - Interpret the supply value responses.
764*5e7646d2SAndroid Build Coastguard Worker  */
765*5e7646d2SAndroid Build Coastguard Worker 
766*5e7646d2SAndroid Build Coastguard Worker static void
backend_walk_cb(cups_snmp_t * packet,void * data)767*5e7646d2SAndroid Build Coastguard Worker backend_walk_cb(cups_snmp_t *packet,	/* I - SNMP packet */
768*5e7646d2SAndroid Build Coastguard Worker                 void        *data)	/* I - User data (unused) */
769*5e7646d2SAndroid Build Coastguard Worker {
770*5e7646d2SAndroid Build Coastguard Worker   int	i, j, k;			/* Looping vars */
771*5e7646d2SAndroid Build Coastguard Worker   static const char * const colors[][2] =
772*5e7646d2SAndroid Build Coastguard Worker   {					/* Standard color names */
773*5e7646d2SAndroid Build Coastguard Worker     { "black",         "#000000" },
774*5e7646d2SAndroid Build Coastguard Worker     { "blue",          "#0000FF" },
775*5e7646d2SAndroid Build Coastguard Worker     { "brown",         "#A52A2A" },
776*5e7646d2SAndroid Build Coastguard Worker     { "cyan",          "#00FFFF" },
777*5e7646d2SAndroid Build Coastguard Worker     { "dark-gray",     "#404040" },
778*5e7646d2SAndroid Build Coastguard Worker     { "dark gray",     "#404040" },
779*5e7646d2SAndroid Build Coastguard Worker     { "dark-yellow",   "#FFCC00" },
780*5e7646d2SAndroid Build Coastguard Worker     { "dark yellow",   "#FFCC00" },
781*5e7646d2SAndroid Build Coastguard Worker     { "gold",          "#FFD700" },
782*5e7646d2SAndroid Build Coastguard Worker     { "gray",          "#808080" },
783*5e7646d2SAndroid Build Coastguard Worker     { "green",         "#00FF00" },
784*5e7646d2SAndroid Build Coastguard Worker     { "light-black",   "#606060" },
785*5e7646d2SAndroid Build Coastguard Worker     { "light black",   "#606060" },
786*5e7646d2SAndroid Build Coastguard Worker     { "light-cyan",    "#E0FFFF" },
787*5e7646d2SAndroid Build Coastguard Worker     { "light cyan",    "#E0FFFF" },
788*5e7646d2SAndroid Build Coastguard Worker     { "light-gray",    "#D3D3D3" },
789*5e7646d2SAndroid Build Coastguard Worker     { "light gray",    "#D3D3D3" },
790*5e7646d2SAndroid Build Coastguard Worker     { "light-magenta", "#FF77FF" },
791*5e7646d2SAndroid Build Coastguard Worker     { "light magenta", "#FF77FF" },
792*5e7646d2SAndroid Build Coastguard Worker     { "magenta",       "#FF00FF" },
793*5e7646d2SAndroid Build Coastguard Worker     { "orange",        "#FFA500" },
794*5e7646d2SAndroid Build Coastguard Worker     { "red",           "#FF0000" },
795*5e7646d2SAndroid Build Coastguard Worker     { "silver",        "#C0C0C0" },
796*5e7646d2SAndroid Build Coastguard Worker     { "white",         "#FFFFFF" },
797*5e7646d2SAndroid Build Coastguard Worker     { "yellow",        "#FFFF00" }
798*5e7646d2SAndroid Build Coastguard Worker   };
799*5e7646d2SAndroid Build Coastguard Worker 
800*5e7646d2SAndroid Build Coastguard Worker 
801*5e7646d2SAndroid Build Coastguard Worker   (void)data;
802*5e7646d2SAndroid Build Coastguard Worker 
803*5e7646d2SAndroid Build Coastguard Worker   if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerColorantValue) &&
804*5e7646d2SAndroid Build Coastguard Worker       packet->object_type == CUPS_ASN1_OCTET_STRING)
805*5e7646d2SAndroid Build Coastguard Worker   {
806*5e7646d2SAndroid Build Coastguard Worker    /*
807*5e7646d2SAndroid Build Coastguard Worker     * Get colorant...
808*5e7646d2SAndroid Build Coastguard Worker     */
809*5e7646d2SAndroid Build Coastguard Worker 
810*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerColorantValueOffset];
811*5e7646d2SAndroid Build Coastguard Worker 
812*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerColorantValue.1.%d = \"%s\"\n", i,
813*5e7646d2SAndroid Build Coastguard Worker             (char *)packet->object_value.string.bytes);
814*5e7646d2SAndroid Build Coastguard Worker 
815*5e7646d2SAndroid Build Coastguard Worker     for (j = 0; j < num_supplies; j ++)
816*5e7646d2SAndroid Build Coastguard Worker       if (supplies[j].colorant == i)
817*5e7646d2SAndroid Build Coastguard Worker       {
818*5e7646d2SAndroid Build Coastguard Worker 	for (k = 0; k < (int)(sizeof(colors) / sizeof(colors[0])); k ++)
819*5e7646d2SAndroid Build Coastguard Worker 	  if (!_cups_strcasecmp(colors[k][0],
820*5e7646d2SAndroid Build Coastguard Worker 	                        (char *)packet->object_value.string.bytes))
821*5e7646d2SAndroid Build Coastguard Worker 	  {
822*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(supplies[j].color, colors[k][1], sizeof(supplies[j].color));
823*5e7646d2SAndroid Build Coastguard Worker 	    break;
824*5e7646d2SAndroid Build Coastguard Worker 	  }
825*5e7646d2SAndroid Build Coastguard Worker       }
826*5e7646d2SAndroid Build Coastguard Worker   }
827*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesColorantIndex))
828*5e7646d2SAndroid Build Coastguard Worker   {
829*5e7646d2SAndroid Build Coastguard Worker    /*
830*5e7646d2SAndroid Build Coastguard Worker     * Get colorant index...
831*5e7646d2SAndroid Build Coastguard Worker     */
832*5e7646d2SAndroid Build Coastguard Worker 
833*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesColorantIndexOffset];
834*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
835*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_INTEGER)
836*5e7646d2SAndroid Build Coastguard Worker       return;
837*5e7646d2SAndroid Build Coastguard Worker 
838*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesColorantIndex.1.%d = %d\n", i,
839*5e7646d2SAndroid Build Coastguard Worker             packet->object_value.integer);
840*5e7646d2SAndroid Build Coastguard Worker 
841*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
842*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
843*5e7646d2SAndroid Build Coastguard Worker 
844*5e7646d2SAndroid Build Coastguard Worker     supplies[i - 1].colorant = packet->object_value.integer;
845*5e7646d2SAndroid Build Coastguard Worker   }
846*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesDescription))
847*5e7646d2SAndroid Build Coastguard Worker   {
848*5e7646d2SAndroid Build Coastguard Worker    /*
849*5e7646d2SAndroid Build Coastguard Worker     * Get supply name/description...
850*5e7646d2SAndroid Build Coastguard Worker     */
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesDescriptionOffset];
853*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
854*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_OCTET_STRING)
855*5e7646d2SAndroid Build Coastguard Worker       return;
856*5e7646d2SAndroid Build Coastguard Worker 
857*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
858*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
859*5e7646d2SAndroid Build Coastguard Worker 
860*5e7646d2SAndroid Build Coastguard Worker     switch (charset)
861*5e7646d2SAndroid Build Coastguard Worker     {
862*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csASCII :
863*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUTF8 :
864*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUnicodeASCII :
865*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(supplies[i - 1].name,
866*5e7646d2SAndroid Build Coastguard Worker 	          (char *)packet->object_value.string.bytes,
867*5e7646d2SAndroid Build Coastguard Worker 		  sizeof(supplies[0].name));
868*5e7646d2SAndroid Build Coastguard Worker           break;
869*5e7646d2SAndroid Build Coastguard Worker 
870*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csISOLatin1 :
871*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUnicodeLatin1 :
872*5e7646d2SAndroid Build Coastguard Worker 	  cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
873*5e7646d2SAndroid Build Coastguard Worker 	                    (char *)packet->object_value.string.bytes,
874*5e7646d2SAndroid Build Coastguard Worker 		            sizeof(supplies[0].name), CUPS_ISO8859_1);
875*5e7646d2SAndroid Build Coastguard Worker           break;
876*5e7646d2SAndroid Build Coastguard Worker 
877*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csShiftJIS :
878*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csWindows31J : /* Close enough for our purposes */
879*5e7646d2SAndroid Build Coastguard Worker 	  cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
880*5e7646d2SAndroid Build Coastguard Worker 	                    (char *)packet->object_value.string.bytes,
881*5e7646d2SAndroid Build Coastguard Worker 		            sizeof(supplies[0].name), CUPS_JIS_X0213);
882*5e7646d2SAndroid Build Coastguard Worker           break;
883*5e7646d2SAndroid Build Coastguard Worker 
884*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUCS4 :
885*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUTF32 :
886*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUTF32BE :
887*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUTF32LE :
888*5e7646d2SAndroid Build Coastguard Worker 	  cupsUTF32ToUTF8((cups_utf8_t *)supplies[i - 1].name,
889*5e7646d2SAndroid Build Coastguard Worker 	                  (cups_utf32_t *)packet->object_value.string.bytes,
890*5e7646d2SAndroid Build Coastguard Worker 			  sizeof(supplies[0].name));
891*5e7646d2SAndroid Build Coastguard Worker           break;
892*5e7646d2SAndroid Build Coastguard Worker 
893*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUnicode :
894*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUTF16BE :
895*5e7646d2SAndroid Build Coastguard Worker       case CUPS_TC_csUTF16LE :
896*5e7646d2SAndroid Build Coastguard Worker 	  utf16_to_utf8((cups_utf8_t *)supplies[i - 1].name,
897*5e7646d2SAndroid Build Coastguard Worker 	                packet->object_value.string.bytes,
898*5e7646d2SAndroid Build Coastguard Worker 			packet->object_value.string.num_bytes,
899*5e7646d2SAndroid Build Coastguard Worker 			sizeof(supplies[0].name), charset == CUPS_TC_csUTF16LE);
900*5e7646d2SAndroid Build Coastguard Worker           break;
901*5e7646d2SAndroid Build Coastguard Worker 
902*5e7646d2SAndroid Build Coastguard Worker       default :
903*5e7646d2SAndroid Build Coastguard Worker 	 /*
904*5e7646d2SAndroid Build Coastguard Worker 	  * If we get here, the printer is using an unknown character set and
905*5e7646d2SAndroid Build Coastguard Worker 	  * we just want to copy characters that look like ASCII...
906*5e7646d2SAndroid Build Coastguard Worker 	  */
907*5e7646d2SAndroid Build Coastguard Worker 
908*5e7646d2SAndroid Build Coastguard Worker           {
909*5e7646d2SAndroid Build Coastguard Worker 	    char	*src, *dst;	/* Pointers into strings */
910*5e7646d2SAndroid Build Coastguard Worker 
911*5e7646d2SAndroid Build Coastguard Worker            /*
912*5e7646d2SAndroid Build Coastguard Worker 	    * Loop safe because both the object_value and supplies char arrays
913*5e7646d2SAndroid Build Coastguard Worker 	    * are CUPS_SNMP_MAX_STRING elements long.
914*5e7646d2SAndroid Build Coastguard Worker 	    */
915*5e7646d2SAndroid Build Coastguard Worker 
916*5e7646d2SAndroid Build Coastguard Worker             for (src = (char *)packet->object_value.string.bytes,
917*5e7646d2SAndroid Build Coastguard Worker 	             dst = supplies[i - 1].name;
918*5e7646d2SAndroid Build Coastguard Worker 		 *src;
919*5e7646d2SAndroid Build Coastguard Worker 		 src ++)
920*5e7646d2SAndroid Build Coastguard Worker 	    {
921*5e7646d2SAndroid Build Coastguard Worker 	      if ((*src & 0x80) || *src < ' ' || *src == 0x7f)
922*5e7646d2SAndroid Build Coastguard Worker 	        *dst++ = '?';
923*5e7646d2SAndroid Build Coastguard Worker 	      else
924*5e7646d2SAndroid Build Coastguard Worker 	        *dst++ = *src;
925*5e7646d2SAndroid Build Coastguard Worker 	    }
926*5e7646d2SAndroid Build Coastguard Worker 
927*5e7646d2SAndroid Build Coastguard Worker 	    *dst = '\0';
928*5e7646d2SAndroid Build Coastguard Worker 	  }
929*5e7646d2SAndroid Build Coastguard Worker 	  break;
930*5e7646d2SAndroid Build Coastguard Worker     }
931*5e7646d2SAndroid Build Coastguard Worker 
932*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesDescription.1.%d = \"%s\"\n", i,
933*5e7646d2SAndroid Build Coastguard Worker             supplies[i - 1].name);
934*5e7646d2SAndroid Build Coastguard Worker 
935*5e7646d2SAndroid Build Coastguard Worker   }
936*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesLevel))
937*5e7646d2SAndroid Build Coastguard Worker   {
938*5e7646d2SAndroid Build Coastguard Worker    /*
939*5e7646d2SAndroid Build Coastguard Worker     * Get level...
940*5e7646d2SAndroid Build Coastguard Worker     */
941*5e7646d2SAndroid Build Coastguard Worker 
942*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesLevelOffset];
943*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
944*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_INTEGER)
945*5e7646d2SAndroid Build Coastguard Worker       return;
946*5e7646d2SAndroid Build Coastguard Worker 
947*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesLevel.1.%d = %d\n", i,
948*5e7646d2SAndroid Build Coastguard Worker             packet->object_value.integer);
949*5e7646d2SAndroid Build Coastguard Worker 
950*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
951*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
952*5e7646d2SAndroid Build Coastguard Worker 
953*5e7646d2SAndroid Build Coastguard Worker     supplies[i - 1].level = packet->object_value.integer;
954*5e7646d2SAndroid Build Coastguard Worker   }
955*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesMaxCapacity) &&
956*5e7646d2SAndroid Build Coastguard Worker            !(quirks & CUPS_SNMP_CAPACITY))
957*5e7646d2SAndroid Build Coastguard Worker   {
958*5e7646d2SAndroid Build Coastguard Worker    /*
959*5e7646d2SAndroid Build Coastguard Worker     * Get max capacity...
960*5e7646d2SAndroid Build Coastguard Worker     */
961*5e7646d2SAndroid Build Coastguard Worker 
962*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesMaxCapacityOffset];
963*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
964*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_INTEGER)
965*5e7646d2SAndroid Build Coastguard Worker       return;
966*5e7646d2SAndroid Build Coastguard Worker 
967*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesMaxCapacity.1.%d = %d\n", i,
968*5e7646d2SAndroid Build Coastguard Worker             packet->object_value.integer);
969*5e7646d2SAndroid Build Coastguard Worker 
970*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
971*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
972*5e7646d2SAndroid Build Coastguard Worker 
973*5e7646d2SAndroid Build Coastguard Worker     if (supplies[i - 1].max_capacity == 0 &&
974*5e7646d2SAndroid Build Coastguard Worker         packet->object_value.integer > 0)
975*5e7646d2SAndroid Build Coastguard Worker       supplies[i - 1].max_capacity = packet->object_value.integer;
976*5e7646d2SAndroid Build Coastguard Worker   }
977*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesClass))
978*5e7646d2SAndroid Build Coastguard Worker   {
979*5e7646d2SAndroid Build Coastguard Worker    /*
980*5e7646d2SAndroid Build Coastguard Worker     * Get marker class...
981*5e7646d2SAndroid Build Coastguard Worker     */
982*5e7646d2SAndroid Build Coastguard Worker 
983*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesClassOffset];
984*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
985*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_INTEGER)
986*5e7646d2SAndroid Build Coastguard Worker       return;
987*5e7646d2SAndroid Build Coastguard Worker 
988*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesClass.1.%d = %d\n", i,
989*5e7646d2SAndroid Build Coastguard Worker             packet->object_value.integer);
990*5e7646d2SAndroid Build Coastguard Worker 
991*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
992*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
993*5e7646d2SAndroid Build Coastguard Worker 
994*5e7646d2SAndroid Build Coastguard Worker     supplies[i - 1].sclass = packet->object_value.integer;
995*5e7646d2SAndroid Build Coastguard Worker   }
996*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesType))
997*5e7646d2SAndroid Build Coastguard Worker   {
998*5e7646d2SAndroid Build Coastguard Worker    /*
999*5e7646d2SAndroid Build Coastguard Worker     * Get marker type...
1000*5e7646d2SAndroid Build Coastguard Worker     */
1001*5e7646d2SAndroid Build Coastguard Worker 
1002*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesTypeOffset];
1003*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
1004*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_INTEGER)
1005*5e7646d2SAndroid Build Coastguard Worker       return;
1006*5e7646d2SAndroid Build Coastguard Worker 
1007*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesType.1.%d = %d\n", i,
1008*5e7646d2SAndroid Build Coastguard Worker             packet->object_value.integer);
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
1011*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
1012*5e7646d2SAndroid Build Coastguard Worker 
1013*5e7646d2SAndroid Build Coastguard Worker     supplies[i - 1].type = packet->object_value.integer;
1014*5e7646d2SAndroid Build Coastguard Worker   }
1015*5e7646d2SAndroid Build Coastguard Worker   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesSupplyUnit))
1016*5e7646d2SAndroid Build Coastguard Worker   {
1017*5e7646d2SAndroid Build Coastguard Worker    /*
1018*5e7646d2SAndroid Build Coastguard Worker     * Get units for capacity...
1019*5e7646d2SAndroid Build Coastguard Worker     */
1020*5e7646d2SAndroid Build Coastguard Worker 
1021*5e7646d2SAndroid Build Coastguard Worker     i = packet->object_name[prtMarkerSuppliesSupplyUnitOffset];
1022*5e7646d2SAndroid Build Coastguard Worker     if (i < 1 || i > CUPS_MAX_SUPPLIES ||
1023*5e7646d2SAndroid Build Coastguard Worker         packet->object_type != CUPS_ASN1_INTEGER)
1024*5e7646d2SAndroid Build Coastguard Worker       return;
1025*5e7646d2SAndroid Build Coastguard Worker 
1026*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG2: prtMarkerSuppliesSupplyUnit.1.%d = %d\n", i,
1027*5e7646d2SAndroid Build Coastguard Worker             packet->object_value.integer);
1028*5e7646d2SAndroid Build Coastguard Worker 
1029*5e7646d2SAndroid Build Coastguard Worker     if (i > num_supplies)
1030*5e7646d2SAndroid Build Coastguard Worker       num_supplies = i;
1031*5e7646d2SAndroid Build Coastguard Worker 
1032*5e7646d2SAndroid Build Coastguard Worker     if (packet->object_value.integer == CUPS_TC_percent)
1033*5e7646d2SAndroid Build Coastguard Worker       supplies[i - 1].max_capacity = 100;
1034*5e7646d2SAndroid Build Coastguard Worker   }
1035*5e7646d2SAndroid Build Coastguard Worker }
1036*5e7646d2SAndroid Build Coastguard Worker 
1037*5e7646d2SAndroid Build Coastguard Worker 
1038*5e7646d2SAndroid Build Coastguard Worker /*
1039*5e7646d2SAndroid Build Coastguard Worker  * 'utf16_to_utf8()' - Convert UTF-16 text to UTF-8.
1040*5e7646d2SAndroid Build Coastguard Worker  */
1041*5e7646d2SAndroid Build Coastguard Worker 
1042*5e7646d2SAndroid Build Coastguard Worker static void
utf16_to_utf8(cups_utf8_t * dst,const unsigned char * src,size_t srcsize,size_t dstsize,int le)1043*5e7646d2SAndroid Build Coastguard Worker utf16_to_utf8(
1044*5e7646d2SAndroid Build Coastguard Worker     cups_utf8_t         *dst,		/* I - Destination buffer */
1045*5e7646d2SAndroid Build Coastguard Worker     const unsigned char *src,		/* I - Source string */
1046*5e7646d2SAndroid Build Coastguard Worker     size_t		srcsize,	/* I - Size of source string */
1047*5e7646d2SAndroid Build Coastguard Worker     size_t              dstsize,	/* I - Size of destination buffer */
1048*5e7646d2SAndroid Build Coastguard Worker     int                 le)		/* I - Source is little-endian? */
1049*5e7646d2SAndroid Build Coastguard Worker {
1050*5e7646d2SAndroid Build Coastguard Worker   cups_utf32_t	ch,			/* Current character */
1051*5e7646d2SAndroid Build Coastguard Worker 		temp[CUPS_SNMP_MAX_STRING],
1052*5e7646d2SAndroid Build Coastguard Worker 					/* UTF-32 string */
1053*5e7646d2SAndroid Build Coastguard Worker 		*ptr;			/* Pointer into UTF-32 string */
1054*5e7646d2SAndroid Build Coastguard Worker 
1055*5e7646d2SAndroid Build Coastguard Worker 
1056*5e7646d2SAndroid Build Coastguard Worker   for (ptr = temp; srcsize >= 2;)
1057*5e7646d2SAndroid Build Coastguard Worker   {
1058*5e7646d2SAndroid Build Coastguard Worker     if (le)
1059*5e7646d2SAndroid Build Coastguard Worker       ch = (cups_utf32_t)(src[0] | (src[1] << 8));
1060*5e7646d2SAndroid Build Coastguard Worker     else
1061*5e7646d2SAndroid Build Coastguard Worker       ch = (cups_utf32_t)((src[0] << 8) | src[1]);
1062*5e7646d2SAndroid Build Coastguard Worker 
1063*5e7646d2SAndroid Build Coastguard Worker     src += 2;
1064*5e7646d2SAndroid Build Coastguard Worker     srcsize -= 2;
1065*5e7646d2SAndroid Build Coastguard Worker 
1066*5e7646d2SAndroid Build Coastguard Worker     if (ch >= 0xd800 && ch <= 0xdbff && srcsize >= 2)
1067*5e7646d2SAndroid Build Coastguard Worker     {
1068*5e7646d2SAndroid Build Coastguard Worker      /*
1069*5e7646d2SAndroid Build Coastguard Worker       * Multi-word UTF-16 char...
1070*5e7646d2SAndroid Build Coastguard Worker       */
1071*5e7646d2SAndroid Build Coastguard Worker 
1072*5e7646d2SAndroid Build Coastguard Worker       cups_utf32_t lch;			/* Lower word */
1073*5e7646d2SAndroid Build Coastguard Worker 
1074*5e7646d2SAndroid Build Coastguard Worker 
1075*5e7646d2SAndroid Build Coastguard Worker       if (le)
1076*5e7646d2SAndroid Build Coastguard Worker 	lch = (cups_utf32_t)(src[0] | (src[1] << 8));
1077*5e7646d2SAndroid Build Coastguard Worker       else
1078*5e7646d2SAndroid Build Coastguard Worker 	lch = (cups_utf32_t)((src[0] << 8) | src[1]);
1079*5e7646d2SAndroid Build Coastguard Worker 
1080*5e7646d2SAndroid Build Coastguard Worker       if (lch >= 0xdc00 && lch <= 0xdfff)
1081*5e7646d2SAndroid Build Coastguard Worker       {
1082*5e7646d2SAndroid Build Coastguard Worker 	src += 2;
1083*5e7646d2SAndroid Build Coastguard Worker 	srcsize -= 2;
1084*5e7646d2SAndroid Build Coastguard Worker 
1085*5e7646d2SAndroid Build Coastguard Worker 	ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
1086*5e7646d2SAndroid Build Coastguard Worker       }
1087*5e7646d2SAndroid Build Coastguard Worker     }
1088*5e7646d2SAndroid Build Coastguard Worker 
1089*5e7646d2SAndroid Build Coastguard Worker     if (ptr < (temp + CUPS_SNMP_MAX_STRING - 1))
1090*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = ch;
1091*5e7646d2SAndroid Build Coastguard Worker   }
1092*5e7646d2SAndroid Build Coastguard Worker 
1093*5e7646d2SAndroid Build Coastguard Worker   *ptr = '\0';
1094*5e7646d2SAndroid Build Coastguard Worker 
1095*5e7646d2SAndroid Build Coastguard Worker   cupsUTF32ToUTF8(dst, temp, (int)dstsize);
1096*5e7646d2SAndroid Build Coastguard Worker }
1097