52
59
extern void upsdebugx(int level, const char *fmt, ...);
53
60
#define TRACE upsdebugx
55
/* Units and exponents table (HID PDC, ļæ½3.2.3) */
62
/* Units and exponents table (HID PDC, 3.2.3) */
56
63
#define NB_HID_UNITS 10
57
64
const long HIDUnits[NB_HID_UNITS][2]=
59
{0x00000000,0}, /* None */
60
{0x00F0D121,7}, /* Voltage */
61
{0x00100001,0}, /* Ampere */
62
{0x0000D121,7}, /* VA */
63
{0x0000D121,7}, /* Watts */
64
{0x00001001,0}, /* second */
65
{0x00010001,0}, /* ļæ½K */
66
{0x00000000,0}, /* percent */
67
{0x0000F001,0}, /* Hertz */
68
{0x00101001,0}, /* As */
66
{0x00000000,0}, /* None */
67
{0x00F0D121,7}, /* Voltage */
68
{0x00100001,0}, /* Ampere */
69
{0x0000D121,7}, /* VA */
70
{0x0000D121,7}, /* Watts */
71
{0x00001001,0}, /* second */
72
{0x00010001,0}, /* K */
73
{0x00000000,0}, /* percent */
74
{0x0000F001,0}, /* Hertz */
75
{0x00101001,0}, /* As */
71
78
/* support functions */
72
79
void logical_to_physical(HIDData *Data);
73
80
void physical_to_logical(HIDData *Data);
81
const char *hid_lookup_path(int usage);
74
82
int hid_lookup_usage(char *name);
75
ushort lookup_path(const char *HIDpath, HIDData *data);
83
ushort lookup_path(char *HIDpath, HIDData *data);
76
84
void dump_hex (const char *msg, const unsigned char *buf, int len);
77
85
long get_unit_expo(long UnitType);
78
86
float expo(int a, int b);
81
HIDDevice *HIDOpenDevice(const char *port, MatchFlags *flg)
86
curDevice.Name = NULL;
87
curDevice.Vendor = NULL;
88
curDevice.VendorID = -1;
89
curDevice.Product = NULL;
90
curDevice.ProductID = -1;
91
curDevice.Serial = NULL;
92
curDevice.Application = -1;
95
/* get and parse descriptors (dev, cfg and report) */
96
if ((ReportSize = libusb_open(&curDevice, flg, ReportDesc)) == -1) {
100
TRACE(2, "Report Descriptor size = %d", ReportSize);
101
dump_hex ("Report Descriptor", ReportDesc, 200);
103
/* HID Parser Init */
104
ResetParser(&hParser);
105
hParser.ReportDescSize = ReportSize;
106
memcpy(hParser.ReportDesc, ReportDesc, ReportSize);
107
HIDParse(&hParser, &hData);
109
/* CHeck for matching UsageCode (1rst collection == application == type of device) */
110
if ((hData.Path.Node[0].UPage == ((flg->UsageCode & 0xFFFF0000) / 0x10000))
111
&& (hData.Path.Node[0].Usage == (flg->UsageCode & 0x0000FFFF)))
112
TRACE(2, "Found a device matching UsageCode (0x%08x)", flg->UsageCode);
114
TRACE(2, "Found a device, but not matching UsageCode (0x%08x)", flg->UsageCode);
89
void HIDDumpTree(HIDDevice *hd)
94
while (HIDParse(&hParser, &hData) != FALSE)
97
for (i = 0; i < hData.Path.Size; i++)
99
strcat(str, hid_lookup_path((hData.Path.Node[i].UPage * 0x10000) + hData.Path.Node[i].Usage));
100
if (i < (hData.Path.Size - 1))
103
TRACE(1, "Path: %s", str);
107
HIDDevice *HIDOpenDevice(const char *port, MatchFlags *flg, int mode)
111
if ( mode == MODE_OPEN )
114
curDevice.Name = NULL;
115
curDevice.Vendor = NULL;
116
curDevice.VendorID = -1;
117
curDevice.Product = NULL;
118
curDevice.ProductID = -1;
119
curDevice.Serial = NULL;
120
curDevice.Application = -1;
125
TRACE(2, "Reopening device");
128
/* get and parse descriptors (dev, cfg and report) */
129
ReportSize = libusb_open(&curDevice, flg, ReportDesc, mode);
131
if (ReportSize == -1)
135
if ( mode == MODE_REOPEN )
137
TRACE(2, "Device reopened successfully");
141
TRACE(2, "Report Descriptor size = %d", ReportSize);
142
dump_hex ("Report Descriptor", ReportDesc, 200);
144
/* HID Parser Init */
145
ResetParser(&hParser);
146
hParser.ReportDescSize = ReportSize;
147
memcpy(hParser.ReportDesc, ReportDesc, ReportSize);
148
HIDParse(&hParser, &hData);
153
/* int HIDGetItem(hid_info_t *ItemInfo, HIDItem *item) */
121
154
HIDItem *HIDGetItem(const char *ItemPath)
126
float HIDGetItemValue(const char *path)
131
/* Prepare path of HID object */
132
hData.Type = ITEM_FEATURE;
135
if((retcode = lookup_path(path, &hData)) > 0) {
136
TRACE(2, "Path depth = %i", retcode);
138
for (i = 0; i<retcode; i++)
139
TRACE(2, "%i: UPage(%x), Usage(%x)", i,
140
hData.Path.Node[i].UPage,
141
hData.Path.Node[i].Usage);
143
hData.Path.Size = retcode;
145
/* Get info on object (reportID, offset and size) */
146
if (FindObject(&hParser,&hData) == 1) {
147
/* Get report with data */
148
/* if ((replen=libusb_get_report(hData.ReportID,
149
raw_buf, MAX_REPORT_SIZE)) > 0) { => doesn't work! */
150
if ((replen=libusb_get_report(hData.ReportID, raw_buf, 10)) > 0) {
151
/* Extract the data value */
152
GetValue((const unsigned char *) raw_buf, &hData);
154
TRACE(2, "=>> Before exponent: %ld, %i/%i)", hData.Value,
155
(int)hData.UnitExp, (int)get_unit_expo(hData.Unit) );
157
/* Convert Logical Min, Max and Value in Physical */
158
/* logical_to_physical(&hData); */
162
/* Process exponents */
163
/* Value*=(float) pow(10,(int)hData.UnitExp - get_unit_expo(hData.Unit)); */
164
Value*=(float) expo(10,(int)hData.UnitExp - get_unit_expo(hData.Unit));
165
hData.Value = (long) Value;
167
/* Convert Logical Min, Max and Value into Physical */
168
logical_to_physical(&hData);
170
dump_hex ("Report ", raw_buf, replen);
175
TRACE(2, "Can't retrieve Report %i", hData.ReportID);
179
TRACE(2, "Can't find object %s", path);
181
return -2; /* TODO: should be checked */
184
char *HIDGetItemString(const char *path)
188
/* Prepare path of HID object */
189
hData.Type = ITEM_FEATURE;
192
if((retcode = lookup_path(path, &hData)) > 0) {
193
TRACE(2, "Path depth = %i", retcode);
195
for (i = 0; i<retcode; i++)
196
TRACE(2, "%i: UPage(%x), Usage(%x)", i,
156
/* was for libhid, not useful in our scope! */
160
/* return 1 if OK, 0 on fail, <= -1 otherwise (ie disconnect) */
161
float HIDGetItemValue(char *path, float *Value)
166
/* Prepare path of HID object */
167
hData.Type = ITEM_FEATURE;
171
if((retcode = lookup_path(path, &hData)) > 0)
173
TRACE(4, "Path depth = %i", retcode);
175
for (i = 0; i<retcode; i++)
176
TRACE(4, "%i: UPage(%x), Usage(%x)", i,
177
hData.Path.Node[i].UPage,
178
hData.Path.Node[i].Usage);
180
hData.Path.Size = retcode;
182
/* Get info on object (reportID, offset and size) */
183
if (FindObject(&hParser, &hData) == 1)
185
/* Get report with data */
186
/* if ((replen=libusb_get_report(hData.ReportID,
187
raw_buf, MAX_REPORT_SIZE)) > 0) { => doesn't work! */
188
/* Bufferize at least the last report */
189
if ( ( (prev_report == hData.ReportID) && (time(NULL) <= (prev_report_ts + MAX_TS)) )
190
|| ((replen=libusb_get_report(hData.ReportID, raw_buf, 10)) > 0) )
192
/* Extract the data value */
193
GetValue((const unsigned char *) raw_buf, &hData);
195
TRACE(4, "=>> Before exponent: %ld, %i/%i)", hData.Value,
196
(int)hData.UnitExp, (int)get_unit_expo(hData.Unit) );
198
/* Convert Logical Min, Max and Value in Physical */
199
/* logical_to_physical(&hData); */
201
tmpValue = hData.Value;
203
/* Process exponents */
204
/* Value*=(float) pow(10,(int)hData.UnitExp - get_unit_expo(hData.Unit)); */
205
tmpValue*=(float) expo(10,(int)hData.UnitExp - get_unit_expo(hData.Unit));
206
hData.Value = (long) tmpValue;
208
/* Convert Logical Min, Max and Value into Physical */
209
logical_to_physical(&hData);
211
TRACE(4, "=>> After conversion: %ld, %i/%i)", hData.Value,
212
(int)hData.UnitExp, (int)get_unit_expo(hData.Unit) );
214
dump_hex ("Report ", raw_buf, replen);
216
*Value = hData.Value;
217
prev_report = hData.ReportID;
218
prev_report_ts = time(NULL);
223
TRACE(2, "Can't retrieve Report %i (%i/%i)", hData.ReportID, replen, errno);
228
TRACE(2, "Can't find object %s", path);
230
return 0; /* TODO: should be checked */
233
char *HIDGetItemString(char *path)
237
/* Prepare path of HID object */
238
hData.Type = ITEM_FEATURE;
242
if((retcode = lookup_path(path, &hData)) > 0) {
243
TRACE(4, "Path depth = %i", retcode);
245
for (i = 0; i<retcode; i++)
246
TRACE(4, "%i: UPage(%x), Usage(%x)", i,
197
247
hData.Path.Node[i].UPage,
198
248
hData.Path.Node[i].Usage);
222
bool HIDSetItemValue(const char *path, float value)
272
bool HIDSetItemValue(char *path, float value)
226
/* Begin by a standard Get to fill in com structures ... */
227
Value = HIDGetItemValue(path);
229
/* ... And play with global vars */
230
if (Value != -2) { /* Get succeed */
232
TRACE(2, "=>> SET: Before set: %.2f (%ld)", Value, (long)value);
234
/* Test if Item is settable */
235
if (hData.Attribute != ATTR_DATA_CST) {
236
/* Set new value for this item */
237
/* And Process exponents restoration */
238
Value = value * expo(10, get_unit_expo(hData.Unit) - (int)hData.UnitExp);
240
hData.Value=(long) Value;
242
TRACE(2, "=>> SET: after exp: %ld/%.2f (exp = %.2f)", hData.Value, Value,
243
expo(10, (int)get_unit_expo(hData.Unit) - (int)hData.UnitExp));
245
/* Convert Physical Min, Max and Value in Logical */
246
physical_to_logical(&hData);
247
TRACE(2, "=>> SET: after PL: %ld", hData.Value);
249
SetValue(&hData, raw_buf);
251
dump_hex ("==> Report after setvalue", raw_buf, replen);
253
if (libusb_set_report(hData.ReportID, raw_buf, replen) > 0) {
254
TRACE(2, "Set report succeeded");
257
TRACE(2, "Set report failed");
277
/* Begin by a standard Get to fill in com structures ... */
278
retcode = HIDGetItemValue(path, &Value);
280
/* ... And play with global vars */
281
if (retcode == 1) /* Get succeed */
283
TRACE(2, "=>> SET: Before set: %.2f (%ld)", Value, (long)value);
285
/* Test if Item is settable */
286
if (hData.Attribute != ATTR_DATA_CST)
288
/* Set new value for this item */
289
/* And Process exponents restoration */
290
Value = value * expo(10, get_unit_expo(hData.Unit) - (int)hData.UnitExp);
292
hData.Value=(long) Value;
294
TRACE(2, "=>> SET: after exp: %ld/%.2f (exp = %.2f)", hData.Value, Value,
295
expo(10, (int)get_unit_expo(hData.Unit) - (int)hData.UnitExp));
297
/* Convert Physical Min, Max and Value in Logical */
298
physical_to_logical(&hData);
299
TRACE(2, "=>> SET: after PL: %ld", hData.Value);
301
SetValue(&hData, raw_buf);
303
dump_hex ("==> Report after setvalue", raw_buf, replen);
305
if (libusb_set_report(hData.ReportID, raw_buf, replen) > 0)
307
TRACE(2, "Set report succeeded");
312
TRACE(2, "Set report failed");
315
/* check if set succeed! => doesn't work on *Delay (decremented!) */
316
/* Value = HIDGetItemValue(path);
318
TRACE(2, "=>> SET: new value = %.2f (was set to %.2f)\n",
319
Value, (float) value);
320
return TRUE;*/ /* (Value == value); */
260
/* check if set succeed! => doesn't work on *Delay (decremented!) */
261
/* Value = HIDGetItemValue(path);
263
TRACE(2, "=>> SET: new value = %.2f (was set to %.2f)\n",
264
Value, (float) value);
265
return TRUE;*/ /* (Value == value); */
270
HIDItem *HIDGetNextEvent(HIDDevice *dev)
326
int HIDGetEvents(HIDDevice *dev, HIDItem **eventsList)
272
/* unsigned char buf[20];
274
upsdebugx(1, "Waiting for notifications\n");*/
276
/* TODO: To be written */
277
/* needs libusb-0.1.8 to work => use ifdef and autoconf */
278
/* libusb_get_interrupt(&buf[0], 20, 5000); */
328
unsigned char buf[20];
330
int size, offset = 0, itemCount = 0;
332
upsdebugx(1, "Waiting for notifications...");
334
/* needs libusb-0.1.8 to work => use ifdef and autoconf */
335
if ((size = libusb_get_interrupt(&buf[0], 20, 5000)) > -1)
337
dump_hex ("Notification", buf, size);
339
/* Convert report size in bits */
340
size = (size - 1) * 8;
342
/* Parse response Report and Set correspondant Django values */
343
hData.ReportID = buf[0];
344
hData.Type = ITEM_INPUT;
349
hData.Offset = offset;
351
/* Reset HID Path but keep Report ID */
352
memset(&hData.Path, '\0', sizeof(HIDPath));
354
/* Get HID Object characteristics */
355
if(FindObject(&hParser, &hData))
357
/* Get HID Object value from report */
358
GetValue(buf, &hData);
359
memset(&itemPath, 0, sizeof(128));
360
lookup_path(&itemPath[0], &hData);
362
upsdebugx(3, "Object: %s = %ld", itemPath, hData.Value);
364
/* FIXME: enhance this or fix/change the HID parser (see libhid project) */
365
/* if ( strstr(itemPath, "000000") == NULL) */
366
if (strcmp(itemPath, "UPS.PowerSummary.PresentStatus.") > 0)
368
eventsList[itemCount] = (HIDItem *)malloc(sizeof (HIDItem));
369
eventsList[itemCount]->Path = strdup(itemPath);
370
eventsList[itemCount]->Value = hData.Value;
374
offset += hData.Size;
378
itemCount = size; /* propagate error code */
281
383
void HIDCloseDevice(HIDDevice *dev)
283
libusb_close(&curDevice);
385
TRACE(2, "Closing device");
386
libusb_close(&curDevice);
287
390
/*******************************************************
289
392
*******************************************************/
291
394
#define MAX_STRING 64
293
396
void logical_to_physical(HIDData *Data)
295
if(Data->PhyMax - Data->PhyMin > 0)
297
float Factor = (float)(Data->PhyMax - Data->PhyMin) / (Data->LogMax - Data->LogMin);
299
Data->Value=(long)((Data->Value - Data->LogMin) * Factor) + Data->PhyMin;
301
if(Data->Value > Data->PhyMax)
302
Data->Value |= ~Data->PhyMax;
304
else /* => nothing to do!? */
306
/* Value.m_Value=(long)(pConvPrm->HValue); */
307
if(Data->Value > Data->LogMax)
308
Data->Value |= ~Data->LogMax;
311
/* if(Data->Value > Data->Value.m_Max)
312
Value.m_Value |= ~Value.m_Max;
398
if(Data->PhyMax - Data->PhyMin > 0)
400
float Factor = (float)(Data->PhyMax - Data->PhyMin) / (Data->LogMax - Data->LogMin);
402
Data->Value=(long)((Data->Value - Data->LogMin) * Factor) + Data->PhyMin;
404
if(Data->Value > Data->PhyMax)
405
Data->Value |= ~Data->PhyMax;
407
else /* => nothing to do!? */
409
/* Value.m_Value=(long)(pConvPrm->HValue); */
410
if(Data->Value > Data->LogMax)
411
Data->Value |= ~Data->LogMax;
414
/* if(Data->Value > Data->Value.m_Max)
415
Value.m_Value |= ~Value.m_Max;
316
419
void physical_to_logical(HIDData *Data)
318
TRACE(2, "PhyMax = %ld, PhyMin = %ld, LogMax = %ld, LogMin = %ld",
319
Data->PhyMax, Data->PhyMin, Data->LogMax, Data->LogMin);
321
if(Data->PhyMax - Data->PhyMin > 0)
323
float Factor=(float)(Data->LogMax - Data->LogMin) / (Data->PhyMax - Data->PhyMin);
325
Data->Value=(long)((Data->Value - Data->PhyMin) * Factor) + Data->LogMin;
327
/* else => nothing to do!?
329
m_ConverterTab[iTab].HValue=m_ConverterTab[iTab].DValue;
421
TRACE(2, "PhyMax = %ld, PhyMin = %ld, LogMax = %ld, LogMin = %ld",
422
Data->PhyMax, Data->PhyMin, Data->LogMax, Data->LogMin);
424
if(Data->PhyMax - Data->PhyMin > 0)
426
float Factor=(float)(Data->LogMax - Data->LogMin) / (Data->PhyMax - Data->PhyMin);
429
Data->Value=(long)((Data->Value - Data->PhyMin) * Factor) + Data->LogMin;
431
/* else => nothing to do!?
433
m_ConverterTab[iTab].HValue=m_ConverterTab[iTab].DValue;
333
437
long get_unit_expo(long UnitType)
337
while (i < NB_HID_UNITS) {
338
if (HIDUnits[i][0] == UnitType) {
339
exp = HIDUnits[i][1];
441
while (i < NB_HID_UNITS)
443
if (HIDUnits[i][0] == UnitType)
445
exp = HIDUnits[i][1];
347
453
/* exponent function: return a^b */
348
/* TODO: check if needed to replace libmath->pow */
454
/* FIXME: check if needed/possible to replace libmath->pow */
349
455
float expo(int a, int b)
354
return (float) a * expo(a,b-1);
356
return (float)((float)(1/(float)a) * (float) expo(a,b+1));
460
return (float) a * expo(a,b-1);
462
return (float)((float)(1/(float)a) * (float) expo(a,b+1));
362
/* translate HID string path to numeric path and return path depth */
468
/* translate HID string path from/to numeric path and return path depth */
363
469
/* TODO: use usbutils functions (need to be externalised!) */
364
ushort lookup_path(const char *HIDpath, HIDData *data)
470
ushort lookup_path(char *HIDpath, HIDData *data)
366
ushort i = 0, cond = 1;
368
char buf[MAX_STRING];
371
strncpy(buf, HIDpath, strlen(HIDpath));
372
buf[strlen(HIDpath)] = '\0';
375
TRACE(2, "entering lookup_path(%s)", buf);
379
if ((end = strchr(start, '.')) == NULL) {
385
TRACE(2, "parsing %s", start);
388
if ((cur_usage = hid_lookup_usage(start)) == -1) {
389
TRACE(2, "%s wasn't found", start);
393
data->Path.Node[i].UPage = (cur_usage & 0xFFFF0000) / 0x10000;
394
data->Path.Node[i].Usage = cur_usage & 0x0000FFFF;
472
ushort i = 0, cond = 1;
474
char buf[MAX_STRING];
477
TRACE(3, "entering lookup_path()");
479
/* Check the way we are called */
480
if (data->Path.Size != 0)
482
/* FIXME: another bug? */
483
strcat(HIDpath, "UPS.");
486
for (i = 1; i <= hData.Path.Size; i++)
488
/* Deal with ?bogus? */
489
if ( ((hData.Path.Node[i].UPage * 0x10000) + hData.Path.Node[i].Usage) == 0)
492
/* manage indexed collection */
493
if (hData.Path.Node[i].UPage == 0x00FF)
495
TRACE(5, "Got an indexed collection");
496
sprintf(strrchr(HIDpath, '.'), "[%i]", hData.Path.Node[i].Usage);
499
strcat(HIDpath, hid_lookup_path((hData.Path.Node[i].UPage * 0x10000) + hData.Path.Node[i].Usage));
501
if (i < (hData.Path.Size - 1))
502
strcat (HIDpath, ".");
508
strncpy(buf, HIDpath, strlen(HIDpath));
509
buf[strlen(HIDpath)] = '\0';
514
if ((end = strchr(start, '.')) == NULL) {
520
TRACE(4, "parsing %s", start);
523
if ((cur_usage = hid_lookup_usage(start)) == -1) {
524
TRACE(4, "%s wasn't found", start);
528
data->Path.Node[i].UPage = (cur_usage & 0xFFFF0000) / 0x10000;
529
data->Path.Node[i].Usage = cur_usage & 0x0000FFFF;
412
549
static usage_lkp_t usage_lkp[] = {
413
550
/* Power Device Page */
414
{ "PresentStatus", 0x00840002 },
415
{ "UPS", 0x00840004 },
416
{ "BatterySystem", 0x00840010 },
417
{ "Battery", 0x00840012 },
418
{ "BatteryID", 0x00840013 },
419
{ "PowerConverter", 0x00840016 },
420
{ "OutletSystem", 0x00840018 },
421
{ "Input", 0x0084001a },
422
{ "Output", 0x0084001c },
423
{ "Outlet", 0x00840020 },
424
{ "OutletID", 0x00840021 },
425
{ "PowerSummary", 0x00840024 },
426
{ "Voltage", 0x00840030 },
427
{ "Current", 0x00840031 },
428
{ "Frequency", 0x00840032 },
429
{ "PercentLoad", 0x00840035 },
430
{ "Temperature", 0x00840036 },
431
{ "ConfigVoltage", 0x00840040 },
432
{ "ConfigCurrent", 0x00840041 },
433
{ "ConfigFrequency", 0x00840042 },
434
{ "ConfigApparentPower", 0x00840043 },
435
{ "LowVoltageTransfer", 0x00840053 },
436
{ "HighVoltageTransfer", 0x00840054 },
437
{ "DelayBeforeReboot", 0x00840055 },
438
{ "DelayBeforeStartup", 0x00840056 },
439
{ "DelayBeforeShutdown", 0x00840057 },
440
{ "Test", 0x00840058 },
441
{ "OverLoad", 0x00840065 }, /* mispelled in usb.ids */
442
{ "ShutdownImminent", 0x00840069 },
443
{ "SwitchOn/Off", 0x0084006b },
444
{ "Switchable", 0x0084006c },
445
{ "Boost", 0x0084006e },
446
{ "Buck", 0x0084006f },
447
{ "Flow", 0x0084001e },
551
{ "Undefined", 0x00840000 },
552
{ "PresentStatus", 0x00840002 },
553
{ "UPS", 0x00840004 },
554
{ "BatterySystem", 0x00840010 },
555
{ "Battery", 0x00840012 },
556
{ "BatteryID", 0x00840013 },
557
{ "PowerConverter", 0x00840016 },
558
{ "PowerConverterID", 0X00840017 },
559
{ "OutletSystem", 0x00840018 },
560
{ "OutletSystemID", 0x00840019 },
561
{ "Input", 0x0084001a },
562
{ "Output", 0x0084001c },
563
{ "Flow", 0x0084001e },
564
{ "FlowID", 0x0084001f },
565
{ "Outlet", 0x00840020 },
566
{ "OutletID", 0x00840021 },
567
{ "PowerSummary", 0x00840024 },
568
{ "PowerSummaryID", 0x00840025 },
569
{ "Voltage", 0x00840030 },
570
{ "Current", 0x00840031 },
571
{ "Frequency", 0x00840032 },
572
{ "PercentLoad", 0x00840035 },
573
{ "Temperature", 0x00840036 },
574
{ "ConfigVoltage", 0x00840040 },
575
{ "ConfigCurrent", 0x00840041 },
576
{ "ConfigFrequency", 0x00840042 },
577
{ "ConfigApparentPower", 0x00840043 },
578
{ "LowVoltageTransfer", 0x00840053 },
579
{ "HighVoltageTransfer", 0x00840054 },
580
{ "DelayBeforeReboot", 0x00840055 },
581
{ "DelayBeforeStartup", 0x00840056 },
582
{ "DelayBeforeShutdown", 0x00840057 },
583
{ "Test", 0x00840058 },
584
{ "AudibleAlarmControl", 0x0084005a },
585
{ "Good", 0x00840061 },
586
{ "InternalFailure", 0x00840062 },
587
{ "OverLoad", 0x00840065 }, /* mispelled in usb.ids */
588
{ "OverTemperature", 0x00840067 },
589
{ "ShutdownRequested", 0x00840068 },
590
{ "ShutdownImminent", 0x00840069 },
591
{ "SwitchOn/Off", 0x0084006b },
592
{ "Switchable", 0x0084006c },
593
{ "Used", 0x0084006d },
594
{ "Boost", 0x0084006e },
595
{ "Buck", 0x0084006f },
596
{ "CommunicationLost", 0x00840073 },
597
{ "iManufacturer", 0x008400fd },
598
{ "iProduct", 0x008400fe },
599
{ "iSerialNumber", 0x008400ff },
448
600
/* Battery System Page */
449
{ "RemainingCapacityLimit", 0x00850029 },
450
{ "BelowRemainingCapacityLimit", 0x00850042 },
451
{ "RemainingCapacity", 0x00850066 },
452
{ "RunTimeToEmpty", 0x00850068 },
453
{ "ACPresent", 0x008500d0 },
454
{ "Charging", 0x00850044 },
455
{ "Discharging", 0x00850045 },
456
{ "NeedReplacement", 0x0085004b },
601
{ "Undefined", 0x00850000 },
602
{ "RemainingCapacityLimit", 0x00850029 },
603
{ "RemainingTimeLimit", 0x0085002a },
604
{ "CapacityMode", 0x0085002c },
605
{ "BelowRemainingCapacityLimit", 0x00850042 },
606
{ "RemainingTimeLimitExpired", 0x00850043 },
607
{ "Charging", 0x00850044 },
608
{ "Discharging", 0x00850045 },
609
{ "NeedReplacement", 0x0085004b },
610
{ "RemainingCapacity", 0x00850066 },
611
{ "FullChargeCapacity", 0x00850067 },
612
{ "RunTimeToEmpty", 0x00850068 },
613
{ "ManufacturerDate", 0x00850085 },
614
{ "Rechargeable", 0x0085008b },
615
{ "WarningCapacityLimit", 0x0085008c },
616
{ "CapacityGranularity1", 0x0085008d },
617
{ "CapacityGranularity2", 0x0085008e },
618
{ "iOEMInformation", 0x0085008f },
619
{ "DesignCapacity", 0x00850083 },
620
{ "iDeviceChemistry", 0x00850089 },
621
{ "ACPresent", 0x008500d0 },
622
{ "BatteryPresent", 0x008500d1 },
623
{ "VoltageNotRegulated", 0x008500db },
457
624
/* TODO: per MFR specific usages */
458
625
/* MGE UPS SYSTEMS Page */
459
{ "iModel", 0xffff00f0 },
460
{ "RemainingCapacityLimitSetting", 0xffff004d },
461
{ "TestPeriod", 0xffff0045 },
462
{ "LowVoltageBoostTransfer", 0xffff0050 },
463
{ "HighVoltageBoostTransfer", 0xffff0051 },
464
{ "LowVoltageBuckTransfer", 0xffff0052 },
465
{ "HighVoltageBuckTransfer", 0xffff0053 },
626
{ "iModel", 0xffff00f0 },
627
{ "RemainingCapacityLimitSetting", 0xffff004d },
628
{ "TestPeriod", 0xffff0045 },
629
{ "LowVoltageBoostTransfer", 0xffff0050 },
630
{ "HighVoltageBoostTransfer", 0xffff0051 },
631
{ "LowVoltageBuckTransfer", 0xffff0052 },
632
{ "HighVoltageBuckTransfer", 0xffff0053 },
634
{ "APCGeneralCollection", 0xff860005 },
635
{ "APCBattReplaceDate", 0xff860016 },
636
{ "APCBattCapBeforeStartup", 0xFF860019 }, /* FIXME: need to be exploited */
637
{ "APC_UPS_FirmwareRevision", 0xff860042 },
638
{ "APC860052", 0xff860052 }, /* Needed for APCForceShutdown path */
639
{ "APCStatusFlag", 0xff860060 },
640
{ "APCPanelTest", 0xff860072 }, /* FIXME: need to be exploited */
641
{ "APCShutdownAfterDelay", 0xff860076 }, /* FIXME: need to be exploited */
642
{ "APC_USB_FirmwareRevision", 0xff860079 }, /* FIXME: need to be exploited */
643
{ "APCForceShutdown", 0xff86007c },
644
{ "APCDelayBeforeShutdown", 0xff86007d },
645
{ "APCDelayBeforeStartup", 0xff86007e }, /* FIXME: need to be exploited */
646
/* FIXME: The below one seems to have been wrongly encoded by APC */
647
/* Pages 84 to 88 are reserved for official HID definition! */
648
{ "BUPHibernate", 0x00850058 }, /* FIXME: need to be exploited */
649
{ "BUPBattCapBeforeStartup", 0x00860012 }, /* FIXME: need to be exploited */
650
{ "BUPDelayBeforeStartup", 0x00860076 }, /* FIXME: need to be exploited */
651
{ "BUPSelfTest", 0x00860010 }, /* FIXME: need to be exploited */
653
* USB USAGE NOTES for APC (from Russell Kroll in the old hidups
655
* FIXME: read 0xff86.... instead of 0x(00)86....?
657
* 0x860013 == 44200155090 - capability again
658
* == locale 4, 4 choices, 2 bytes, 00, 15, 50, 90
659
* == minimum charge to return online
661
* 0x860060 == "441HMLL" - looks like a 'capability' string
662
* == locale 4, 4 choices, 1 byte each
663
* == line sensitivity (high, medium, low, low)
664
* NOTE! the above does not seem to correspond to my info
666
* 0x860062 == D43133136127130
667
* == locale D, 4 choices, 3 bytes, 133, 136, 127, 130
668
* == high transfer voltage
670
* 0x860064 == D43103100097106
671
* == locale D, 4 choices, 3 bytes, 103, 100, 097, 106
672
* == low transfer voltage
674
* 0x860066 == 441HMLL (see 860060)
676
* 0x860074 == 4410TLN
677
* == locale 4, 4 choices, 1 byte, 0, T, L, N
678
* == alarm setting (5s, 30s, low battery, none)
680
* 0x860077 == 443060180300600
681
* == locale 4, 4 choices, 3 bytes, 060,180,300,600
682
* == wake-up delay (after power returns)
466
685
/* end of structure. */
689
const char *hid_lookup_path(int usage)
692
static char raw_usage[10];
694
TRACE(3, "Looking up %08x", usage);
696
for (i = 0; (usage_lkp[i].usage_name[0] != '\0'); i++)
698
if (usage_lkp[i].usage_code == usage)
699
return usage_lkp[i].usage_name;
702
/* if the corresponding path isn't found,
703
return the numeric usage in string form */
704
sprintf (&raw_usage[0], "%08x", usage);
705
return &raw_usage[0];
470
708
int hid_lookup_usage(char *name)
474
TRACE(2, "Looking up %s", name);
476
if (name[0] == '[') /* manage indexed collection */
477
return (0x00FF0000 + atoi(&name[1]));
479
for (i = 0; (usage_lkp[i].usage_code != 0x0); i++)
481
if (!strcmp(usage_lkp[i].usage_name, name))
483
TRACE(2, "hid_lookup_usage: found %04x",
484
usage_lkp[i].usage_code);
485
return usage_lkp[i].usage_code;
712
TRACE(3, "Looking up %s", name);
714
if (name[0] == '[') /* manage indexed collection */
715
return (0x00FF0000 + atoi(&name[1]));
718
for (i = 0; (usage_lkp[i].usage_code != 0x0); i++)
720
if (!strcmp(usage_lkp[i].usage_name, name))
722
TRACE(4, "hid_lookup_usage: found %04x",
723
usage_lkp[i].usage_code);
725
return usage_lkp[i].usage_code;
492
732
#define NIBBLE(_i) (((_i) < 10) ? '0' + (_i) : 'A' + (_i) - 10)
494
734
void dump_hex (const char *msg, const unsigned char *buf, int len)
498
const unsigned char *pc;
500
const unsigned char *start;
507
for (i = 0, pc = buf, nlocal = len; i < 16; i++, pc++) {
511
*out++ = NIBBLE ((c >> 4) & 0xF);
512
*out++ = NIBBLE (c & 0xF);
524
TRACE(2, "%s: (%d bytes) => %s", msg, len, line);
738
const unsigned char *pc;
740
const unsigned char *start;
747
for (i = 0, pc = buf, nlocal = len; i < 16; i++, pc++)
753
*out++ = NIBBLE ((c >> 4) & 0xF);
754
*out++ = NIBBLE (c & 0xF);
767
TRACE(3, "%s: (%d bytes) => %s", msg, len, line);