Commit bdf0fc9d authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[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.
parent 43c72bb3
...@@ -1572,7 +1572,8 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id ...@@ -1572,7 +1572,8 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
int i; int i;
char *c; 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))) if (!(hid = usb_hid_configure(intf)))
return -EIO; return -EIO;
...@@ -1590,6 +1591,7 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id ...@@ -1590,6 +1591,7 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
dev_set_drvdata(&intf->dev, hid); dev_set_drvdata(&intf->dev, hid);
if (!hid->claimed) { if (!hid->claimed) {
printk ("HID device not claimed by input or hiddev\n");
hid_disconnect(intf); hid_disconnect(intf);
return -EIO; return -EIO;
} }
......
...@@ -33,7 +33,7 @@ struct hid_usage_entry { ...@@ -33,7 +33,7 @@ struct hid_usage_entry {
char *description; char *description;
}; };
static struct hid_usage_entry hid_usage_table[] = { static const struct hid_usage_entry hid_usage_table[] = {
{ 0, 0, "Undefined" }, { 0, 0, "Undefined" },
{ 1, 0, "GenericDesktop" }, { 1, 0, "GenericDesktop" },
{0, 0x01, "Pointer"}, {0, 0x01, "Pointer"},
...@@ -218,11 +218,95 @@ static struct hid_usage_entry hid_usage_table[] = { ...@@ -218,11 +218,95 @@ static struct hid_usage_entry hid_usage_table[] = {
{0, 0xAA, "Shared_Parameter_Blocks"}, {0, 0xAA, "Shared_Parameter_Blocks"},
{0, 0xAB, "Create_New_Effect_Report"}, {0, 0xAB, "Create_New_Effect_Report"},
{0, 0xAC, "RAM_Pool_Available"}, {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 } { 0, 0, NULL }
}; };
static void resolv_usage_page(unsigned page) { 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++) for (p = hid_usage_table; p->description; p++)
if (p->page == page) { if (p->page == page) {
...@@ -233,13 +317,13 @@ static void resolv_usage_page(unsigned page) { ...@@ -233,13 +317,13 @@ static void resolv_usage_page(unsigned page) {
} }
static void resolv_usage(unsigned usage) { static void resolv_usage(unsigned usage) {
struct hid_usage_entry *p; const struct hid_usage_entry *p;
resolv_usage_page(usage >> 16); resolv_usage_page(usage >> 16);
printk("."); printk(".");
for (p = hid_usage_table; p->description; p++) for (p = hid_usage_table; p->description; p++)
if (p->page == (usage >> 16)) { 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)) { if (p->usage == (usage & 0xffff)) {
printk("%s", p->description); printk("%s", p->description);
return; return;
......
...@@ -306,7 +306,7 @@ struct hid_report_enum { ...@@ -306,7 +306,7 @@ struct hid_report_enum {
#define HID_REPORT_TYPES 3 #define HID_REPORT_TYPES 3
#define HID_BUFFER_SIZE 32 #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 #define HID_OUTPUT_FIFO_SIZE 64
struct hid_control_fifo { struct hid_control_fifo {
......
...@@ -652,6 +652,15 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd ...@@ -652,6 +652,15 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return copy_to_user((char *) arg, hid->name, len) ? return copy_to_user((char *) arg, hid->name, len) ?
-EFAULT : 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; return -EINVAL;
} }
......
...@@ -159,6 +159,7 @@ struct hiddev_usage_ref { ...@@ -159,6 +159,7 @@ struct hiddev_usage_ref {
#define HIDIOCSFLAG _IOW('H', 0x0F, int) #define HIDIOCSFLAG _IOW('H', 0x0F, int)
#define HIDIOCGCOLLECTIONINDEX _IOW('H', 0x10, struct hiddev_usage_ref) #define HIDIOCGCOLLECTIONINDEX _IOW('H', 0x10, struct hiddev_usage_ref)
#define HIDIOCGCOLLECTIONINFO _IOWR('H', 0x11, struct hiddev_collection_info) #define HIDIOCGCOLLECTIONINFO _IOWR('H', 0x11, struct hiddev_collection_info)
#define HIDIOCGPHYS(len) _IOC(_IOC_READ, 'H', 0x12, len)
/* /*
* Flags to be used in HIDIOCSFLAG * Flags to be used in HIDIOCSFLAG
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment