linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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: Re: [PATCH RFC] hid-input: add support for HID devices reporting Battery Strength
Date: Fri, 02 Dec 2011 09:44:13 -0800	[thread overview]
Message-ID: <4ED90E6D.8090402@goop.org> (raw)
In-Reply-To: <CACo8zOd45i3EnCVMyJoDPP4bx2AnD9mEjDiC=bJKvmX=TWfXGg@mail.gmail.com>

On 12/01/2011 09:52 PM, Daniel Nicoletti wrote:
> I've sent an email earlier asking for help with a GetFeature code, and now I
> have a second patch on top of Jeremy's to provide the battery functionality
> for devices that support reporting it.
>
> If I understood correctly when talking to Jeremy he said his device
> never actually
> reported the status as an input event (sorry if I didn't understand it
> correctly),

No, it does.  When the mouse first connects it reports the battery level
as an Input event.  Without my patch, X sees the battery level as a
strange little absolute axis on the mouse, which it ignores.

I don't know if the mouse also reports the battery later on
spontaneously; I haven't observed it, so I suspect you may be right that
you have to poll it to get further updates.

>  and
> after reading HID specs I believe it's really because it was meant to be probed,
> I have an Apple Keyboard and Magic Trackpad both bluetooth batteries operated,
> so using PacketLogger I saw that Mac OSX always ask the battery status using
> the so called GetFeature.

Could you cite a specific reference?  I don't see any references to
"GetFeature" in HID spec I have.  The closest I see is
"Get_Report(INPUT/OUTPUT/FEATURE)", which specifically says "This
request is not intended to be used for polling the device state on a
regular basis".  Though I'm not at all surprised if device manufacturers
ignore this, or that it is contradictory with some other part of the spec.

> What my patch does is basically:
> - store the report id that matches the battery_strength
> - setup the battery if 0x6.0x20 is found, even if that is reported as a feature
>   (as it was meant to be but only the MagicTrackpad does)
> - when upower or someone access /sys/class/power_supply/hid-*/capacity it
>   will probe the device and return it's status.

How often does usermode read this file?  Does it/can it select on the
file to wait for changes.

Given that battery level shouldn't change that quickly, I wonder if
having a timer poll the device every minute or something of that order
might be useful?

>
> It works great for both devices, but I have two concerns:
> - the report_features function has a duplicated code

Yes, but that's easy to fix.

> - it would be nice if it was possible for specific drivers to provide their own
>   probe as there might be some strange devices... (but maybe it's
> already possible)
I'd wait until there's a device which can't be handled by this mechanism
before trying to generalize it.  Unless we can unify the wacom driver,
but that seems to be in its own little world.

> I've talked to the upower dev and he fixed it to be able to show the
> right percentage.

Cool, but I have some concerns about that (see below).

> Here how the uevent file (in /sys/class/power_supply/hid-*/) looks like:
> POWER_SUPPLY_NAME=hid-00:22:41:D9:18:E7-battery
> POWER_SUPPLY_PRESENT=1
> POWER_SUPPLY_ONLINE=1
> POWER_SUPPLY_CAPACITY=66
> POWER_SUPPLY_MODEL_NAME=MacAdmin’s keyboard
> POWER_SUPPLY_STATUS=Discharging
>
> POWER_SUPPLY_NAME=hid-70:CD:60:F5:FF:3F-battery
> POWER_SUPPLY_PRESENT=1
> POWER_SUPPLY_ONLINE=1
> POWER_SUPPLY_CAPACITY=62
> POWER_SUPPLY_MODEL_NAME=nexx’s Trackpad
> POWER_SUPPLY_STATUS=Discharging
>
> and the patch (note that this is my first kernel patch so sorry if
> formatting is not ok, should I attach it?):
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index b9b8c75..8fac47c 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -277,6 +277,7 @@ 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
>  };
>
>  static int hidinput_get_battery_property(struct power_supply *psy,
> @@ -285,6 +286,9 @@ static int hidinput_get_battery_property(struct
> power_supply *psy,
>  {
>  	struct hid_device *dev = container_of(psy, struct hid_device, battery);
>  	int ret = 0;
> +	int ret_rep;
> +	__u8 *buf = NULL;
> +	unsigned char report_number = dev->battery_report_id;
>
>  	switch (prop) {
>  	case POWER_SUPPLY_PROP_PRESENT:
> @@ -293,28 +297,45 @@ static int hidinput_get_battery_property(struct
> power_supply *psy,
>  		break;
>
>  	case POWER_SUPPLY_PROP_CAPACITY:
> -		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)) /
> -				(dev->battery_max - dev->battery_min);
> -		else
> +		buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL);

Why allocate a two byte buffer?  Why not just put it on the stack?  How
do you know that's the right size?

> +		if (!buf) {
> +			ret = -ENOMEM;
> +			break;
> +		}
> +
> +		memset(buf, 0, sizeof(buf));
> +		ret_rep = dev->hid_get_raw_report(dev, report_number, buf,
> sizeof(buf), HID_FEATURE_REPORT);
> +		if (ret_rep != 2) {
>  			ret = -EINVAL;
> +			break;
> +		}
> +
> +		/* store the returned value */
> +		/* I'm not calculating this using the logical_minimum and maximum */
> +		/* because my device returns 0-100 even though the min and max are 0-255 */
> +		val->intval = buf[1];

That's definitely not the case for my mouse.  I'm not sure what the
range actually is, but I've seen values reported > 100 with fresh
alkaline batteries.  Initially I also thought it was using a 0-100 range
despite the min/max, and I added a per-device quirk mechanism - but
since my device didn't need it, I did't include it in the patch
posting.  I'd reinstate it if there are devices that report 0-100.

>  		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;
>  	}
>
> +	if (buf) {
> +		kfree(buf);
> +	}
>  	return ret;
>  }
>
> -static void hidinput_setup_battery(struct hid_device *dev, s32 min, s32 max)
> +static void hidinput_setup_battery(struct hid_device *dev, unsigned
> id, s32 min, s32 max)
>  {
>  	struct power_supply *battery = &dev->battery;
>  	int ret;
> @@ -326,7 +347,7 @@ static void hidinput_setup_battery(struct
> hid_device *dev, s32 min, s32 max)
>  	if (battery->name == NULL)
>  		return;
>
> -	battery->type = POWER_SUPPLY_TYPE_BATTERY;
> +	battery->type = POWER_SUPPLY_TYPE_USB;

What's the purpose of this?  Is it to make upower behave in a
different/better way?  My reading is that this means that it's powered
by USB ("Standard Downstream Port").  A bluetooth device doesn't have
any USB involved at all (except if the BT adapter itself is USB, which
is moot).

If upower is getting confused thinking that a "battery" is necessarily a
laptop battery, then I think it needs to be fixed to pay closer
attention to the device tree topology.

(looks up upower) Ah, I see.

The changes in the current upower.git look very suspect to me, if
nothing else because of the hard-coded "magicmouse" and "wacom", and the
use of POWER_SUPPLY_TYPE_USB.  Can upower not look to see if there's a
power-supply hanging off a HID device and report that as peripheral power?

> -	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 */
> +				if (((rep->field[i]->usage + j)->hid & HID_USAGE_PAGE) ==
> HID_UP_GENDEVCTRLS &&
> +					((rep->field[i]->usage + j)->hid & HID_USAGE) == 0x20) {
> +					hidinput_setup_battery(hid,
> +							       rep->id,
> +							       rep->field[i]->logical_minimum,
> +							       rep->field[i]->logical_maximum);
> +				}
> +
> +				if (drv->feature_mapping)
> +					drv->feature_mapping(hid, rep->field[i],
> +							     rep->field[i]->usage + j);
> +			}
I'd be inclined to split all this out into a separate function, so that
you can make it common with the code on the input path.

    J
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2011-12-02 17:44 UTC|newest]

Thread overview: 45+ 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 [this message]
2011-12-02 18:29                       ` Daniel Nicoletti
2011-12-03  6:09                         ` Jeremy Fitzhardinge
2011-12-03  6:13                         ` [GIT PULL RFC] directly poll battery strength when reading power_supply Jeremy Fitzhardinge
2011-12-06  9:17                           ` 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 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=4ED90E6D.8090402@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).