Skip to content

Commit a78805e

Browse files
committed
[FROM-ML] HID: hid-lenovo-go: Add OS Mode Toggle
Adds OS Mode toggle, who's primary function is to change the built-in functional chords to use the right handle legion button instead of the left handle legion button as the mode shift key. This setting needs to be restored after resume, so a reset-resume hook is added. Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca> Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
1 parent c7dbf4d commit a78805e

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed

drivers/hid/hid-lenovo-go.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct hid_go_cfg {
7676
u32 mcu_version_product;
7777
u32 mcu_version_protocol;
7878
u32 mouse_dpi;
79+
u8 os_mode;
7980
u8 rgb_effect;
8081
u8 rgb_en;
8182
u8 rgb_mode;
@@ -166,6 +167,8 @@ enum feature_status_index {
166167
FEATURE_GAMEPAD_MODE = 0x0e,
167168
};
168169

170+
#define FEATURE_OS_MODE 0x69
171+
169172
enum fps_switch_status_index {
170173
FPS_STATUS_UNKNOWN,
171174
GAMEPAD,
@@ -311,6 +314,23 @@ enum device_status_index {
311314
GET_HOTKEY_TRIGG_STATUS,
312315
};
313316

317+
enum os_mode_cfg_index {
318+
SET_OS_MODE = 0x09,
319+
GET_OS_MODE,
320+
};
321+
322+
enum os_mode_type_index {
323+
OS_UNKNOWN,
324+
WINDOWS,
325+
LINUX,
326+
};
327+
328+
static const char *const os_mode_text[] = {
329+
[OS_UNKNOWN] = "unknown",
330+
[WINDOWS] = "windows",
331+
[LINUX] = "linux",
332+
};
333+
314334
static int hid_go_version_event(struct command_report *cmd_rep)
315335
{
316336
switch (cmd_rep->sub_cmd) {
@@ -593,6 +613,21 @@ static int hid_go_device_status_event(struct command_report *cmd_rep)
593613
}
594614
}
595615

616+
static int hid_go_os_mode_cfg_event(struct command_report *cmd_rep)
617+
{
618+
switch (cmd_rep->sub_cmd) {
619+
case SET_OS_MODE:
620+
if (cmd_rep->data[0] != 1)
621+
return -EIO;
622+
return 0;
623+
case GET_OS_MODE:
624+
drvdata.os_mode = cmd_rep->data[0];
625+
return 0;
626+
default:
627+
return -EINVAL;
628+
};
629+
}
630+
596631
static int hid_go_set_event_return(struct command_report *cmd_rep)
597632
{
598633
if (cmd_rep->data[0] != 0)
@@ -666,6 +701,9 @@ static int hid_go_raw_event(struct hid_device *hdev, struct hid_report *report,
666701
break;
667702
};
668703
break;
704+
case OS_MODE_DATA:
705+
ret = hid_go_os_mode_cfg_event(cmd_rep);
706+
break;
669707
default:
670708
goto passthrough;
671709
};
@@ -1338,6 +1376,64 @@ static ssize_t calibrate_config_options(struct device *dev,
13381376
return count;
13391377
}
13401378

1379+
static ssize_t os_mode_store(struct device *dev, struct device_attribute *attr,
1380+
const char *buf, size_t count)
1381+
{
1382+
size_t size = 1;
1383+
int ret;
1384+
u8 val;
1385+
1386+
ret = sysfs_match_string(os_mode_text, buf);
1387+
if (ret <= 0)
1388+
return ret;
1389+
1390+
val = ret;
1391+
ret = mcu_property_out(drvdata.hdev, OS_MODE_DATA, FEATURE_OS_MODE,
1392+
SET_OS_MODE, USB_MCU, &val, size);
1393+
if (ret < 0)
1394+
return ret;
1395+
1396+
drvdata.os_mode = val;
1397+
1398+
return count;
1399+
}
1400+
1401+
static ssize_t os_mode_show(struct device *dev, struct device_attribute *attr,
1402+
char *buf)
1403+
{
1404+
ssize_t count = 0;
1405+
int ret;
1406+
u8 i;
1407+
1408+
ret = mcu_property_out(drvdata.hdev, OS_MODE_DATA, FEATURE_OS_MODE,
1409+
GET_OS_MODE, USB_MCU, 0, 0);
1410+
if (ret)
1411+
return ret;
1412+
1413+
i = drvdata.os_mode;
1414+
if (i >= ARRAY_SIZE(os_mode_text))
1415+
return -EINVAL;
1416+
1417+
count = sysfs_emit(buf, "%s\n", os_mode_text[i]);
1418+
1419+
return count;
1420+
}
1421+
1422+
static ssize_t os_mode_index_show(struct device *dev,
1423+
struct device_attribute *attr, char *buf)
1424+
{
1425+
ssize_t count = 0;
1426+
unsigned int i;
1427+
1428+
for (i = 1; i < ARRAY_SIZE(os_mode_text); i++)
1429+
count += sysfs_emit_at(buf, count, "%s ", os_mode_text[i]);
1430+
1431+
if (count)
1432+
buf[count - 1] = '\n';
1433+
1434+
return count;
1435+
}
1436+
13411437
static int rgb_cfg_call(struct hid_device *hdev, enum mcu_command_index cmd,
13421438
enum rgb_config_index index, u8 *val, size_t size)
13431439
{
@@ -1704,6 +1800,9 @@ static DEVICE_ATTR_RO_NAMED(gamepad_rumble_intensity_index,
17041800
static DEVICE_ATTR_RW(fps_mode_dpi);
17051801
static DEVICE_ATTR_RO(fps_mode_dpi_index);
17061802

1803+
static DEVICE_ATTR_RW(os_mode);
1804+
static DEVICE_ATTR_RO(os_mode_index);
1805+
17071806
static struct attribute *mcu_attrs[] = {
17081807
&dev_attr_fps_mode_dpi.attr,
17091808
&dev_attr_fps_mode_dpi_index.attr,
@@ -1712,6 +1811,8 @@ static struct attribute *mcu_attrs[] = {
17121811
&dev_attr_gamepad_mode_index.attr,
17131812
&dev_attr_gamepad_rumble_intensity.attr,
17141813
&dev_attr_gamepad_rumble_intensity_index.attr,
1814+
&dev_attr_os_mode.attr,
1815+
&dev_attr_os_mode_index.attr,
17151816
&dev_attr_reset_mcu.attr,
17161817
&dev_attr_version_firmware_mcu.attr,
17171818
&dev_attr_version_gen_mcu.attr,
@@ -2177,6 +2278,27 @@ static void hid_go_cfg_remove(struct hid_device *hdev)
21772278
hid_set_drvdata(hdev, NULL);
21782279
}
21792280

2281+
static int hid_go_cfg_reset_resume(struct hid_device *hdev)
2282+
{
2283+
u8 os_mode = drvdata.os_mode;
2284+
int ret;
2285+
2286+
ret = mcu_property_out(drvdata.hdev, OS_MODE_DATA, FEATURE_OS_MODE,
2287+
SET_OS_MODE, USB_MCU, &os_mode, 1);
2288+
if (ret < 0)
2289+
return ret;
2290+
2291+
ret = mcu_property_out(drvdata.hdev, OS_MODE_DATA, FEATURE_OS_MODE,
2292+
GET_OS_MODE, USB_MCU, 0, 0);
2293+
if (ret < 0)
2294+
return ret;
2295+
2296+
if (drvdata.os_mode != os_mode)
2297+
return -ENODEV;
2298+
2299+
return 0;
2300+
}
2301+
21802302
static int hid_go_probe(struct hid_device *hdev, const struct hid_device_id *id)
21812303
{
21822304
int ret, ep;
@@ -2235,6 +2357,20 @@ static void hid_go_remove(struct hid_device *hdev)
22352357
}
22362358
}
22372359

2360+
static int hid_go_reset_resume(struct hid_device *hdev)
2361+
{
2362+
int ep = get_endpoint_address(hdev);
2363+
2364+
switch (ep) {
2365+
case GO_GP_INTF_IN:
2366+
return hid_go_cfg_reset_resume(hdev);
2367+
default:
2368+
break;
2369+
}
2370+
2371+
return 0;
2372+
}
2373+
22382374
static const struct hid_device_id hid_go_devices[] = {
22392375
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO,
22402376
USB_DEVICE_ID_LENOVO_LEGION_GO2_XINPUT) },
@@ -2254,6 +2390,7 @@ static struct hid_driver hid_lenovo_go = {
22542390
.probe = hid_go_probe,
22552391
.remove = hid_go_remove,
22562392
.raw_event = hid_go_raw_event,
2393+
.reset_resume = hid_go_reset_resume,
22572394
};
22582395
module_hid_driver(hid_lenovo_go);
22592396

0 commit comments

Comments
 (0)