diff options
| author | Jeremy Fitzhardinge <jeremy@goop.org> | 2011-12-02 14:12:36 -0500 |
|---|---|---|
| committer | Jeremy Fitzhardinge <jeremy@goop.org> | 2012-01-08 02:30:37 -0500 |
| commit | bbc21cfd55858d7c3e55bfaa91fa934b0b13ad4d (patch) | |
| tree | 8b0495e337bd64c8677c218d01bb3cc2e6211663 | |
| parent | ef5251993c3597a88b893fe22ee830092dff35f9 (diff) | |
hid-input/battery: add quirks for battery
Some devices always report percentage, despite having 0/255 as their
min/max, so add a quirk for them.
Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org>
| -rw-r--r-- | drivers/hid/hid-core.c | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-input.c | 41 | ||||
| -rw-r--r-- | include/linux/hid.h | 2 |
3 files changed, 40 insertions, 5 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c0ef2b49a00c..aa4a30b7c6af 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1157,7 +1157,7 @@ static bool hid_match_one_id(struct hid_device *hdev, | |||
| 1157 | (id->product == HID_ANY_ID || id->product == hdev->product); | 1157 | (id->product == HID_ANY_ID || id->product == hdev->product); |
| 1158 | } | 1158 | } |
| 1159 | 1159 | ||
| 1160 | static const struct hid_device_id *hid_match_id(struct hid_device *hdev, | 1160 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, |
| 1161 | const struct hid_device_id *id) | 1161 | const struct hid_device_id *id) |
| 1162 | { | 1162 | { |
| 1163 | for (; id->bus; id++) | 1163 | for (; id->bus; id++) |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index b108ce71583f..69dec476883a 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | #include <linux/hid.h> | 32 | #include <linux/hid.h> |
| 33 | #include <linux/hid-debug.h> | 33 | #include <linux/hid-debug.h> |
| 34 | 34 | ||
| 35 | #include "hid-ids.h" | ||
| 36 | |||
| 35 | #define unk KEY_UNKNOWN | 37 | #define unk KEY_UNKNOWN |
| 36 | 38 | ||
| 37 | static const unsigned char hid_keyboard[256] = { | 39 | static const unsigned char hid_keyboard[256] = { |
| @@ -280,6 +282,28 @@ static enum power_supply_property hidinput_battery_props[] = { | |||
| 280 | POWER_SUPPLY_PROP_STATUS | 282 | POWER_SUPPLY_PROP_STATUS |
| 281 | }; | 283 | }; |
| 282 | 284 | ||
| 285 | #define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */ | ||
| 286 | |||
| 287 | static const struct hid_device_id hid_battery_quirks[] = { | ||
| 288 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE), | ||
| 289 | HID_BATTERY_QUIRK_PERCENT }, | ||
| 290 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD), | ||
| 291 | HID_BATTERY_QUIRK_PERCENT }, | ||
| 292 | {} | ||
| 293 | }; | ||
| 294 | |||
| 295 | static unsigned find_battery_quirk(struct hid_device *hdev) | ||
| 296 | { | ||
| 297 | unsigned quirks = 0; | ||
| 298 | const struct hid_device_id *match; | ||
| 299 | |||
| 300 | match = hid_match_id(hdev, hid_battery_quirks); | ||
| 301 | if (match != NULL) | ||
| 302 | quirks = match->driver_data; | ||
| 303 | |||
| 304 | return quirks; | ||
| 305 | } | ||
| 306 | |||
| 283 | static int hidinput_get_battery_property(struct power_supply *psy, | 307 | static int hidinput_get_battery_property(struct power_supply *psy, |
| 284 | enum power_supply_property prop, | 308 | enum power_supply_property prop, |
| 285 | union power_supply_propval *val) | 309 | union power_supply_propval *val) |
| @@ -304,10 +328,11 @@ static int hidinput_get_battery_property(struct power_supply *psy, | |||
| 304 | break; | 328 | break; |
| 305 | } | 329 | } |
| 306 | 330 | ||
| 307 | /* store the returned value */ | 331 | if (dev->battery_min < dev->battery_max && |
| 308 | /* I'm not calculating this using the logical_minimum and maximum */ | 332 | buf[1] >= dev->battery_min && |
| 309 | /* because my device returns 0-100 even though the min and max are 0-255 */ | 333 | buf[1] <= dev->battery_max) |
| 310 | val->intval = buf[1]; | 334 | val->intval = (100 * (buf[1] - dev->battery_min)) / |
| 335 | (dev->battery_max - dev->battery_min); | ||
| 311 | break; | 336 | break; |
| 312 | 337 | ||
| 313 | case POWER_SUPPLY_PROP_MODEL_NAME: | 338 | case POWER_SUPPLY_PROP_MODEL_NAME: |
| @@ -330,6 +355,7 @@ static void hidinput_setup_battery(struct hid_device *dev, unsigned id, s32 min, | |||
| 330 | { | 355 | { |
| 331 | struct power_supply *battery = &dev->battery; | 356 | struct power_supply *battery = &dev->battery; |
| 332 | int ret; | 357 | int ret; |
| 358 | unsigned quirks; | ||
| 333 | 359 | ||
| 334 | if (battery->name != NULL) | 360 | if (battery->name != NULL) |
| 335 | return; /* already initialized? */ | 361 | return; /* already initialized? */ |
| @@ -344,6 +370,13 @@ static void hidinput_setup_battery(struct hid_device *dev, unsigned id, s32 min, | |||
| 344 | battery->use_for_apm = 0; | 370 | battery->use_for_apm = 0; |
| 345 | battery->get_property = hidinput_get_battery_property; | 371 | battery->get_property = hidinput_get_battery_property; |
| 346 | 372 | ||
| 373 | quirks = find_battery_quirk(dev); | ||
| 374 | |||
| 375 | if (quirks & HID_BATTERY_QUIRK_PERCENT) { | ||
| 376 | min = 0; | ||
| 377 | max = 100; | ||
| 378 | } | ||
| 379 | |||
| 347 | dev->battery_min = min; | 380 | dev->battery_min = min; |
| 348 | dev->battery_max = max; | 381 | dev->battery_max = max; |
| 349 | dev->battery_report_id = id; | 382 | dev->battery_report_id = id; |
diff --git a/include/linux/hid.h b/include/linux/hid.h index b5df198d87a5..fa772c86fa2c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -735,6 +735,8 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); | |||
| 735 | int hid_check_keys_pressed(struct hid_device *hid); | 735 | int hid_check_keys_pressed(struct hid_device *hid); |
| 736 | int hid_connect(struct hid_device *hid, unsigned int connect_mask); | 736 | int hid_connect(struct hid_device *hid, unsigned int connect_mask); |
| 737 | void hid_disconnect(struct hid_device *hid); | 737 | void hid_disconnect(struct hid_device *hid); |
| 738 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, | ||
| 739 | const struct hid_device_id *id); | ||
| 738 | 740 | ||
| 739 | /** | 741 | /** |
| 740 | * hid_map_usage - map usage input bits | 742 | * hid_map_usage - map usage input bits |
