From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Daniel Nicoletti <dantti12@gmail.com>
Cc: linux-input@vger.kernel.org, Jiri Kosina <jkosina@suse.cz>,
vojtech@ucw.cz, Przemo Firszt <przemo@firszt.eu>,
Richard Hughes <richard@hughsie.com>
Subject: [GIT PULL RFC] directly poll battery strength when reading power_supply
Date: Fri, 02 Dec 2011 22:13:12 -0800 [thread overview]
Message-ID: <4ED9BDF8.3010600@goop.org> (raw)
In-Reply-To: <CACo8zOcvKwr0wDkytvJfqyx4kV0ceYyCt+qnDqiSgxNywpzeHg@mail.gmail.com>
Hi,
This series of patches includes Daniel's patch to directly poll for the battery strength rather than
hoping the device will happen to send it, along with some cleanup patches from me.
The only functional change I made from Daniel's patch is keeping the power_supply type as BATTERY rather
than USB.
J
The following changes since commit 1b2bdc70c10f9bf1455ea76a558261d7431b533c:
hid-input: add support for HID devices reporting Battery Strength (2011-11-23 00:38:25 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git hid-battery
Daniel Nicoletti (1):
hid-input: add support for HID devices reporting Battery Strength
Jeremy Fitzhardinge (7):
hid-input: fix compile for !HID_BATTERY_STRENGTH
hid-input/battery: remove apparently redundant kmalloc
hid-input/battery: add quirks for battery
hid-input/battery: deal with both FEATURE and INPUT report batteries
hid-input/battery: make the battery setup common for INPUTs and FEATUREs
hid-input/battery: power-supply type really *is* a battery
hid-input/battery: remove battery_val
drivers/hid/hid-core.c | 2 +-
drivers/hid/hid-input.c | 105 +++++++++++++++++++++++++++++++++++------------
include/linux/hid.h | 5 ++-
3 files changed, 83 insertions(+), 29 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 848a56c..70f5192 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,
(id->product == HID_ANY_ID || id->product == hdev->product);
}
-static const struct hid_device_id *hid_match_id(struct hid_device *hdev,
+const struct hid_device_id *hid_match_id(struct hid_device *hdev,
const struct hid_device_id *id)
{
for (; id->bus; id++)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 83afb86..7360351 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -32,6 +32,8 @@
#include <linux/hid.h>
#include <linux/hid-debug.h>
+#include "hid-ids.h"
+
#define unk KEY_UNKNOWN
static const unsigned char hid_keyboard[256] = {
@@ -277,14 +279,39 @@ static enum power_supply_property hidinput_battery_props[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_STATUS
};
+#define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */
+
+static const struct hid_device_id hid_battery_quirks[] = {
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE),
+ HID_BATTERY_QUIRK_PERCENT },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD),
+ HID_BATTERY_QUIRK_PERCENT },
+ {}
+};
+
+static unsigned find_battery_quirk(struct hid_device *hdev)
+{
+ unsigned quirks = 0;
+ const struct hid_device_id *match;
+
+ match = hid_match_id(hdev, hid_battery_quirks);
+ if (match != NULL)
+ quirks = match->driver_data;
+
+ return quirks;
+}
+
static int hidinput_get_battery_property(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *val)
{
struct hid_device *dev = container_of(psy, struct hid_device, battery);
int ret = 0;
+ int ret_rep;
+ __u8 buf[2] = {};
switch (prop) {
case POWER_SUPPLY_PROP_PRESENT:
@@ -293,19 +320,29 @@ static int hidinput_get_battery_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CAPACITY:
+ ret_rep = dev->hid_get_raw_report(dev, dev->battery_report_id,
+ buf, sizeof(buf),
+ dev->battery_report_type);
+ if (ret_rep != 2) {
+ ret = -EINVAL;
+ break;
+ }
+
if (dev->battery_min < dev->battery_max &&
- dev->battery_val >= dev->battery_min &&
- dev->battery_val <= dev->battery_max)
- val->intval = (100 * (dev->battery_val - dev->battery_min)) /
+ buf[1] >= dev->battery_min &&
+ buf[1] <= dev->battery_max)
+ val->intval = (100 * (buf[1] - dev->battery_min)) /
(dev->battery_max - dev->battery_min);
- else
- ret = -EINVAL;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = dev->name;
break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+
default:
ret = -EINVAL;
break;
@@ -314,17 +351,22 @@ static int hidinput_get_battery_property(struct power_supply *psy,
return ret;
}
-static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
+static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field)
{
struct power_supply *battery = &dev->battery;
int ret;
+ unsigned quirks;
+ s32 min, max;
+
+ if (field->usage->hid != HID_DC_BATTERYSTRENGTH)
+ return false; /* no match */
if (battery->name != NULL)
- return; /* already initialized? */
+ goto out; /* already initialized? */
battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq);
if (battery->name == NULL)
- return;
+ goto out;
battery->type = POWER_SUPPLY_TYPE_BATTERY;
battery->properties = hidinput_battery_props;
@@ -332,8 +374,20 @@ static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
battery->use_for_apm = 0;
battery->get_property = hidinput_get_battery_property;
+ quirks = find_battery_quirk(dev);
+
+ min = field->logical_minimum;
+ max = field->logical_maximum;
+
+ if (quirks & HID_BATTERY_QUIRK_PERCENT) {
+ min = 0;
+ max = 100;
+ }
+
dev->battery_min = min;
dev->battery_max = max;
+ dev->battery_report_type = report_type;
+ dev->battery_report_id = field->report->id;
ret = power_supply_register(&dev->dev, battery);
if (ret != 0) {
@@ -341,6 +395,9 @@ static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
kfree(battery->name);
battery->name = NULL;
}
+
+out:
+ return true;
}
static void hidinput_cleanup_battery(struct hid_device *dev)
@@ -353,8 +410,10 @@ static void hidinput_cleanup_battery(struct hid_device *dev)
dev->battery.name = NULL;
}
#else /* !CONFIG_HID_BATTERY_STRENGTH */
-static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
+static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
+ struct hid_field *field)
{
+ return false;
}
static void hidinput_cleanup_battery(struct hid_device *dev)
@@ -721,12 +780,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_GENDEVCTRLS:
- if ((usage->hid & HID_USAGE) == 0x20) { /* Battery Strength */
- hidinput_setup_battery(device,
- field->logical_minimum,
- field->logical_maximum);
+ if (hidinput_setup_battery(device, HID_INPUT_REPORT, field))
goto ignore;
- } else
+ else
goto unknown;
break;
@@ -861,13 +917,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
input = field->hidinput->input;
- if (usage->hid == HID_DC_BATTERYSTRENGTH) {
- hid->battery_val = value;
- hid_dbg(hid, "battery value is %d (range %d-%d)\n",
- value, hid->battery_min, hid->battery_max);
- return;
- }
-
if (!usage->type)
return;
@@ -990,15 +1039,17 @@ static void report_features(struct hid_device *hid)
struct hid_report *rep;
int i, j;
- if (!drv->feature_mapping)
- return;
-
rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
list_for_each_entry(rep, &rep_enum->report_list, list)
for (i = 0; i < rep->maxfield; i++)
- for (j = 0; j < rep->field[i]->maxusage; j++)
- drv->feature_mapping(hid, rep->field[i],
- rep->field[i]->usage + j);
+ for (j = 0; j < rep->field[i]->maxusage; j++) {
+ /* Verify if Battery Strength feature is available */
+ hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
+
+ if (drv->feature_mapping)
+ drv->feature_mapping(hid, rep->field[i],
+ rep->field[i]->usage + j);
+ }
}
/*
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 214801d..49d116e 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -495,7 +495,8 @@ struct hid_device { /* device report descriptor */
struct power_supply battery;
__s32 battery_min;
__s32 battery_max;
- __s32 battery_val;
+ __s32 battery_report_type;
+ __s32 battery_report_id;
#endif
unsigned int status; /* see STAT flags above */
@@ -735,6 +736,8 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
int hid_check_keys_pressed(struct hid_device *hid);
int hid_connect(struct hid_device *hid, unsigned int connect_mask);
void hid_disconnect(struct hid_device *hid);
+const struct hid_device_id *hid_match_id(struct hid_device *hdev,
+ const struct hid_device_id *id);
/**
* hid_map_usage - map usage input bits
next prev parent reply other threads:[~2011-12-03 6:13 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-19 6:52 Supporting Battery Strength from my Bluetooth Mouse Jeremy Fitzhardinge
2011-11-19 11:18 ` Jiri Kosina
2011-11-19 21:34 ` Jeremy Fitzhardinge
2011-11-20 10:26 ` Jiri Kosina
2011-11-21 16:38 ` Jeremy Fitzhardinge
2011-11-21 17:36 ` Dmitry Torokhov
2011-11-21 17:49 ` Jeremy Fitzhardinge
2011-11-21 23:29 ` Jiri Kosina
2011-11-21 23:34 ` Jeremy Fitzhardinge
2011-11-22 0:03 ` Jiri Kosina
2011-11-23 8:49 ` [PATCH RFC] hid-input: add support for HID devices reporting Battery Strength Jeremy Fitzhardinge
2011-11-23 16:36 ` Chase Douglas
2011-11-23 21:07 ` Jeremy Fitzhardinge
2011-11-23 21:52 ` Przemo Firszt
2011-11-28 21:33 ` Jiri Kosina
2011-12-02 5:52 ` Daniel Nicoletti
2011-12-02 17:44 ` Jeremy Fitzhardinge
2011-12-02 18:29 ` Daniel Nicoletti
2011-12-03 6:09 ` Jeremy Fitzhardinge
2011-12-03 6:13 ` Jeremy Fitzhardinge [this message]
2011-12-06 9:17 ` [GIT PULL RFC] directly poll battery strength when reading power_supply Jiri Kosina
2011-12-08 1:56 ` Jeremy Fitzhardinge
2012-05-19 4:10 ` Daniel Nicoletti
2011-12-06 9:56 ` Richard Hughes
2011-12-06 17:10 ` Jeremy Fitzhardinge
2011-12-07 12:51 ` Richard Hughes
2011-12-07 17:25 ` Jeremy Fitzhardinge
2011-12-07 17:29 ` Richard Hughes
2011-12-07 17:36 ` Jeremy Fitzhardinge
2011-12-07 17:41 ` Richard Hughes
2011-12-08 1:41 ` [GIT PULL] power_supply: add power supply scope Jeremy Fitzhardinge
2011-12-08 1:41 ` Jeremy Fitzhardinge
2011-12-08 10:02 ` Anton Vorontsov
2011-12-08 10:05 ` Richard Hughes
2011-12-08 10:42 ` Anton Vorontsov
2011-12-08 10:41 ` Anton Vorontsov
2011-12-08 16:53 ` Jeremy Fitzhardinge
2011-12-08 23:36 ` Anton Vorontsov
2011-12-09 8:18 ` Jeremy Fitzhardinge
2011-12-09 9:59 ` Anton Vorontsov
2011-12-09 16:58 ` Jeremy Fitzhardinge
2011-12-09 10:17 ` Anton Vorontsov
2011-12-09 17:49 ` Jeremy Fitzhardinge
2011-12-09 20:00 ` Daniel Nicoletti
2011-12-09 20:36 ` Jeremy Fitzhardinge
2011-12-02 17:58 ` [PATCH RFC] hid-input: add support for HID devices reporting Battery Strength Jeremy Fitzhardinge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4ED9BDF8.3010600@goop.org \
--to=jeremy@goop.org \
--cc=dantti12@gmail.com \
--cc=jkosina@suse.cz \
--cc=linux-input@vger.kernel.org \
--cc=przemo@firszt.eu \
--cc=richard@hughsie.com \
--cc=vojtech@ucw.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.