/*
* "$Id$"
*
- * SNMP supplies functions for CUPS.
+ * SNMP supplies functions for CUPS.
*
- * Copyright 2008-2012 by Apple Inc.
+ * Copyright 2008-2014 by Apple Inc.
*
- * These coded instructions, statements, and computer programs are the
- * property of Apple Inc. and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "LICENSE.txt"
- * "LICENSE" which should have been included with this file. If this
- * file is missing or damaged, see the license at "http://www.cups.org/".
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * "LICENSE" which should have been included with this file. If this
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
- * This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- * backendSNMPSupplies() - Get the current supplies for a device.
- * backend_init_supplies() - Initialize the supplies list.
- * backend_walk_cb() - Interpret the supply value responses.
- * utf16_to_utf8() - Convert UTF-16 text to UTF-8.
+ * This file is subject to the Apple OS-Developed Software exception.
*/
/*
#define CUPS_MAX_SUPPLIES 32 /* Maximum number of supplies for a printer */
#define CUPS_SUPPLY_TIMEOUT 2.0 /* Timeout for SNMP lookups */
-#define CUPS_DEVELOPER_LOW 1
-#define CUPS_DEVELOPER_EMPTY 2
-#define CUPS_MARKER_SUPPLY_LOW 4
-#define CUPS_MARKER_SUPPLY_EMPTY 8
-#define CUPS_OPC_NEAR_EOL 16
-#define CUPS_OPC_LIFE_OVER 32
-#define CUPS_TONER_LOW 64
-#define CUPS_TONER_EMPTY 128
+#define CUPS_DEVELOPER_LOW 0x0001
+#define CUPS_DEVELOPER_EMPTY 0x0002
+#define CUPS_MARKER_SUPPLY_LOW 0x0004
+#define CUPS_MARKER_SUPPLY_EMPTY 0x0008
+#define CUPS_OPC_NEAR_EOL 0x0010
+#define CUPS_OPC_LIFE_OVER 0x0020
+#define CUPS_TONER_LOW 0x0040
+#define CUPS_TONER_EMPTY 0x0080
+#define CUPS_WASTE_ALMOST_FULL 0x0100
+#define CUPS_WASTE_FULL 0x0200
+#define CUPS_CLEANER_NEAR_EOL 0x0400 /* Proposed JPS3 */
+#define CUPS_CLEANER_LIFE_OVER 0x0800 /* Proposed JPS3 */
+
+#define CUPS_SNMP_NONE 0x0000
+#define CUPS_SNMP_CAPACITY 0x0001 /* Supply levels reported as percentages */
/*
char name[CUPS_SNMP_MAX_STRING], /* Name of supply */
color[8]; /* Color: "#RRGGBB" or "none" */
int colorant, /* Colorant index */
+ sclass, /* Supply class */
type, /* Supply type */
max_capacity, /* Maximum capacity */
level; /* Current level value */
static int current_state = -1;
/* Current device state bits */
static int charset = -1; /* Character set for supply names */
+static unsigned quirks = CUPS_SNMP_NONE;
+ /* Quirks we have to work around */
static int num_supplies = 0;
/* Number of supplies found */
static backend_supplies_t supplies[CUPS_MAX_SUPPLIES];
(sizeof(prtMarkerSuppliesMaxCapacity) /
sizeof(prtMarkerSuppliesMaxCapacity[0]));
/* Offset to supply index */
+static const int prtMarkerSuppliesClass[] =
+ { CUPS_OID_prtMarkerSuppliesClass, -1 },
+ /* Class OID */
+ prtMarkerSuppliesClassOffset =
+ (sizeof(prtMarkerSuppliesClass) /
+ sizeof(prtMarkerSuppliesClass[0]));
+ /* Offset to supply index */
static const int prtMarkerSuppliesType[] =
{ CUPS_OID_prtMarkerSuppliesType, -1 },
/* Type OID */
(sizeof(prtMarkerSuppliesType) /
sizeof(prtMarkerSuppliesType[0]));
/* Offset to supply index */
-
-static const backend_state_t const printer_states[] =
+static const int prtMarkerSuppliesSupplyUnit[] =
+ { CUPS_OID_prtMarkerSuppliesSupplyUnit, -1 },
+ /* Units OID */
+ prtMarkerSuppliesSupplyUnitOffset =
+ (sizeof(prtMarkerSuppliesSupplyUnit) /
+ sizeof(prtMarkerSuppliesSupplyUnit[0]));
+ /* Offset to supply index */
+
+static const backend_state_t printer_states[] =
{
/* { CUPS_TC_lowPaper, "media-low-report" }, */
{ CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty, "media-empty-warning" },
{ CUPS_TC_outputFull, "output-area-full-warning" }
};
-static const backend_state_t const supply_states[] =
+static const backend_state_t supply_states[] =
{
{ CUPS_DEVELOPER_LOW, "developer-low-report" },
{ CUPS_DEVELOPER_EMPTY, "developer-empty-warning" },
{ CUPS_OPC_NEAR_EOL, "opc-near-eol-report" },
{ CUPS_OPC_LIFE_OVER, "opc-life-over-warning" },
{ CUPS_TONER_LOW, "toner-low-report" },
- { CUPS_TONER_EMPTY, "toner-empty-warning" }
+ { CUPS_TONER_EMPTY, "toner-empty-warning" },
+ { CUPS_WASTE_ALMOST_FULL, "waste-receptacle-almost-full-report" },
+ { CUPS_WASTE_FULL, "waste-receptacle-full-warning" },
+ { CUPS_CLEANER_NEAR_EOL, "cleaner-life-almost-over-report" },
+ { CUPS_CLEANER_LIFE_OVER, "cleaner-life-over-warning" },
};
{
if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
percent = 100 * supplies[i].level / supplies[i].max_capacity;
+ else if (supplies[i].level >= 0 && supplies[i].level <= 100 &&
+ (quirks & CUPS_SNMP_CAPACITY))
+ percent = supplies[i].level;
else
percent = 50;
+ if (supplies[i].sclass == CUPS_TC_receptacleThatIsFilled)
+ percent = 100 - percent;
+
if (percent <= 5)
{
switch (supplies[i].type)
else
new_supply_state |= CUPS_TONER_LOW;
break;
- case CUPS_TC_wasteToner :
- case CUPS_TC_wasteInk :
- break;
case CUPS_TC_ink :
case CUPS_TC_inkCartridge :
case CUPS_TC_inkRibbon :
else
new_supply_state |= CUPS_OPC_NEAR_EOL;
break;
+ case CUPS_TC_wasteInk :
+ case CUPS_TC_wastePaper :
+ case CUPS_TC_wasteToner :
+ case CUPS_TC_wasteWater :
+ case CUPS_TC_wasteWax :
+ if (percent <= 1)
+ new_supply_state |= CUPS_WASTE_FULL;
+ else
+ new_supply_state |= CUPS_WASTE_ALMOST_FULL;
+ break;
+ case CUPS_TC_cleanerUnit :
+ case CUPS_TC_fuserCleaningPad :
+ if (percent <= 1)
+ new_supply_state |= CUPS_CLEANER_LIFE_OVER;
+ else
+ new_supply_state |= CUPS_CLEANER_NEAR_EOL;
+ break;
}
}
if (i)
*ptr++ = ',';
- if (supplies[i].max_capacity > 0 && supplies[i].level >= 0)
- sprintf(ptr, "%d", percent);
+ if ((supplies[i].max_capacity > 0 || (quirks & CUPS_SNMP_CAPACITY)) &&
+ supplies[i].level >= 0)
+ snprintf(ptr, sizeof(value) - (size_t)(ptr - value), "%d", percent);
else
- strcpy(ptr, "-1");
+ strlcpy(ptr, "-1", sizeof(value) - (size_t)(ptr - value));
}
fprintf(stderr, "ATTR: marker-levels=%s\n", value);
"other",
"unknown",
"toner",
- "wasteToner",
+ "waste-toner",
"ink",
- "inkCartridge",
- "inkRibbon",
- "wasteInk",
+ "ink-cartridge",
+ "ink-ribbon",
+ "waste-ink",
"opc",
"developer",
- "fuserOil",
- "solidWax",
- "ribbonWax",
- "wasteWax",
+ "fuser-oil",
+ "solid-wax",
+ "ribbon-wax",
+ "waste-wax",
"fuser",
- "coronaWire",
- "fuserOilWick",
- "cleanerUnit",
- "fuserCleaningPad",
- "transferUnit",
- "tonerCartridge",
- "fuserOiler",
+ "corona-wire",
+ "fuser-oil-wick",
+ "cleaner-unit",
+ "fuser-cleaning-pad",
+ "transfer-unit",
+ "toner-cartridge",
+ "fuser-oiler",
"water",
- "wasteWater",
- "glueWaterAdditive",
- "wastePaper",
- "bindingSupply",
- "bandingSupply",
- "stitchingWire",
- "shrinkWrap",
- "paperWrap",
+ "waste-water",
+ "glue-water-additive",
+ "waste-paper",
+ "binding-supply",
+ "banding-supply",
+ "stitching-wire",
+ "shrink-wrap",
+ "paper-wrap",
"staples",
"inserts",
"covers"
return;
}
+ if ((ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL)
+ {
+ if (!_cups_strcasecmp(ppdattr->value, "capacity"))
+ quirks |= CUPS_SNMP_CAPACITY;
+ }
+
ppdClose(ppd);
/*
/*
* Yes, read the cache file:
*
- * 2 num_supplies charset
+ * 3 num_supplies charset
* device description
* supply structures...
*/
if (cupsFileGets(cachefile, value, sizeof(value)))
{
- if (sscanf(value, "2 %d%d", &num_supplies, &charset) == 2 &&
+ if (sscanf(value, "3 %d%d", &num_supplies, &charset) == 2 &&
num_supplies <= CUPS_MAX_SUPPLIES &&
cupsFileGets(cachefile, value, sizeof(value)))
{
if (!strcmp(description, value))
cupsFileRead(cachefile, (char *)supplies,
- num_supplies * sizeof(backend_supplies_t));
+ (size_t)num_supplies * sizeof(backend_supplies_t));
else
{
num_supplies = -1;
if ((cachefile = cupsFileOpen(cachefilename, "w")) != NULL)
{
- cupsFilePrintf(cachefile, "2 %d %d\n", num_supplies, charset);
+ cupsFilePrintf(cachefile, "3 %d %d\n", num_supplies, charset);
cupsFilePrintf(cachefile, "%s\n", description);
if (num_supplies > 0)
cupsFileWrite(cachefile, (char *)supplies,
- num_supplies * sizeof(backend_supplies_t));
+ (size_t)num_supplies * sizeof(backend_supplies_t));
cupsFileClose(cachefile);
}
*/
for (i = 0; i < num_supplies; i ++)
- strcpy(supplies[i].color, "none");
+ strlcpy(supplies[i].color, "none", sizeof(supplies[i].color));
_cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1,
_cupsSNMPDefaultCommunity(), prtMarkerColorantValue,
if (i)
*ptr++ = ',';
- strcpy(ptr, supplies[i].color);
+ strlcpy(ptr, supplies[i].color, sizeof(value) - (size_t)(ptr - value));
}
fprintf(stderr, "ATTR: marker-colors=%s\n", value);
type = supplies[i].type;
if (type < CUPS_TC_other || type > CUPS_TC_covers)
- strcpy(ptr, "unknown");
+ strlcpy(ptr, "unknown", sizeof(value) - (size_t)(ptr - value));
else
- strcpy(ptr, types[type - CUPS_TC_other]);
+ strlcpy(ptr, types[type - CUPS_TC_other], sizeof(value) - (size_t)(ptr - value));
}
fprintf(stderr, "ATTR: marker-types=%s\n", value);
if (!_cups_strcasecmp(colors[k][0],
(char *)packet->object_value.string.bytes))
{
- strcpy(supplies[j].color, colors[k][1]);
+ strlcpy(supplies[j].color, colors[k][1], sizeof(supplies[j].color));
break;
}
}
supplies[i - 1].level = packet->object_value.integer;
}
- else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesMaxCapacity))
+ else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesMaxCapacity) &&
+ !(quirks & CUPS_SNMP_CAPACITY))
{
/*
* Get max capacity...
if (i > num_supplies)
num_supplies = i;
- supplies[i - 1].max_capacity = packet->object_value.integer;
+ if (supplies[i - 1].max_capacity == 0 &&
+ packet->object_value.integer > 0)
+ supplies[i - 1].max_capacity = packet->object_value.integer;
+ }
+ else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesClass))
+ {
+ /*
+ * Get marker class...
+ */
+
+ i = packet->object_name[prtMarkerSuppliesClassOffset];
+ if (i < 1 || i > CUPS_MAX_SUPPLIES ||
+ packet->object_type != CUPS_ASN1_INTEGER)
+ return;
+
+ fprintf(stderr, "DEBUG2: prtMarkerSuppliesClass.1.%d = %d\n", i,
+ packet->object_value.integer);
+
+ if (i > num_supplies)
+ num_supplies = i;
+
+ supplies[i - 1].sclass = packet->object_value.integer;
}
else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesType))
{
supplies[i - 1].type = packet->object_value.integer;
}
+ else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesSupplyUnit))
+ {
+ /*
+ * Get units for capacity...
+ */
+
+ i = packet->object_name[prtMarkerSuppliesSupplyUnitOffset];
+ if (i < 1 || i > CUPS_MAX_SUPPLIES ||
+ packet->object_type != CUPS_ASN1_INTEGER)
+ return;
+
+ fprintf(stderr, "DEBUG2: prtMarkerSuppliesSupplyUnit.1.%d = %d\n", i,
+ packet->object_value.integer);
+
+ if (i > num_supplies)
+ num_supplies = i;
+
+ if (packet->object_value.integer == CUPS_TC_percent)
+ supplies[i - 1].max_capacity = 100;
+ }
}
for (ptr = temp; srcsize >= 2;)
{
if (le)
- ch = src[0] | (src[1] << 8);
+ ch = (cups_utf32_t)(src[0] | (src[1] << 8));
else
- ch = (src[0] << 8) | src[1];
+ ch = (cups_utf32_t)((src[0] << 8) | src[1]);
src += 2;
srcsize -= 2;
* Multi-word UTF-16 char...
*/
- int lch; /* Lower word */
+ cups_utf32_t lch; /* Lower word */
if (le)
- lch = src[0] | (src[1] << 8);
+ lch = (cups_utf32_t)(src[0] | (src[1] << 8));
else
- lch = (src[0] << 8) | src[1];
+ lch = (cups_utf32_t)((src[0] << 8) | src[1]);
if (lch >= 0xdc00 && lch <= 0xdfff)
{
*ptr = '\0';
- cupsUTF32ToUTF8(dst, temp, dstsize);
+ cupsUTF32ToUTF8(dst, temp, (int)dstsize);
}