@@ -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+
169172enum 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+
314334static 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+
596631static 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+
13411437static 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,
17041800static DEVICE_ATTR_RW (fps_mode_dpi );
17051801static DEVICE_ATTR_RO (fps_mode_dpi_index );
17061802
1803+ static DEVICE_ATTR_RW (os_mode );
1804+ static DEVICE_ATTR_RO (os_mode_index );
1805+
17071806static 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+
21802302static 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+
22382374static 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};
22582395module_hid_driver (hid_lenovo_go );
22592396
0 commit comments