]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/snmp-supplies.c
Remove old files.
[thirdparty/cups.git] / backend / snmp-supplies.c
CommitLineData
568fa3fa
MS
1/*
2 * "$Id$"
3 *
4 * SNMP supplies functions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2008 by Apple Inc.
7 *
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/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 *
16 * Contents:
17 *
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 */
22
23/*
24 * Include necessary headers.
25 */
26
27#include "backend-private.h"
28#include <cups/array.h>
29
30
31/*
32 * Local constants...
33 */
34
35#define CUPS_MAX_SUPPLIES 32 /* Maximum number of supplies for a printer */
36
37
38/*
39 * Local structures...
40 */
41
42typedef struct
43{
44 char name[CUPS_SNMP_MAX_STRING], /* Name of supply */
45 color[8]; /* Color: "#RRGGBB" or "none" */
46 int colorant, /* Colorant index */
47 type, /* Supply type */
48 max_capacity, /* Maximum capacity */
49 level; /* Current level value */
50} backend_supplies_t;
51
52
53/*
54 * Local globals...
55 */
56
57static http_addr_t current_addr; /* Current address */
58static int num_supplies = 0;
59 /* Number of supplies found */
60static backend_supplies_t supplies[CUPS_MAX_SUPPLIES];
61 /* Supply information */
62
63static const int hrDeviceDescr[] =
64 { CUPS_OID_hrDeviceDescr, 1, -1 };
65 /* Device description OID */
66static const int hrPrinterStatus[] =
67 { CUPS_OID_hrPrinterStatus, 1, -1 };
68 /* Current state OID */
69static const int hrPrinterDetectedErrorState[] =
70 { CUPS_OID_hrPrinterDetectedErrorState, 1, -1 };
71 /* Current printer state bits OID */
72static const int prtMarkerColorantValue[] =
73 { CUPS_OID_prtMarkerColorantValue, -1 },
74 /* Colorant OID */
75 prtMarkerColorantValueOffset =
76 (sizeof(prtMarkerColorantValue) /
77 sizeof(prtMarkerColorantValue[0]));
78 /* Offset to colorant index */
79static const int prtMarkerLifeCount[] =
80 { CUPS_OID_prtMarkerLifeCount, 1, 1, -1 };
81 /* Page counter OID */
82static const int prtMarkerSuppliesEntry[] =
83 { CUPS_OID_prtMarkerSuppliesEntry, -1 };
84 /* Supplies OID */
85static const int prtMarkerSuppliesColorantIndex[] =
86 { CUPS_OID_prtMarkerSuppliesColorantIndex, -1 },
87 /* Colorant index OID */
88 prtMarkerSuppliesColorantIndexOffset =
89 (sizeof(prtMarkerSuppliesColorantIndex) /
90 sizeof(prtMarkerSuppliesColorantIndex[0]));
91 /* Offset to supply index */
92static const int prtMarkerSuppliesDescription[] =
93 { CUPS_OID_prtMarkerSuppliesDescription, -1 },
94 /* Description OID */
95 prtMarkerSuppliesDescriptionOffset =
96 (sizeof(prtMarkerSuppliesDescription) /
97 sizeof(prtMarkerSuppliesDescription[0]));
98 /* Offset to supply index */
99static const int prtMarkerSuppliesLevel[] =
100 { CUPS_OID_prtMarkerSuppliesLevel, -1 },
101 /* Level OID */
102 prtMarkerSuppliesLevelOffset =
103 (sizeof(prtMarkerSuppliesLevel) /
104 sizeof(prtMarkerSuppliesLevel[0]));
105 /* Offset to supply index */
106static const int prtMarkerSuppliesMaxCapacity[] =
107 { CUPS_OID_prtMarkerSuppliesMaxCapacity, -1 },
108 /* Max capacity OID */
109 prtMarkerSuppliesMaxCapacityOffset =
110 (sizeof(prtMarkerSuppliesMaxCapacity) /
111 sizeof(prtMarkerSuppliesMaxCapacity[0]));
112 /* Offset to supply index */
113static const int prtMarkerSuppliesType[] =
114 { CUPS_OID_prtMarkerSuppliesType, -1 },
115 /* Type OID */
116 prtMarkerSuppliesTypeOffset =
117 (sizeof(prtMarkerSuppliesType) /
118 sizeof(prtMarkerSuppliesType[0]));
119 /* Offset to supply index */
120
121
122/*
123 * Local functions...
124 */
125
126static void backend_init_supplies(int snmp_fd, http_addr_t *addr);
127static void backend_walk_cb(cups_snmp_t *packet, void *data);
128
129
130/*
131 * 'backendSNMPSupplies()' - Get the current supplies for a device.
132 */
133
134int /* O - 0 on success, -1 on error */
135backendSNMPSupplies(
136 int snmp_fd, /* I - SNMP socket */
137 http_addr_t *addr, /* I - Printer address */
138 int *page_count, /* O - Page count */
139 int *printer_state) /* O - Printer state */
140{
141 if (!httpAddrEqual(addr, &current_addr))
142 backend_init_supplies(snmp_fd, addr);
143 else if (num_supplies > 0)
144 cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
145 cupsSNMPDefaultCommunity(), prtMarkerSuppliesLevel, 500,
146 backend_walk_cb, NULL);
147
148 if (page_count)
149 *page_count = -1;
150
151 if (printer_state)
152 *printer_state = -1;
153
154 if (num_supplies > 0)
155 {
156 int i; /* Looping var */
157 char value[CUPS_MAX_SUPPLIES * 4],
158 /* marker-levels value string */
159 *ptr; /* Pointer into value string */
160 cups_snmp_t packet; /* SNMP response packet */
161
162
163 /*
164 * Generate the marker-levels value string...
165 */
166
167 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
168 {
169 if (i)
170 *ptr++ = ',';
171
172 sprintf(ptr, "%d", 100 * supplies[i].level / supplies[i].max_capacity);
173 }
174
175 fprintf(stderr, "ATTR: marker-levels=%s\n", value);
176
177 /*
178 * Get the current printer status bits...
179 */
180
181 if (!cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
182 cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
183 hrPrinterDetectedErrorState))
184 return (-1);
185
186 if (!cupsSNMPRead(snmp_fd, &packet, 500) ||
187 packet.object_type != CUPS_ASN1_OCTET_STRING)
188 return (-1);
189
190 i = ((packet.object_value.string[0] & 255) << 8) |
191 (packet.object_value.string[1] & 255);
192
193 if (i & CUPS_TC_lowPaper)
194 fputs("STATE: +media-low-warning\n", stderr);
195 else
196 fputs("STATE: -media-low-warning\n", stderr);
197
198 if (i & (CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty))
199 fputs("STATE: +media-empty-error\n", stderr);
200 else
201 fputs("STATE: -media-empty-error\n", stderr);
202
203 if (i & CUPS_TC_lowToner)
204 fputs("STATE: +toner-low-warning\n", stderr);
205 else
206 fputs("STATE: -toner-low-warning\n", stderr);
207
208 if (i & CUPS_TC_noToner)
209 fputs("STATE: +toner-empty-error\n", stderr);
210 else
211 fputs("STATE: -toner-empty-error\n", stderr);
212
213 if (i & CUPS_TC_doorOpen)
214 fputs("STATE: +door-open-report\n", stderr);
215 else
216 fputs("STATE: -door-open-report\n", stderr);
217
218 if (i & CUPS_TC_jammed)
219 fputs("STATE: +media-jam-error\n", stderr);
220 else
221 fputs("STATE: -media-jam-error\n", stderr);
222
223 if (i & CUPS_TC_offline)
224 fputs("STATE: +offline-report\n", stderr);
225 else
226 fputs("STATE: -offline-report\n", stderr);
227
228 if (i & (CUPS_TC_serviceRequested | CUPS_TC_overduePreventMaint))
229 fputs("STATE: +service-needed-error\n", stderr);
230 else
231 fputs("STATE: -service-needed-error\n", stderr);
232
233 if (i & CUPS_TC_inputTrayMissing)
234 fputs("STATE: +input-tray-missing-error\n", stderr);
235 else
236 fputs("STATE: -input-tray-missing-error\n", stderr);
237
238 if (i & CUPS_TC_outputTrayMissing)
239 fputs("STATE: +output-tray-missing-error\n", stderr);
240 else
241 fputs("STATE: -output-tray-missing-error\n", stderr);
242
243 if (i & CUPS_TC_markerSupplyMissing)
244 fputs("STATE: +marker-supply-missing-error\n", stderr);
245 else
246 fputs("STATE: -marker-supply-missing-error\n", stderr);
247
248 if (i & CUPS_TC_outputNearFull)
249 fputs("STATE: +output-area-almost-full-warning\n", stderr);
250 else
251 fputs("STATE: -output-area-almost-full-warning\n", stderr);
252
253 if (i & CUPS_TC_outputFull)
254 fputs("STATE: +output-area-full-error\n", stderr);
255 else
256 fputs("STATE: -output-area-full-error\n", stderr);
257
258 /*
259 * Get the current printer state...
260 */
261
262 if (printer_state)
263 {
264 if (!cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
265 cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
266 hrPrinterStatus))
267 return (-1);
268
269 if (!cupsSNMPRead(snmp_fd, &packet, 500) ||
270 packet.object_type != CUPS_ASN1_INTEGER)
271 return (-1);
272
273 *printer_state = packet.object_value.integer;
274 }
275
276 /*
277 * Get the current page count...
278 */
279
280 if (page_count)
281 {
282 if (!cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
283 cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
284 prtMarkerLifeCount))
285 return (-1);
286
287 if (!cupsSNMPRead(snmp_fd, &packet, 500) ||
288 packet.object_type != CUPS_ASN1_COUNTER)
289 return (-1);
290
291 *page_count = packet.object_value.counter;
292 }
293
294 return (0);
295 }
296 else
297 return (-1);
298}
299
300
301/*
302 * 'backend_init_supplies()' - Initialize the supplies list.
303 */
304
305static void
306backend_init_supplies(
307 int snmp_fd, /* I - SNMP socket */
308 http_addr_t *addr) /* I - Printer address */
309{
310 int i, /* Looping var */
311 type; /* Current marker type */
312 cups_file_t *cachefile; /* Cache file */
313 const char *cachedir; /* CUPS_CACHEDIR value */
314 char addrstr[1024], /* Address string */
315 cachefilename[1024], /* Cache filename */
316 description[CUPS_SNMP_MAX_STRING],
317 /* Device description string */
318 value[CUPS_MAX_SUPPLIES * (CUPS_SNMP_MAX_STRING * 2 + 3)],
319 /* Value string */
320 *ptr, /* Pointer into value string */
321 *name_ptr; /* Pointer into name string */
322 cups_snmp_t packet; /* SNMP response packet */
323 static const char * const types[] = /* Supply types */
324 {
325 "other",
326 "unknown",
327 "toner",
328 "wasteToner",
329 "ink",
330 "inkCartridge",
331 "inkRibbon",
332 "wasteInk",
333 "opc",
334 "developer",
335 "fuserOil",
336 "solidWax",
337 "ribbonWax",
338 "wasteWax",
339 "fuser",
340 "coronaWire",
341 "fuserOilWick",
342 "cleanerUnit",
343 "fuserCleaningPad",
344 "transferUnit",
345 "tonerCartridge",
346 "fuserOiler",
347 "water",
348 "wasteWater",
349 "glueWaterAdditive",
350 "wastePaper",
351 "bindingSupply",
352 "bandingSupply",
353 "stitchingWire",
354 "shrinkWrap",
355 "paperWrap",
356 "staples",
357 "inserts",
358 "covers"
359 };
360
361
362 /*
363 * Reset state information...
364 */
365
366 current_addr = *addr;
367 num_supplies = -1;
368
369 memset(supplies, 0, sizeof(supplies));
370
371 /*
372 * Get the device description...
373 */
374
375 if (!cupsSNMPWrite(snmp_fd, addr, CUPS_SNMP_VERSION_1,
376 cupsSNMPDefaultCommunity(), CUPS_ASN1_GET_REQUEST, 1,
377 hrDeviceDescr))
378 return;
379
380 if (!cupsSNMPRead(snmp_fd, &packet, 500) ||
381 packet.object_type != CUPS_ASN1_OCTET_STRING)
382 {
383 strlcpy(description, "Unknown", sizeof(description));
384 num_supplies = 0;
385 }
386 else
387 strlcpy(description, packet.object_value.string, sizeof(description));
388
389 /*
390 * See if we have already queried this device...
391 */
392
393 httpAddrString(addr, addrstr, sizeof(addrstr));
394
395 if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
396 cachedir = CUPS_CACHEDIR;
397
398 snprintf(cachefilename, sizeof(cachefilename), "%s/%s.snmp", cachedir,
399 addrstr);
400
401 if ((cachefile = cupsFileOpen(cachefilename, "r")) != NULL)
402 {
403 /*
404 * Yes, read the cache file:
405 *
406 * 1 num_supplies
407 * device description
408 * supply structures...
409 */
410
411 if (cupsFileGets(cachefile, value, sizeof(value)))
412 {
413 if (sscanf(value, "1 %d", &num_supplies) == 1 &&
414 num_supplies <= CUPS_MAX_SUPPLIES &&
415 cupsFileGets(cachefile, value, sizeof(value)))
416 {
417 if ((ptr = value + strlen(value) - 1) >= value && *ptr == '\n')
418 *ptr = '\n';
419
420 if (!strcmp(description, value))
421 cupsFileRead(cachefile, (char *)supplies,
422 num_supplies * sizeof(backend_supplies_t));
423 else
424 num_supplies = -1;
425 }
426 else
427 num_supplies = -1;
428 }
429
430 cupsFileClose(cachefile);
431 }
432
433 /*
434 * If the cache information isn't correct, scan for supplies...
435 */
436
437 if (num_supplies < 0)
438 {
439 /*
440 * Walk the printer configuration information...
441 */
442
443 cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
444 cupsSNMPDefaultCommunity(), prtMarkerSuppliesEntry, 500,
445 backend_walk_cb, NULL);
446 }
447
448 /*
449 * Save the cached information...
450 */
451
452 if (num_supplies < 0)
453 num_supplies = 0;
454
455 if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
456 {
457 cupsFilePrintf(cachefile, "1 %d\n", num_supplies);
458 cupsFilePrintf(cachefile, "%s\n", description);
459
460 if (num_supplies > 0)
461 cupsFileWrite(cachefile, (char *)supplies,
462 num_supplies * sizeof(backend_supplies_t));
463
464 cupsFileClose(cachefile);
465 }
466
467 if (num_supplies <= 0)
468 return;
469
470 /*
471 * Get the colors...
472 */
473
474 for (i = 0; i < num_supplies; i ++)
475 strcpy(supplies[i].color, "none");
476
477 cupsSNMPWalk(snmp_fd, &current_addr, CUPS_SNMP_VERSION_1,
478 cupsSNMPDefaultCommunity(), prtMarkerColorantValue, 500,
479 backend_walk_cb, NULL);
480
481 /*
482 * Output the marker-colors attribute...
483 */
484
485 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
486 {
487 if (i)
488 *ptr++ = ',';
489
490 strcpy(ptr, supplies[i].color);
491 }
492
493 fprintf(stderr, "ATTR: marker-colors=%s\n", value);
494
495 /*
496 * Output the marker-names attribute...
497 */
498
499 for (i = 0, ptr = value; i < num_supplies; i ++)
500 {
501 if (i)
502 *ptr++ = ',';
503
504 *ptr++ = '\"';
505 for (name_ptr = supplies[i].name; *name_ptr;)
506 {
507 if (*name_ptr == '\\' || *name_ptr == '\"')
508 *ptr++ = '\\';
509
510 *ptr++ = *name_ptr++;
511 }
512 *ptr++ = '\"';
513 }
514
515 *ptr = '\0';
516
517 fprintf(stderr, "ATTR: marker-names=%s\n", value);
518
519 /*
520 * Output the marker-types attribute...
521 */
522
523 for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr))
524 {
525 if (i)
526 *ptr++ = ',';
527
528 type = supplies[i].type;
529
530 if (type < CUPS_TC_other || type > CUPS_TC_covers)
531 strcpy(ptr, "unknown");
532 else
533 strcpy(ptr, types[type - CUPS_TC_other]);
534 }
535
536 fprintf(stderr, "ATTR: marker-types=%s\n", value);
537}
538
539
540/*
541 * 'backend_walk_cb()' - Interpret the supply value responses...
542 */
543
544static void
545backend_walk_cb(cups_snmp_t *packet, /* I - SNMP packet */
546 void *data) /* I - User data (unused) */
547{
548 int i, j, k; /* Looping vars */
549 static const char * const colors[8][2] =
550 { /* Standard color names */
551 { "black", "#000000" },
552 { "blue", "#0000FF" },
553 { "cyan", "#00FFFF" },
554 { "green", "#00FF00" },
555 { "magenta", "#FF00FF" },
556 { "red", "#FF0000" },
557 { "white", "#FFFFFF" },
558 { "yellow", "#FFFF00" }
559 };
560
561
562 (void)data;
563
564 if (cupsSNMPIsOIDPrefixed(packet, prtMarkerColorantValue) &&
565 packet->object_type == CUPS_ASN1_OCTET_STRING)
566 {
567 /*
568 * Get colorant...
569 */
570
571 i = packet->object_name[prtMarkerColorantValueOffset];
572
573 fprintf(stderr, "DEBUG2: prtMarkerColorantValue.1.%d = \"%s\"\n", i,
574 packet->object_value.string);
575
576 for (j = 0; j < num_supplies; j ++)
577 if (supplies[j].colorant == i)
578 {
579 for (k = 0; k < (int)(sizeof(colors) / sizeof(colors[0])); k ++)
580 if (!strcmp(colors[k][0], packet->object_value.string))
581 {
582 strcpy(supplies[j].color, colors[k][1]);
583 break;
584 }
585 }
586 }
587 else if (cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesColorantIndex))
588 {
589 /*
590 * Get colorant index...
591 */
592
593 i = packet->object_name[prtMarkerSuppliesColorantIndexOffset];
594 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
595 packet->object_type != CUPS_ASN1_INTEGER)
596 return;
597
598 fprintf(stderr, "DEBUG2: prtMarkerSuppliesColorantIndex.1.%d = %d\n", i,
599 packet->object_value.integer);
600
601 if (i > num_supplies)
602 num_supplies = i;
603
604 supplies[i - 1].colorant = packet->object_value.integer;
605 }
606 else if (cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesDescription))
607 {
608 /*
609 * Get supply name/description...
610 */
611
612 i = packet->object_name[prtMarkerSuppliesDescriptionOffset];
613 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
614 packet->object_type != CUPS_ASN1_OCTET_STRING)
615 return;
616
617 fprintf(stderr, "DEBUG2: prtMarkerSuppliesDescription.1.%d = \"%s\"\n", i,
618 packet->object_value.string);
619
620 if (i > num_supplies)
621 num_supplies = i;
622
623 strlcpy(supplies[i - 1].name, packet->object_value.string,
624 sizeof(supplies[0].name));
625 }
626 else if (cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesLevel))
627 {
628 /*
629 * Get level...
630 */
631
632 i = packet->object_name[prtMarkerSuppliesLevelOffset];
633 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
634 packet->object_type != CUPS_ASN1_INTEGER)
635 return;
636
637 fprintf(stderr, "DEBUG2: prtMarkerSuppliesLevel.1.%d = %d\n", i,
638 packet->object_value.integer);
639
640 if (i > num_supplies)
641 num_supplies = i;
642
643 supplies[i - 1].level = packet->object_value.integer;
644 }
645 else if (cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesMaxCapacity))
646 {
647 /*
648 * Get max capacity...
649 */
650
651 i = packet->object_name[prtMarkerSuppliesMaxCapacityOffset];
652 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
653 packet->object_type != CUPS_ASN1_INTEGER)
654 return;
655
656 fprintf(stderr, "DEBUG2: prtMarkerSuppliesMaxCapacity.1.%d = %d\n", i,
657 packet->object_value.integer);
658
659 if (i > num_supplies)
660 num_supplies = i;
661
662 supplies[i - 1].max_capacity = packet->object_value.integer;
663 }
664 else if (cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesType))
665 {
666 /*
667 * Get marker type...
668 */
669
670 i = packet->object_name[prtMarkerSuppliesTypeOffset];
671 if (i < 1 || i > CUPS_MAX_SUPPLIES ||
672 packet->object_type != CUPS_ASN1_INTEGER)
673 return;
674
675 fprintf(stderr, "DEBUG2: prtMarkerSuppliesType.1.%d = %d\n", i,
676 packet->object_value.integer);
677
678 if (i > num_supplies)
679 num_supplies = i;
680
681 supplies[i - 1].type = packet->object_value.integer;
682 }
683}
684
685
686/*
687 * End of "$Id$".
688 */