ChangeSet 1.859, 2002/11/14 13:57:34-08:00, david-b@pacbell.net [PATCH] HID patches for MGE UPS I thought I'd send the results of some experimentation of mine getting an MGE UPS (Evolution) to talk to 2.5 ... basically it behaved after some patches, though the "hidups" driver didn't. They're all attached: - "hiddev-1.patch" ... The default queue size was so small that this low-speed device couldn't queue up about 110 control requests (that many reports to check!) during init. - "hiddev-2.patch" ... Makes hid debug output more useful by (a) making it compile again; (b) adding lots of "Power Device" and "Battery System" reports, and putting all that data into the readonly data section; (c) actually printing the usage strings, if they're known; (d) printing a message when neither input nor hiddev claim the device ... likely something's wrong, like someone didn't configure in input subsystem or hiddev support. - "hiddev-3.patch" ... Teaches hiddev to expose the physical ID just like the input event framework does. Useful to help sort out which UPS is which, so you won't power down the wrong set of servers by accident. diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c --- a/drivers/usb/input/hid-core.c Thu Nov 14 14:11:53 2002 +++ b/drivers/usb/input/hid-core.c Thu Nov 14 14:11:53 2002 @@ -1572,7 +1572,8 @@ int i; char *c; - dbg("HID probe called for ifnum %d", intf->ifnum); + dbg("HID probe called for ifnum %d", + intf->altsetting->desc.bInterfaceNumber); if (!(hid = usb_hid_configure(intf))) return -EIO; @@ -1590,6 +1591,7 @@ dev_set_drvdata(&intf->dev, hid); if (!hid->claimed) { + printk ("HID device not claimed by input or hiddev\n"); hid_disconnect(intf); return -EIO; } diff -Nru a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h --- a/drivers/usb/input/hid-debug.h Thu Nov 14 14:11:53 2002 +++ b/drivers/usb/input/hid-debug.h Thu Nov 14 14:11:53 2002 @@ -33,7 +33,7 @@ char *description; }; -static struct hid_usage_entry hid_usage_table[] = { +static const struct hid_usage_entry hid_usage_table[] = { { 0, 0, "Undefined" }, { 1, 0, "GenericDesktop" }, {0, 0x01, "Pointer"}, @@ -218,11 +218,95 @@ {0, 0xAA, "Shared_Parameter_Blocks"}, {0, 0xAB, "Create_New_Effect_Report"}, {0, 0xAC, "RAM_Pool_Available"}, + { 0x84, 0, "Power Device" }, + { 0x84, 0x02, "PresentStatus" }, + { 0x84, 0x03, "ChangeStatus" }, + { 0x84, 0x04, "UPS" }, + { 0x84, 0x05, "PowerSupply" }, + { 0x84, 0x10, "BatterySystem" }, + { 0x84, 0x11, "BatterySystemID" }, + { 0x84, 0x12, "Battery" }, + { 0x84, 0x13, "BatteryID" }, + { 0x84, 0x14, "Charger" }, + { 0x84, 0x15, "ChargerID" }, + { 0x84, 0x16, "PowerConverter" }, + { 0x84, 0x17, "PowerConverterID" }, + { 0x84, 0x18, "OutletSystem" }, + { 0x84, 0x19, "OutletSystemID" }, + { 0x84, 0x1a, "Input" }, + { 0x84, 0x1b, "InputID" }, + { 0x84, 0x1c, "Output" }, + { 0x84, 0x1d, "OutputID" }, + { 0x84, 0x1e, "Flow" }, + { 0x84, 0x1f, "FlowID" }, + { 0x84, 0x20, "Outlet" }, + { 0x84, 0x21, "OutletID" }, + { 0x84, 0x22, "Gang" }, + { 0x84, 0x24, "PowerSummary" }, + { 0x84, 0x25, "PowerSummaryID" }, + { 0x84, 0x30, "Voltage" }, + { 0x84, 0x31, "Current" }, + { 0x84, 0x32, "Frequency" }, + { 0x84, 0x33, "ApparentPower" }, + { 0x84, 0x35, "PercentLoad" }, + { 0x84, 0x40, "ConfigVoltage" }, + { 0x84, 0x41, "ConfigCurrent" }, + { 0x84, 0x43, "ConfigApparentPower" }, + { 0x84, 0x53, "LowVoltageTransfer" }, + { 0x84, 0x54, "HighVoltageTransfer" }, + { 0x84, 0x56, "DelayBeforeStartup" }, + { 0x84, 0x57, "DelayBeforeShutdown" }, + { 0x84, 0x58, "Test" }, + { 0x84, 0x5a, "AudibleAlarmControl" }, + { 0x84, 0x60, "Present" }, + { 0x84, 0x61, "Good" }, + { 0x84, 0x62, "InternalFailure" }, + { 0x84, 0x65, "Overload" }, + { 0x84, 0x66, "OverCharged" }, + { 0x84, 0x67, "OverTemperature" }, + { 0x84, 0x68, "ShutdownRequested" }, + { 0x84, 0x69, "ShutdownImminent" }, + { 0x84, 0x6b, "SwitchOn/Off" }, + { 0x84, 0x6c, "Switchable" }, + { 0x84, 0x6d, "Used" }, + { 0x84, 0x6e, "Boost" }, + { 0x84, 0x73, "CommunicationLost" }, + { 0x84, 0xfd, "iManufacturer" }, + { 0x84, 0xfe, "iProduct" }, + { 0x84, 0xff, "iSerialNumber" }, + { 0x85, 0, "Battery System" }, + { 0x85, 0x01, "SMBBatteryMode" }, + { 0x85, 0x02, "SMBBatteryStatus" }, + { 0x85, 0x03, "SMBAlarmWarning" }, + { 0x85, 0x04, "SMBChargerMode" }, + { 0x85, 0x05, "SMBChargerStatus" }, + { 0x85, 0x06, "SMBChargerSpecInfo" }, + { 0x85, 0x07, "SMBSelectorState" }, + { 0x85, 0x08, "SMBSelectorPresets" }, + { 0x85, 0x09, "SMBSelectorInfo" }, + { 0x85, 0x29, "RemainingCapacityLimit" }, + { 0x85, 0x2c, "CapacityMode" }, + { 0x85, 0x42, "BelowRemainingCapacityLimit" }, + { 0x85, 0x44, "Charging" }, + { 0x85, 0x45, "Discharging" }, + { 0x85, 0x4b, "NeedReplacement" }, + { 0x85, 0x66, "RemainingCapacity" }, + { 0x85, 0x68, "RunTimeToEmpty" }, + { 0x85, 0x6a, "AverageTimeToFull" }, + { 0x85, 0x83, "DesignCapacity" }, + { 0x85, 0x85, "ManufacturerDate" }, + { 0x85, 0x89, "iDeviceChemistry" }, + { 0x85, 0x8b, "Rechargable" }, + { 0x85, 0x8f, "iOEMInformation" }, + { 0x85, 0x8d, "CapacityGranularity1" }, + { 0x85, 0xd0, "ACPresent" }, + /* pages 0xff00 to 0xffff are vendor-specific */ + { 0xffff, 0, "Vendor-specific-FF" }, { 0, 0, NULL } }; static void resolv_usage_page(unsigned page) { - struct hid_usage_entry *p; + const struct hid_usage_entry *p; for (p = hid_usage_table; p->description; p++) if (p->page == page) { @@ -233,13 +317,13 @@ } static void resolv_usage(unsigned usage) { - struct hid_usage_entry *p; + const struct hid_usage_entry *p; resolv_usage_page(usage >> 16); printk("."); for (p = hid_usage_table; p->description; p++) if (p->page == (usage >> 16)) { - for(++p; p->description && p->page == 0; p++) + for(++p; p->description && p->page != 0; p++) if (p->usage == (usage & 0xffff)) { printk("%s", p->description); return; diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h --- a/drivers/usb/input/hid.h Thu Nov 14 14:11:53 2002 +++ b/drivers/usb/input/hid.h Thu Nov 14 14:11:53 2002 @@ -306,7 +306,7 @@ #define HID_REPORT_TYPES 3 #define HID_BUFFER_SIZE 32 -#define HID_CONTROL_FIFO_SIZE 64 +#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ #define HID_OUTPUT_FIFO_SIZE 64 struct hid_control_fifo { diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c --- a/drivers/usb/input/hiddev.c Thu Nov 14 14:11:53 2002 +++ b/drivers/usb/input/hiddev.c Thu Nov 14 14:11:53 2002 @@ -652,6 +652,15 @@ return copy_to_user((char *) arg, hid->name, len) ? -EFAULT : len; } + + if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { + int len; + if (!hid->phys) return 0; + len = strlen(hid->phys) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user((char *) arg, hid->phys, len) ? + -EFAULT : len; + } } return -EINVAL; } diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h --- a/include/linux/hiddev.h Thu Nov 14 14:11:53 2002 +++ b/include/linux/hiddev.h Thu Nov 14 14:11:53 2002 @@ -159,6 +159,7 @@ #define HIDIOCSFLAG _IOW('H', 0x0F, int) #define HIDIOCGCOLLECTIONINDEX _IOW('H', 0x10, struct hiddev_usage_ref) #define HIDIOCGCOLLECTIONINFO _IOWR('H', 0x11, struct hiddev_collection_info) +#define HIDIOCGPHYS(len) _IOC(_IOC_READ, 'H', 0x12, len) /* * Flags to be used in HIDIOCSFLAG