Message ID | 20180403175220.GA148162@dtor-ws (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Dimitry, I reapplied the 3 commits I had to revert earlier and applied your patch. Have correct battery level reading on my BT mouse back! /sys/class/power_supply/hid-00:1f:20:fd:cb:be-battery# grep "" * capacity:53 grep: device: Is a directory model_name:Bluetooth Mouse M336/M337/M535 online:1 grep: power: Is a directory grep: powers: Is a directory present:1 scope:Device status:Discharging grep: subsystem: Is a directory type:Battery uevent:POWER_SUPPLY_NAME=hid-00:1f:20:fd:cb:be-battery uevent:POWER_SUPPLY_PRESENT=1 uevent:POWER_SUPPLY_ONLINE=1 uevent:POWER_SUPPLY_CAPACITY=53 uevent:POWER_SUPPLY_MODEL_NAME=Bluetooth Mouse M336/M337/M535 uevent:POWER_SUPPLY_STATUS=Discharging uevent:POWER_SUPPLY_SCOPE=Device rdesc file is attached Thx for the effort! Best regards, Martin van Es On Tuesday, April 3, 2018 7:52:20 PM CEST Dmitry Torokhov wrote: > The commit 581c4484769e ("HID: input: map digitizer battery usage") > assumed that devices having input (qas opposed to feature) report for > battery strength would report the data on their own, without the need to > be polled by the kernel; unfortunately it is not so. Many wireless mice > do not send unsolicited reports with battery strength data and have to > be polled explicitly. As a complication, stylus devices on digitizers > are not normally connected to the base and thus can not be polled - the > base can only determine battery strength in the stylus when it is in > proximity. > > To solve this issue, we add a special flag that tells the kernel > to avoid polling the device (and expect unsolicited reports) and set it > when report field with physical usage of digitizer stylus (HID_DG_STYLUS). > Unless this flag is set, and we have not seen the unsolicited reports, > the kernel will attempt to poll the device when userspace attempts to > read "capacity" and "state" attributes of power_supply object > corresponding to the devices battery. > > Fixes: 581c4484769e ("HID: input: map digitizer battery usage") > Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=198095 > Cc: stable@vger.kernel.org > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> > --- > > Martin, give this patch a try and reply with your name/email if you > want to be credited for reporting/testing. > > Thanks! > > drivers/hid/hid-input.c | 24 +++++++++++++++++------- > include/linux/hid.h | 9 ++++++++- > 2 files changed, 25 insertions(+), 8 deletions(-) > > diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c > index 6836a856c243..930652c25120 100644 > --- a/drivers/hid/hid-input.c > +++ b/drivers/hid/hid-input.c > @@ -387,7 +387,8 @@ static int hidinput_get_battery_property(struct > power_supply *psy, break; > > case POWER_SUPPLY_PROP_CAPACITY: > - if (dev->battery_report_type == HID_FEATURE_REPORT) { > + if (dev->battery_status != HID_BATTERY_REPORTED && > + !dev->battery_avoid_query) { > value = hidinput_query_battery_capacity(dev); > if (value < 0) > return value; > @@ -403,17 +404,17 @@ static int hidinput_get_battery_property(struct > power_supply *psy, break; > > case POWER_SUPPLY_PROP_STATUS: > - if (!dev->battery_reported && > - dev->battery_report_type == HID_FEATURE_REPORT) { > + if (dev->battery_status != HID_BATTERY_REPORTED && > + !dev->battery_avoid_query) { > value = hidinput_query_battery_capacity(dev); > if (value < 0) > return value; > > dev->battery_capacity = value; > - dev->battery_reported = true; > + dev->battery_status = HID_BATTERY_QUERIED; > } > > - if (!dev->battery_reported) > + if (dev->battery_status == HID_BATTERY_UNKNOWN) > val->intval = POWER_SUPPLY_STATUS_UNKNOWN; > else if (dev->battery_capacity == 100) > val->intval = POWER_SUPPLY_STATUS_FULL; > @@ -486,6 +487,14 @@ static int hidinput_setup_battery(struct hid_device > *dev, unsigned report_type, dev->battery_report_type = report_type; > dev->battery_report_id = field->report->id; > > + /* > + * Stylus is normally not connected to the device and thus we > + * can't query the device and get meaningful battery strength. > + * We have to wait for the device to report it on its own. > + */ > + dev->battery_avoid_query = report_type == HID_INPUT_REPORT && > + field->physical == HID_DG_STYLUS; > + > dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); > if (IS_ERR(dev->battery)) { > error = PTR_ERR(dev->battery); > @@ -530,9 +539,10 @@ static void hidinput_update_battery(struct hid_device > *dev, int value) > > capacity = hidinput_scale_battery_capacity(dev, value); > > - if (!dev->battery_reported || capacity != dev->battery_capacity) { > + if (dev->battery_status != HID_BATTERY_REPORTED || > + capacity != dev->battery_capacity) { > dev->battery_capacity = capacity; > - dev->battery_reported = true; > + dev->battery_status = HID_BATTERY_REPORTED; > power_supply_changed(dev->battery); > } > } > diff --git a/include/linux/hid.h b/include/linux/hid.h > index 8da3e1f48195..26240a22978a 100644 > --- a/include/linux/hid.h > +++ b/include/linux/hid.h > @@ -516,6 +516,12 @@ enum hid_type { > HID_TYPE_USBNONE > }; > > +enum hid_battery_status { > + HID_BATTERY_UNKNOWN = 0, > + HID_BATTERY_QUERIED, /* Kernel explicitly queried battery strength */ > + HID_BATTERY_REPORTED, /* Device sent unsolicited battery strength report > */ +}; > + > struct hid_driver; > struct hid_ll_driver; > > @@ -558,7 +564,8 @@ struct hid_device { /* device report descriptor */ > __s32 battery_max; > __s32 battery_report_type; > __s32 battery_report_id; > - bool battery_reported; > + enum hid_battery_status battery_status; > + bool battery_avoid_query; > #endif > > unsigned int status; /* see STAT flags above */ 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 08 15 00 25 01 75 01 95 08 81 02 05 01 09 30 09 31 16 01 f8 26 ff 07 75 0c 95 02 81 06 09 38 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 75 08 95 01 81 06 c0 c0 05 0c 09 01 a1 01 85 03 05 06 09 20 15 00 26 64 00 75 08 95 01 81 02 c0 06 00 ff 09 01 a1 01 85 10 75 08 95 06 15 00 26 ff 00 09 01 81 00 09 01 91 00 c0 06 00 ff 09 02 a1 01 85 11 75 08 95 13 15 00 26 ff 00 09 02 81 00 09 02 91 00 c0 05 01 09 06 a1 01 85 04 75 01 95 08 05 07 19 e0 29 e7 15 00 25 01 81 02 95 01 75 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 03 95 06 75 08 15 00 26 ff 00 05 07 19 00 29 ff 81 00 c0 05 0c 09 01 a1 01 85 05 15 00 25 01 75 01 95 02 0a 25 02 0a 24 02 81 02 95 01 75 06 81 03 c0 00 INPUT(2)[INPUT] Field(0) Physical(GenericDesktop.Pointer) Application(GenericDesktop.Mouse) Usage(8) Button.0001 Button.0002 Button.0003 Button.0004 Button.0005 Button.0006 Button.0007 Button.0008 Logical Minimum(0) Logical Maximum(1) Report Size(1) Report Count(8) Report Offset(0) Flags( Variable Absolute ) Field(1) Physical(GenericDesktop.Pointer) Application(GenericDesktop.Mouse) Usage(2) GenericDesktop.X GenericDesktop.Y Logical Minimum(-2047) Logical Maximum(2047) Report Size(12) Report Count(2) Report Offset(8) Flags( Variable Relative ) Field(2) Physical(GenericDesktop.Pointer) Application(GenericDesktop.Mouse) Usage(1) GenericDesktop.Wheel Logical Minimum(-127) Logical Maximum(127) Report Size(8) Report Count(1) Report Offset(32) Flags( Variable Relative ) Field(3) Physical(GenericDesktop.Pointer) Application(GenericDesktop.Mouse) Usage(1) Consumer.HorizontalWheel Logical Minimum(-127) Logical Maximum(127) Report Size(8) Report Count(1) Report Offset(40) Flags( Variable Relative ) INPUT(3)[INPUT] Field(0) Application(Consumer.0001) Usage(1) GenericDeviceControls.BatteryStrength Logical Minimum(0) Logical Maximum(100) Report Size(8) Report Count(1) Report Offset(0) Flags( Variable Absolute ) INPUT(16)[INPUT] Field(0) Application(ff00.0001) Usage(6) ff00.0001 ff00.0001 ff00.0001 ff00.0001 ff00.0001 ff00.0001 Logical Minimum(0) Logical Maximum(255) Report Size(8) Report Count(6) Report Offset(0) Flags( Array Absolute ) INPUT(17)[INPUT] Field(0) Application(ff00.0002) Usage(19) ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 Logical Minimum(0) Logical Maximum(255) Report Size(8) Report Count(19) Report Offset(0) Flags( Array Absolute ) INPUT(4)[INPUT] Field(0) Application(GenericDesktop.Keyboard) Usage(8) Keyboard.00e0 Keyboard.00e1 Keyboard.00e2 Keyboard.00e3 Keyboard.00e4 Keyboard.00e5 Keyboard.00e6 Keyboard.00e7 Logical Minimum(0) Logical Maximum(1) Report Size(1) Report Count(8) Report Offset(0) Flags( Variable Absolute ) Field(1) Application(GenericDesktop.Keyboard) Usage(256) Keyboard.0000 Keyboard.0001 Keyboard.0002 Keyboard.0003 Keyboard.0004 Keyboard.0005 Keyboard.0006 Keyboard.0007 Keyboard.0008 Keyboard.0009 Keyboard.000a Keyboard.000b Keyboard.000c Keyboard.000d Keyboard.000e Keyboard.000f Keyboard.0010 Keyboard.0011 Keyboard.0012 Keyboard.0013 Keyboard.0014 Keyboard.0015 Keyboard.0016 Keyboard.0017 Keyboard.0018 Keyboard.0019 Keyboard.001a Keyboard.001b Keyboard.001c Keyboard.001d Keyboard.001e Keyboard.001f Keyboard.0020 Keyboard.0021 Keyboard.0022 Keyboard.0023 Keyboard.0024 Keyboard.0025 Keyboard.0026 Keyboard.0027 Keyboard.0028 Keyboard.0029 Keyboard.002a Keyboard.002b Keyboard.002c Keyboard.002d Keyboard.002e Keyboard.002f Keyboard.0030 Keyboard.0031 Keyboard.0032 Keyboard.0033 Keyboard.0034 Keyboard.0035 Keyboard.0036 Keyboard.0037 Keyboard.0038 Keyboard.0039 Keyboard.003a Keyboard.003b Keyboard.003c Keyboard.003d Keyboard.003e Keyboard.003f Keyboard.0040 Keyboard.0041 Keyboard.0042 Keyboard.0043 Keyboard.0044 Keyboard.0045 Keyboard.0046 Keyboard.0047 Keyboard.0048 Keyboard.0049 Keyboard.004a Keyboard.004b Keyboard.004c Keyboard.004d Keyboard.004e Keyboard.004f Keyboard.0050 Keyboard.0051 Keyboard.0052 Keyboard.0053 Keyboard.0054 Keyboard.0055 Keyboard.0056 Keyboard.0057 Keyboard.0058 Keyboard.0059 Keyboard.005a Keyboard.005b Keyboard.005c Keyboard.005d Keyboard.005e Keyboard.005f Keyboard.0060 Keyboard.0061 Keyboard.0062 Keyboard.0063 Keyboard.0064 Keyboard.0065 Keyboard.0066 Keyboard.0067 Keyboard.0068 Keyboard.0069 Keyboard.006a Keyboard.006b Keyboard.006c Keyboard.006d Keyboard.006e Keyboard.006f Keyboard.0070 Keyboard.0071 Keyboard.0072 Keyboard.0073 Keyboard.0074 Keyboard.0075 Keyboard.0076 Keyboard.0077 Keyboard.0078 Keyboard.0079 Keyboard.007a Keyboard.007b Keyboard.007c Keyboard.007d Keyboard.007e Keyboard.007f Keyboard.0080 Keyboard.0081 Keyboard.0082 Keyboard.0083 Keyboard.0084 Keyboard.0085 Keyboard.0086 Keyboard.0087 Keyboard.0088 Keyboard.0089 Keyboard.008a Keyboard.008b Keyboard.008c Keyboard.008d Keyboard.008e Keyboard.008f Keyboard.0090 Keyboard.0091 Keyboard.0092 Keyboard.0093 Keyboard.0094 Keyboard.0095 Keyboard.0096 Keyboard.0097 Keyboard.0098 Keyboard.0099 Keyboard.009a Keyboard.009b Keyboard.009c Keyboard.009d Keyboard.009e Keyboard.009f Keyboard.00a0 Keyboard.00a1 Keyboard.00a2 Keyboard.00a3 Keyboard.00a4 Keyboard.00a5 Keyboard.00a6 Keyboard.00a7 Keyboard.00a8 Keyboard.00a9 Keyboard.00aa Keyboard.00ab Keyboard.00ac Keyboard.00ad Keyboard.00ae Keyboard.00af Keyboard.00b0 Keyboard.00b1 Keyboard.00b2 Keyboard.00b3 Keyboard.00b4 Keyboard.00b5 Keyboard.00b6 Keyboard.00b7 Keyboard.00b8 Keyboard.00b9 Keyboard.00ba Keyboard.00bb Keyboard.00bc Keyboard.00bd Keyboard.00be Keyboard.00bf Keyboard.00c0 Keyboard.00c1 Keyboard.00c2 Keyboard.00c3 Keyboard.00c4 Keyboard.00c5 Keyboard.00c6 Keyboard.00c7 Keyboard.00c8 Keyboard.00c9 Keyboard.00ca Keyboard.00cb Keyboard.00cc Keyboard.00cd Keyboard.00ce Keyboard.00cf Keyboard.00d0 Keyboard.00d1 Keyboard.00d2 Keyboard.00d3 Keyboard.00d4 Keyboard.00d5 Keyboard.00d6 Keyboard.00d7 Keyboard.00d8 Keyboard.00d9 Keyboard.00da Keyboard.00db Keyboard.00dc Keyboard.00dd Keyboard.00de Keyboard.00df Keyboard.00e0 Keyboard.00e1 Keyboard.00e2 Keyboard.00e3 Keyboard.00e4 Keyboard.00e5 Keyboard.00e6 Keyboard.00e7 Keyboard.00e8 Keyboard.00e9 Keyboard.00ea Keyboard.00eb Keyboard.00ec Keyboard.00ed Keyboard.00ee Keyboard.00ef Keyboard.00f0 Keyboard.00f1 Keyboard.00f2 Keyboard.00f3 Keyboard.00f4 Keyboard.00f5 Keyboard.00f6 Keyboard.00f7 Keyboard.00f8 Keyboard.00f9 Keyboard.00fa Keyboard.00fb Keyboard.00fc Keyboard.00fd Keyboard.00fe Keyboard.00ff Logical Minimum(0) Logical Maximum(255) Report Size(8) Report Count(6) Report Offset(16) Flags( Array Absolute ) INPUT(5)[INPUT] Field(0) Application(Consumer.0001) Usage(2) Consumer.0225 Consumer.0224 Logical Minimum(0) Logical Maximum(1) Report Size(1) Report Count(2) Report Offset(0) Flags( Variable Absolute ) OUTPUT(16)[OUTPUT] Field(0) Application(ff00.0001) Usage(6) ff00.0001 ff00.0001 ff00.0001 ff00.0001 ff00.0001 ff00.0001 Logical Minimum(0) Logical Maximum(255) Report Size(8) Report Count(6) Report Offset(0) Flags( Array Absolute ) OUTPUT(17)[OUTPUT] Field(0) Application(ff00.0002) Usage(19) ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 ff00.0002 Logical Minimum(0) Logical Maximum(255) Report Size(8) Report Count(19) Report Offset(0) Flags( Array Absolute ) OUTPUT(4)[OUTPUT] Field(0) Application(GenericDesktop.Keyboard) Usage(5) LED.NumLock LED.CapsLock LED.ScrollLock LED.Compose LED.Kana Logical Minimum(0) Logical Maximum(1) Report Size(1) Report Count(5) Report Offset(0) Flags( Variable Absolute ) Button.0001 ---> Key.LeftBtn Button.0002 ---> Key.RightBtn Button.0003 ---> Key.MiddleBtn Button.0004 ---> Key.SideBtn Button.0005 ---> Key.ExtraBtn Button.0006 ---> Key.ForwardBtn Button.0007 ---> Key.BackBtn Button.0008 ---> Key.TaskBtn GenericDesktop.X ---> Relative.X GenericDesktop.Y ---> Relative.Y GenericDesktop.Wheel ---> Relative.Wheel Consumer.HorizontalWheel ---> Relative.HWheel GenericDeviceControls.BatteryStrength ---> Power.? ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report Keyboard.00e0 ---> Key.LeftControl Keyboard.00e1 ---> Key.LeftShift Keyboard.00e2 ---> Key.LeftAlt Keyboard.00e3 ---> Key.LeftMeta Keyboard.00e4 ---> Key.RightCtrl Keyboard.00e5 ---> Key.RightShift Keyboard.00e6 ---> Key.RightAlt Keyboard.00e7 ---> Key.RightMeta Keyboard.0000 ---> Sync.Report Keyboard.0001 ---> Sync.Report Keyboard.0002 ---> Sync.Report Keyboard.0003 ---> Sync.Report Keyboard.0004 ---> Key.A Keyboard.0005 ---> Key.B Keyboard.0006 ---> Key.C Keyboard.0007 ---> Key.D Keyboard.0008 ---> Key.E Keyboard.0009 ---> Key.F Keyboard.000a ---> Key.G Keyboard.000b ---> Key.H Keyboard.000c ---> Key.I Keyboard.000d ---> Key.J Keyboard.000e ---> Key.K Keyboard.000f ---> Key.L Keyboard.0010 ---> Key.M Keyboard.0011 ---> Key.N Keyboard.0012 ---> Key.O Keyboard.0013 ---> Key.P Keyboard.0014 ---> Key.Q Keyboard.0015 ---> Key.R Keyboard.0016 ---> Key.S Keyboard.0017 ---> Key.T Keyboard.0018 ---> Key.U Keyboard.0019 ---> Key.V Keyboard.001a ---> Key.W Keyboard.001b ---> Key.X Keyboard.001c ---> Key.Y Keyboard.001d ---> Key.Z Keyboard.001e ---> Key.1 Keyboard.001f ---> Key.2 Keyboard.0020 ---> Key.3 Keyboard.0021 ---> Key.4 Keyboard.0022 ---> Key.5 Keyboard.0023 ---> Key.6 Keyboard.0024 ---> Key.7 Keyboard.0025 ---> Key.8 Keyboard.0026 ---> Key.9 Keyboard.0027 ---> Key.0 Keyboard.0028 ---> Key.Enter Keyboard.0029 ---> Key.Esc Keyboard.002a ---> Key.Backspace Keyboard.002b ---> Key.Tab Keyboard.002c ---> Key.Space Keyboard.002d ---> Key.Minus Keyboard.002e ---> Key.Equal Keyboard.002f ---> Key.LeftBrace Keyboard.0030 ---> Key.RightBrace Keyboard.0031 ---> Key.BackSlash Keyboard.0032 ---> Key.BackSlash Keyboard.0033 ---> Key.Semicolon Keyboard.0034 ---> Key.Apostrophe Keyboard.0035 ---> Key.Grave Keyboard.0036 ---> Key.Comma Keyboard.0037 ---> Key.Dot Keyboard.0038 ---> Key.Slash Keyboard.0039 ---> Key.CapsLock Keyboard.003a ---> Key.F1 Keyboard.003b ---> Key.F2 Keyboard.003c ---> Key.F3 Keyboard.003d ---> Key.F4 Keyboard.003e ---> Key.F5 Keyboard.003f ---> Key.F6 Keyboard.0040 ---> Key.F7 Keyboard.0041 ---> Key.F8 Keyboard.0042 ---> Key.F9 Keyboard.0043 ---> Key.F10 Keyboard.0044 ---> Key.F11 Keyboard.0045 ---> Key.F12 Keyboard.0046 ---> Key.SysRq Keyboard.0047 ---> Key.ScrollLock Keyboard.0048 ---> Key.Pause Keyboard.0049 ---> Key.Insert Keyboard.004a ---> Key.Home Keyboard.004b ---> Key.PageUp Keyboard.004c ---> Key.Delete Keyboard.004d ---> Key.End Keyboard.004e ---> Key.PageDown Keyboard.004f ---> Key.Right Keyboard.0050 ---> Key.Left Keyboard.0051 ---> Key.Down Keyboard.0052 ---> Key.Up Keyboard.0053 ---> Key.NumLock Keyboard.0054 ---> Key.KPSlash Keyboard.0055 ---> Key.KPAsterisk Keyboard.0056 ---> Key.KPMinus Keyboard.0057 ---> Key.KPPlus Keyboard.0058 ---> Key.KPEnter Keyboard.0059 ---> Key.KP1 Keyboard.005a ---> Key.KP2 Keyboard.005b ---> Key.KP3 Keyboard.005c ---> Key.KP4 Keyboard.005d ---> Key.KP5 Keyboard.005e ---> Key.KP6 Keyboard.005f ---> Key.KP7 Keyboard.0060 ---> Key.KP8 Keyboard.0061 ---> Key.KP9 Keyboard.0062 ---> Key.KP0 Keyboard.0063 ---> Key.KPDot Keyboard.0064 ---> Key.102nd Keyboard.0065 ---> Key.Compose Keyboard.0066 ---> Key.Power Keyboard.0067 ---> Key.KPEqual Keyboard.0068 ---> Key.F13 Keyboard.0069 ---> Key.F14 Keyboard.006a ---> Key.F15 Keyboard.006b ---> Key.F16 Keyboard.006c ---> Key.F17 Keyboard.006d ---> Key.F18 Keyboard.006e ---> Key.F19 Keyboard.006f ---> Key.F20 Keyboard.0070 ---> Key.F21 Keyboard.0071 ---> Key.F22 Keyboard.0072 ---> Key.F23 Keyboard.0073 ---> Key.F24 Keyboard.0074 ---> Key.Open Keyboard.0075 ---> Key.Help Keyboard.0076 ---> Key.Props Keyboard.0077 ---> Key.Front Keyboard.0078 ---> Key.Stop Keyboard.0079 ---> Key.Again Keyboard.007a ---> Key.Undo Keyboard.007b ---> Key.Cut Keyboard.007c ---> Key.Copy Keyboard.007d ---> Key.Paste Keyboard.007e ---> Key.Find Keyboard.007f ---> Key.Mute Keyboard.0080 ---> Key.VolumeUp Keyboard.0081 ---> Key.VolumeDown Keyboard.0082 ---> Key.Unknown Keyboard.0083 ---> Key.Unknown Keyboard.0084 ---> Key.Unknown Keyboard.0085 ---> Key.KPComma Keyboard.0086 ---> Key.Unknown Keyboard.0087 ---> Key.RO Keyboard.0088 ---> Key.Katakana/Hiragana Keyboard.0089 ---> Key.Yen Keyboard.008a ---> Key.Henkan Keyboard.008b ---> Key.Muhenkan Keyboard.008c ---> Key.KPJpComma Keyboard.008d ---> Key.Unknown Keyboard.008e ---> Key.Unknown Keyboard.008f ---> Key.Unknown Keyboard.0090 ---> Key.Hangeul Keyboard.0091 ---> Key.Hanja Keyboard.0092 ---> Key.Katakana Keyboard.0093 ---> Key.HIRAGANA Keyboard.0094 ---> Key.Zenkaku/Hankaku Keyboard.0095 ---> Key.Unknown Keyboard.0096 ---> Key.Unknown Keyboard.0097 ---> Key.Unknown Keyboard.0098 ---> Key.Unknown Keyboard.0099 ---> Key.Unknown Keyboard.009a ---> Key.Unknown Keyboard.009b ---> Key.Unknown Keyboard.009c ---> Key.Delete Keyboard.009d ---> Key.Unknown Keyboard.009e ---> Key.Unknown Keyboard.009f ---> Key.Unknown Keyboard.00a0 ---> Key.Unknown Keyboard.00a1 ---> Key.Unknown Keyboard.00a2 ---> Key.Unknown Keyboard.00a3 ---> Key.Unknown Keyboard.00a4 ---> Key.Unknown Keyboard.00a5 ---> Key.Unknown Keyboard.00a6 ---> Key.Unknown Keyboard.00a7 ---> Key.Unknown Keyboard.00a8 ---> Key.Unknown Keyboard.00a9 ---> Key.Unknown Keyboard.00aa ---> Key.Unknown Keyboard.00ab ---> Key.Unknown Keyboard.00ac ---> Key.Unknown Keyboard.00ad ---> Key.Unknown Keyboard.00ae ---> Key.Unknown Keyboard.00af ---> Key.Unknown Keyboard.00b0 ---> Key.Unknown Keyboard.00b1 ---> Key.Unknown Keyboard.00b2 ---> Key.Unknown Keyboard.00b3 ---> Key.Unknown Keyboard.00b4 ---> Key.Unknown Keyboard.00b5 ---> Key.Unknown Keyboard.00b6 ---> Key.KPLeftParenthesis Keyboard.00b7 ---> Key.KPRightParenthesis Keyboard.00b8 ---> Key.Unknown Keyboard.00b9 ---> Key.Unknown Keyboard.00ba ---> Key.Unknown Keyboard.00bb ---> Key.Unknown Keyboard.00bc ---> Key.Unknown Keyboard.00bd ---> Key.Unknown Keyboard.00be ---> Key.Unknown Keyboard.00bf ---> Key.Unknown Keyboard.00c0 ---> Key.Unknown Keyboard.00c1 ---> Key.Unknown Keyboard.00c2 ---> Key.Unknown Keyboard.00c3 ---> Key.Unknown Keyboard.00c4 ---> Key.Unknown Keyboard.00c5 ---> Key.Unknown Keyboard.00c6 ---> Key.Unknown Keyboard.00c7 ---> Key.Unknown Keyboard.00c8 ---> Key.Unknown Keyboard.00c9 ---> Key.Unknown Keyboard.00ca ---> Key.Unknown Keyboard.00cb ---> Key.Unknown Keyboard.00cc ---> Key.Unknown Keyboard.00cd ---> Key.Unknown Keyboard.00ce ---> Key.Unknown Keyboard.00cf ---> Key.Unknown Keyboard.00d0 ---> Key.Unknown Keyboard.00d1 ---> Key.Unknown Keyboard.00d2 ---> Key.Unknown Keyboard.00d3 ---> Key.Unknown Keyboard.00d4 ---> Key.Unknown Keyboard.00d5 ---> Key.Unknown Keyboard.00d6 ---> Key.Unknown Keyboard.00d7 ---> Key.Unknown Keyboard.00d8 ---> Key.Delete Keyboard.00d9 ---> Key.Unknown Keyboard.00da ---> Key.Unknown Keyboard.00db ---> Key.Unknown Keyboard.00dc ---> Key.Unknown Keyboard.00dd ---> Key.Unknown Keyboard.00de ---> Key.Unknown Keyboard.00df ---> Key.Unknown Keyboard.00e0 ---> Key.LeftControl Keyboard.00e1 ---> Key.LeftShift Keyboard.00e2 ---> Key.LeftAlt Keyboard.00e3 ---> Key.LeftMeta Keyboard.00e4 ---> Key.RightCtrl Keyboard.00e5 ---> Key.RightShift Keyboard.00e6 ---> Key.RightAlt Keyboard.00e7 ---> Key.RightMeta Keyboard.00e8 ---> Key.PlayPause Keyboard.00e9 ---> Key.StopCD Keyboard.00ea ---> Key.PreviousSong Keyboard.00eb ---> Key.NextSong Keyboard.00ec ---> Key.EjectCD Keyboard.00ed ---> Key.VolumeUp Keyboard.00ee ---> Key.VolumeDown Keyboard.00ef ---> Key.Mute Keyboard.00f0 ---> Key.WWW Keyboard.00f1 ---> Key.Back Keyboard.00f2 ---> Key.Forward Keyboard.00f3 ---> Key.Stop Keyboard.00f4 ---> Key.Find Keyboard.00f5 ---> Key.ScrollUp Keyboard.00f6 ---> Key.ScrollDown Keyboard.00f7 ---> Key.Edit Keyboard.00f8 ---> Key.Sleep Keyboard.00f9 ---> Key.Coffee Keyboard.00fa ---> Key.Refresh Keyboard.00fb ---> Key.Calc Keyboard.00fc ---> Key.Unknown Keyboard.00fd ---> Key.Unknown Keyboard.00fe ---> Key.Unknown Keyboard.00ff ---> Key.Unknown Consumer.0225 ---> Key.Forward Consumer.0224 ---> Key.Back ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0001 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report ff00.0002 ---> Sync.Report LED.NumLock ---> LED.NumLock LED.CapsLock ---> LED.CapsLock LED.ScrollLock ---> LED.ScrollLock LED.Compose ---> LED.Compose LED.Kana ---> LED.Kana
On Tue, 3 Apr 2018, Martin van Es wrote: > Hi Dimitry, > > I reapplied the 3 commits I had to revert earlier and applied your patch. Have > correct battery level reading on my BT mouse back! > > /sys/class/power_supply/hid-00:1f:20:fd:cb:be-battery# grep "" * > capacity:53 > grep: device: Is a directory > model_name:Bluetooth Mouse M336/M337/M535 > online:1 > grep: power: Is a directory > grep: powers: Is a directory > present:1 > scope:Device > status:Discharging > grep: subsystem: Is a directory > type:Battery > uevent:POWER_SUPPLY_NAME=hid-00:1f:20:fd:cb:be-battery > uevent:POWER_SUPPLY_PRESENT=1 > uevent:POWER_SUPPLY_ONLINE=1 > uevent:POWER_SUPPLY_CAPACITY=53 > uevent:POWER_SUPPLY_MODEL_NAME=Bluetooth Mouse M336/M337/M535 > uevent:POWER_SUPPLY_STATUS=Discharging > uevent:POWER_SUPPLY_SCOPE=Device > > rdesc file is attached > > Thx for the effort! Can I add your Tested-by: while applying the commit? Thanks,
On Wednesday, April 4, 2018 10:33:16 AM CEST Jiri Kosina wrote:
> Can I add your Tested-by: while applying the commit?
That's ok.
Best regards,
Martin
--
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
On Wed, Apr 4, 2018 at 1:51 AM, Martin van Es <martin@mrvanes.com> wrote: > > On Wednesday, April 4, 2018 10:33:16 AM CEST Jiri Kosina wrote: > > Can I add your Tested-by: while applying the commit? > > That's ok. Martin is also the reporter of the issue, I did not put down his name because I wasn't sure if he wanted it there. Thanks.
On Tue, 3 Apr 2018, Dmitry Torokhov wrote: > The commit 581c4484769e ("HID: input: map digitizer battery usage") > assumed that devices having input (qas opposed to feature) report for > battery strength would report the data on their own, without the need to > be polled by the kernel; unfortunately it is not so. Many wireless mice > do not send unsolicited reports with battery strength data and have to > be polled explicitly. As a complication, stylus devices on digitizers > are not normally connected to the base and thus can not be polled - the > base can only determine battery strength in the stylus when it is in > proximity. > > To solve this issue, we add a special flag that tells the kernel > to avoid polling the device (and expect unsolicited reports) and set it > when report field with physical usage of digitizer stylus (HID_DG_STYLUS). > Unless this flag is set, and we have not seen the unsolicited reports, > the kernel will attempt to poll the device when userspace attempts to > read "capacity" and "state" attributes of power_supply object > corresponding to the devices battery. > > Fixes: 581c4484769e ("HID: input: map digitizer battery usage") > Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=198095 > Cc: stable@vger.kernel.org > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Applied for 4.17, thanks.
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6836a856c243..930652c25120 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -387,7 +387,8 @@ static int hidinput_get_battery_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CAPACITY: - if (dev->battery_report_type == HID_FEATURE_REPORT) { + if (dev->battery_status != HID_BATTERY_REPORTED && + !dev->battery_avoid_query) { value = hidinput_query_battery_capacity(dev); if (value < 0) return value; @@ -403,17 +404,17 @@ static int hidinput_get_battery_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_STATUS: - if (!dev->battery_reported && - dev->battery_report_type == HID_FEATURE_REPORT) { + if (dev->battery_status != HID_BATTERY_REPORTED && + !dev->battery_avoid_query) { value = hidinput_query_battery_capacity(dev); if (value < 0) return value; dev->battery_capacity = value; - dev->battery_reported = true; + dev->battery_status = HID_BATTERY_QUERIED; } - if (!dev->battery_reported) + if (dev->battery_status == HID_BATTERY_UNKNOWN) val->intval = POWER_SUPPLY_STATUS_UNKNOWN; else if (dev->battery_capacity == 100) val->intval = POWER_SUPPLY_STATUS_FULL; @@ -486,6 +487,14 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, dev->battery_report_type = report_type; dev->battery_report_id = field->report->id; + /* + * Stylus is normally not connected to the device and thus we + * can't query the device and get meaningful battery strength. + * We have to wait for the device to report it on its own. + */ + dev->battery_avoid_query = report_type == HID_INPUT_REPORT && + field->physical == HID_DG_STYLUS; + dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); if (IS_ERR(dev->battery)) { error = PTR_ERR(dev->battery); @@ -530,9 +539,10 @@ static void hidinput_update_battery(struct hid_device *dev, int value) capacity = hidinput_scale_battery_capacity(dev, value); - if (!dev->battery_reported || capacity != dev->battery_capacity) { + if (dev->battery_status != HID_BATTERY_REPORTED || + capacity != dev->battery_capacity) { dev->battery_capacity = capacity; - dev->battery_reported = true; + dev->battery_status = HID_BATTERY_REPORTED; power_supply_changed(dev->battery); } } diff --git a/include/linux/hid.h b/include/linux/hid.h index 8da3e1f48195..26240a22978a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -516,6 +516,12 @@ enum hid_type { HID_TYPE_USBNONE }; +enum hid_battery_status { + HID_BATTERY_UNKNOWN = 0, + HID_BATTERY_QUERIED, /* Kernel explicitly queried battery strength */ + HID_BATTERY_REPORTED, /* Device sent unsolicited battery strength report */ +}; + struct hid_driver; struct hid_ll_driver; @@ -558,7 +564,8 @@ struct hid_device { /* device report descriptor */ __s32 battery_max; __s32 battery_report_type; __s32 battery_report_id; - bool battery_reported; + enum hid_battery_status battery_status; + bool battery_avoid_query; #endif unsigned int status; /* see STAT flags above */
The commit 581c4484769e ("HID: input: map digitizer battery usage") assumed that devices having input (qas opposed to feature) report for battery strength would report the data on their own, without the need to be polled by the kernel; unfortunately it is not so. Many wireless mice do not send unsolicited reports with battery strength data and have to be polled explicitly. As a complication, stylus devices on digitizers are not normally connected to the base and thus can not be polled - the base can only determine battery strength in the stylus when it is in proximity. To solve this issue, we add a special flag that tells the kernel to avoid polling the device (and expect unsolicited reports) and set it when report field with physical usage of digitizer stylus (HID_DG_STYLUS). Unless this flag is set, and we have not seen the unsolicited reports, the kernel will attempt to poll the device when userspace attempts to read "capacity" and "state" attributes of power_supply object corresponding to the devices battery. Fixes: 581c4484769e ("HID: input: map digitizer battery usage") Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=198095 Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> --- Martin, give this patch a try and reply with your name/email if you want to be credited for reporting/testing. Thanks! drivers/hid/hid-input.c | 24 +++++++++++++++++------- include/linux/hid.h | 9 ++++++++- 2 files changed, 25 insertions(+), 8 deletions(-)