Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
fc590a35
Commit
fc590a35
authored
Feb 23, 2021
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-5.12/logitech' into for-linus
- support for "Unified Battery (1004) feature" from Filipe Laíns
parents
7eb275f9
4d300833
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
240 additions
and
8 deletions
+240
-8
drivers/hid/hid-lg-g15.c
drivers/hid/hid-lg-g15.c
+1
-1
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-logitech-hidpp.c
+239
-7
No files found.
drivers/hid/hid-lg-g15.c
View file @
fc590a35
...
...
@@ -647,7 +647,7 @@ static void lg_g15_input_close(struct input_dev *dev)
static
int
lg_g15_register_led
(
struct
lg_g15_data
*
g15
,
int
i
)
{
const
char
*
const
led_names
[]
=
{
static
const
char
*
const
led_names
[]
=
{
"g15::kbd_backlight"
,
"g15::lcd_backlight"
,
"g15::macro_preset1"
,
...
...
drivers/hid/hid-logitech-hidpp.c
View file @
fc590a35
...
...
@@ -92,6 +92,8 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_CAPABILITY_BATTERY_MILEAGE BIT(2)
#define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS BIT(3)
#define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4)
#define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5)
#define HIDPP_CAPABILITY_UNIFIED_BATTERY BIT(6)
#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
...
...
@@ -152,6 +154,7 @@ struct hidpp_battery {
int
voltage
;
int
charge_type
;
bool
online
;
u8
supported_levels_1004
;
};
/**
...
...
@@ -1171,7 +1174,7 @@ static int hidpp20_batterylevel_get_battery_info(struct hidpp_device *hidpp,
return
0
;
}
static
int
hidpp20_query_battery_info
(
struct
hidpp_device
*
hidpp
)
static
int
hidpp20_query_battery_info
_1000
(
struct
hidpp_device
*
hidpp
)
{
u8
feature_type
;
int
ret
;
...
...
@@ -1208,7 +1211,7 @@ static int hidpp20_query_battery_info(struct hidpp_device *hidpp)
return
0
;
}
static
int
hidpp20_battery_event
(
struct
hidpp_device
*
hidpp
,
static
int
hidpp20_battery_event
_1000
(
struct
hidpp_device
*
hidpp
,
u8
*
data
,
int
size
)
{
struct
hidpp_report
*
report
=
(
struct
hidpp_report
*
)
data
;
...
...
@@ -1380,6 +1383,224 @@ static int hidpp20_battery_voltage_event(struct hidpp_device *hidpp,
return
0
;
}
/* -------------------------------------------------------------------------- */
/* 0x1004: Unified battery */
/* -------------------------------------------------------------------------- */
#define HIDPP_PAGE_UNIFIED_BATTERY 0x1004
#define CMD_UNIFIED_BATTERY_GET_CAPABILITIES 0x00
#define CMD_UNIFIED_BATTERY_GET_STATUS 0x10
#define EVENT_UNIFIED_BATTERY_STATUS_EVENT 0x00
#define FLAG_UNIFIED_BATTERY_LEVEL_CRITICAL BIT(0)
#define FLAG_UNIFIED_BATTERY_LEVEL_LOW BIT(1)
#define FLAG_UNIFIED_BATTERY_LEVEL_GOOD BIT(2)
#define FLAG_UNIFIED_BATTERY_LEVEL_FULL BIT(3)
#define FLAG_UNIFIED_BATTERY_FLAGS_RECHARGEABLE BIT(0)
#define FLAG_UNIFIED_BATTERY_FLAGS_STATE_OF_CHARGE BIT(1)
static
int
hidpp20_unifiedbattery_get_capabilities
(
struct
hidpp_device
*
hidpp
,
u8
feature_index
)
{
struct
hidpp_report
response
;
int
ret
;
u8
*
params
=
(
u8
*
)
response
.
fap
.
params
;
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS
||
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_PERCENTAGE
)
{
/* we have already set the device capabilities, so let's skip */
return
0
;
}
ret
=
hidpp_send_fap_command_sync
(
hidpp
,
feature_index
,
CMD_UNIFIED_BATTERY_GET_CAPABILITIES
,
NULL
,
0
,
&
response
);
/* Ignore these intermittent errors */
if
(
ret
==
HIDPP_ERROR_RESOURCE_ERROR
)
return
-
EIO
;
if
(
ret
>
0
)
{
hid_err
(
hidpp
->
hid_dev
,
"%s: received protocol error 0x%02x
\n
"
,
__func__
,
ret
);
return
-
EPROTO
;
}
if
(
ret
)
return
ret
;
/*
* If the device supports state of charge (battery percentage) we won't
* export the battery level information. there are 4 possible battery
* levels and they all are optional, this means that the device might
* not support any of them, we are just better off with the battery
* percentage.
*/
if
(
params
[
1
]
&
FLAG_UNIFIED_BATTERY_FLAGS_STATE_OF_CHARGE
)
{
hidpp
->
capabilities
|=
HIDPP_CAPABILITY_BATTERY_PERCENTAGE
;
hidpp
->
battery
.
supported_levels_1004
=
0
;
}
else
{
hidpp
->
capabilities
|=
HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS
;
hidpp
->
battery
.
supported_levels_1004
=
params
[
0
];
}
return
0
;
}
static
int
hidpp20_unifiedbattery_map_status
(
struct
hidpp_device
*
hidpp
,
u8
charging_status
,
u8
external_power_status
)
{
int
status
;
switch
(
charging_status
)
{
case
0
:
/* discharging */
status
=
POWER_SUPPLY_STATUS_DISCHARGING
;
break
;
case
1
:
/* charging */
case
2
:
/* charging slow */
status
=
POWER_SUPPLY_STATUS_CHARGING
;
break
;
case
3
:
/* complete */
status
=
POWER_SUPPLY_STATUS_FULL
;
break
;
case
4
:
/* error */
status
=
POWER_SUPPLY_STATUS_NOT_CHARGING
;
hid_info
(
hidpp
->
hid_dev
,
"%s: charging error"
,
hidpp
->
name
);
break
;
default:
status
=
POWER_SUPPLY_STATUS_NOT_CHARGING
;
break
;
}
return
status
;
}
static
int
hidpp20_unifiedbattery_map_level
(
struct
hidpp_device
*
hidpp
,
u8
battery_level
)
{
/* cler unsupported level bits */
battery_level
&=
hidpp
->
battery
.
supported_levels_1004
;
if
(
battery_level
&
FLAG_UNIFIED_BATTERY_LEVEL_FULL
)
return
POWER_SUPPLY_CAPACITY_LEVEL_FULL
;
else
if
(
battery_level
&
FLAG_UNIFIED_BATTERY_LEVEL_GOOD
)
return
POWER_SUPPLY_CAPACITY_LEVEL_NORMAL
;
else
if
(
battery_level
&
FLAG_UNIFIED_BATTERY_LEVEL_LOW
)
return
POWER_SUPPLY_CAPACITY_LEVEL_LOW
;
else
if
(
battery_level
&
FLAG_UNIFIED_BATTERY_LEVEL_CRITICAL
)
return
POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL
;
return
POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN
;
}
static
int
hidpp20_unifiedbattery_get_status
(
struct
hidpp_device
*
hidpp
,
u8
feature_index
,
u8
*
state_of_charge
,
int
*
status
,
int
*
level
)
{
struct
hidpp_report
response
;
int
ret
;
u8
*
params
=
(
u8
*
)
response
.
fap
.
params
;
ret
=
hidpp_send_fap_command_sync
(
hidpp
,
feature_index
,
CMD_UNIFIED_BATTERY_GET_STATUS
,
NULL
,
0
,
&
response
);
/* Ignore these intermittent errors */
if
(
ret
==
HIDPP_ERROR_RESOURCE_ERROR
)
return
-
EIO
;
if
(
ret
>
0
)
{
hid_err
(
hidpp
->
hid_dev
,
"%s: received protocol error 0x%02x
\n
"
,
__func__
,
ret
);
return
-
EPROTO
;
}
if
(
ret
)
return
ret
;
*
state_of_charge
=
params
[
0
];
*
status
=
hidpp20_unifiedbattery_map_status
(
hidpp
,
params
[
2
],
params
[
3
]);
*
level
=
hidpp20_unifiedbattery_map_level
(
hidpp
,
params
[
1
]);
return
0
;
}
static
int
hidpp20_query_battery_info_1004
(
struct
hidpp_device
*
hidpp
)
{
u8
feature_type
;
int
ret
;
u8
state_of_charge
;
int
status
,
level
;
if
(
hidpp
->
battery
.
feature_index
==
0xff
)
{
ret
=
hidpp_root_get_feature
(
hidpp
,
HIDPP_PAGE_UNIFIED_BATTERY
,
&
hidpp
->
battery
.
feature_index
,
&
feature_type
);
if
(
ret
)
return
ret
;
}
ret
=
hidpp20_unifiedbattery_get_capabilities
(
hidpp
,
hidpp
->
battery
.
feature_index
);
if
(
ret
)
return
ret
;
ret
=
hidpp20_unifiedbattery_get_status
(
hidpp
,
hidpp
->
battery
.
feature_index
,
&
state_of_charge
,
&
status
,
&
level
);
if
(
ret
)
return
ret
;
hidpp
->
capabilities
|=
HIDPP_CAPABILITY_UNIFIED_BATTERY
;
hidpp
->
battery
.
capacity
=
state_of_charge
;
hidpp
->
battery
.
status
=
status
;
hidpp
->
battery
.
level
=
level
;
hidpp
->
battery
.
online
=
true
;
return
0
;
}
static
int
hidpp20_battery_event_1004
(
struct
hidpp_device
*
hidpp
,
u8
*
data
,
int
size
)
{
struct
hidpp_report
*
report
=
(
struct
hidpp_report
*
)
data
;
u8
*
params
=
(
u8
*
)
report
->
fap
.
params
;
int
state_of_charge
,
status
,
level
;
bool
changed
;
if
(
report
->
fap
.
feature_index
!=
hidpp
->
battery
.
feature_index
||
report
->
fap
.
funcindex_clientid
!=
EVENT_UNIFIED_BATTERY_STATUS_EVENT
)
return
0
;
state_of_charge
=
params
[
0
];
status
=
hidpp20_unifiedbattery_map_status
(
hidpp
,
params
[
2
],
params
[
3
]);
level
=
hidpp20_unifiedbattery_map_level
(
hidpp
,
params
[
1
]);
changed
=
status
!=
hidpp
->
battery
.
status
||
(
state_of_charge
!=
hidpp
->
battery
.
capacity
&&
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_PERCENTAGE
)
||
(
level
!=
hidpp
->
battery
.
level
&&
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS
);
if
(
changed
)
{
hidpp
->
battery
.
capacity
=
state_of_charge
;
hidpp
->
battery
.
status
=
status
;
hidpp
->
battery
.
level
=
level
;
if
(
hidpp
->
battery
.
ps
)
power_supply_changed
(
hidpp
->
battery
.
ps
);
}
return
0
;
}
/* -------------------------------------------------------------------------- */
/* Battery feature helpers */
/* -------------------------------------------------------------------------- */
static
enum
power_supply_property
hidpp_battery_props
[]
=
{
POWER_SUPPLY_PROP_ONLINE
,
POWER_SUPPLY_PROP_STATUS
,
...
...
@@ -3307,7 +3528,10 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
}
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_HIDPP20_BATTERY
)
{
ret
=
hidpp20_battery_event
(
hidpp
,
data
,
size
);
ret
=
hidpp20_battery_event_1000
(
hidpp
,
data
,
size
);
if
(
ret
!=
0
)
return
ret
;
ret
=
hidpp20_battery_event_1004
(
hidpp
,
data
,
size
);
if
(
ret
!=
0
)
return
ret
;
ret
=
hidpp_solar_battery_event
(
hidpp
,
data
,
size
);
...
...
@@ -3443,9 +3667,14 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
if
(
hidpp
->
quirks
&
HIDPP_QUIRK_CLASS_K750
)
ret
=
hidpp_solar_request_battery_event
(
hidpp
);
else
{
ret
=
hidpp20_query_battery_voltage_info
(
hidpp
);
/* we only support one battery feature right now, so let's
first check the ones that support battery level first
and leave voltage for last */
ret
=
hidpp20_query_battery_info_1000
(
hidpp
);
if
(
ret
)
ret
=
hidpp20_query_battery_info_1004
(
hidpp
);
if
(
ret
)
ret
=
hidpp20_query_battery_info
(
hidpp
);
ret
=
hidpp20_query_battery_
voltage_
info
(
hidpp
);
}
if
(
ret
)
...
...
@@ -3473,7 +3702,8 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
num_battery_props
=
ARRAY_SIZE
(
hidpp_battery_props
)
-
3
;
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_MILEAGE
)
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_MILEAGE
||
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_PERCENTAGE
)
battery_props
[
num_battery_props
++
]
=
POWER_SUPPLY_PROP_CAPACITY
;
...
...
@@ -3650,8 +3880,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
}
else
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_HIDPP20_BATTERY
)
{
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_BATTERY_VOLTAGE
)
hidpp20_query_battery_voltage_info
(
hidpp
);
else
if
(
hidpp
->
capabilities
&
HIDPP_CAPABILITY_UNIFIED_BATTERY
)
hidpp20_query_battery_info_1004
(
hidpp
);
else
hidpp20_query_battery_info
(
hidpp
);
hidpp20_query_battery_info
_1000
(
hidpp
);
}
if
(
hidpp
->
battery
.
ps
)
power_supply_changed
(
hidpp
->
battery
.
ps
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment