Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: Kysona: Add periodic online check

This patch adds a periodic online check at the same interval the battery
status gets requested.
With this change the driver can detect when the mouse is turned off while
the dongle is still plugged in.

Tested with a Kysona M600 V-HUB Special Edition.

Signed-off-by: Lode Willems <me@lodewillems.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Lode Willems and committed by
Jiri Kosina
113521a4 5e06802b

+44 -2
+44 -2
drivers/hid/hid-kysona.c
··· 14 14 15 15 #define BATTERY_TIMEOUT_MS 5000 16 16 17 + #define ONLINE_REPORT_ID 3 17 18 #define BATTERY_REPORT_ID 4 18 19 19 20 struct kysona_drvdata { ··· 81 80 return ret; 82 81 } 83 82 83 + static const char kysona_online_request[] = { 84 + 0x08, ONLINE_REPORT_ID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a 86 + }; 87 + 84 88 static const char kysona_battery_request[] = { 85 89 0x08, BATTERY_REPORT_ID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49 87 91 }; 92 + 93 + static int kysona_m600_fetch_online(struct hid_device *hdev) 94 + { 95 + u8 *write_buf; 96 + int ret; 97 + 98 + /* Request online information */ 99 + write_buf = kmemdup(kysona_online_request, sizeof(kysona_online_request), GFP_KERNEL); 100 + if (!write_buf) 101 + return -ENOMEM; 102 + 103 + ret = hid_hw_raw_request(hdev, kysona_online_request[0], 104 + write_buf, sizeof(kysona_online_request), 105 + HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 106 + if (ret < (int)sizeof(kysona_online_request)) { 107 + hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret); 108 + ret = -ENODATA; 109 + } 110 + kfree(write_buf); 111 + return ret; 112 + } 113 + 114 + static void kysona_fetch_online(struct hid_device *hdev) 115 + { 116 + int ret = kysona_m600_fetch_online(hdev); 117 + 118 + if (ret < 0) 119 + hid_dbg(hdev, 120 + "Online query failed (err: %d)\n", ret); 121 + } 88 122 89 123 static int kysona_m600_fetch_battery(struct hid_device *hdev) 90 124 { ··· 157 121 struct kysona_drvdata, battery_work.work); 158 122 struct hid_device *hdev = drv_data->hdev; 159 123 124 + kysona_fetch_online(hdev); 160 125 kysona_fetch_battery(hdev); 161 126 schedule_delayed_work(&drv_data->battery_work, 162 127 msecs_to_jiffies(BATTERY_TIMEOUT_MS)); ··· 197 160 power_supply_powers(drv_data->battery, &hdev->dev); 198 161 199 162 INIT_DELAYED_WORK(&drv_data->battery_work, kysona_battery_timer_tick); 163 + kysona_fetch_online(hdev); 200 164 kysona_fetch_battery(hdev); 201 165 schedule_delayed_work(&drv_data->battery_work, 202 166 msecs_to_jiffies(BATTERY_TIMEOUT_MS)); ··· 244 206 { 245 207 struct kysona_drvdata *drv_data = hid_get_drvdata(hdev); 246 208 247 - if (drv_data->battery && size == sizeof(kysona_battery_request) && 209 + if (size == sizeof(kysona_online_request) && 210 + data[0] == 8 && data[1] == ONLINE_REPORT_ID) { 211 + drv_data->online = data[6]; 212 + } 213 + 214 + if (size == sizeof(kysona_battery_request) && 248 215 data[0] == 8 && data[1] == BATTERY_REPORT_ID) { 249 216 drv_data->battery_capacity = data[6]; 250 217 drv_data->battery_charging = data[7]; 251 218 drv_data->battery_voltage = (data[8] << 8) | data[9]; 252 - drv_data->online = true; 253 219 } 254 220 255 221 return 0;