55 * Copyright (c) 2023 Luke Jones <luke@ljones.dev>
66 */
77
8+ #include "linux/compiler_attributes.h"
89#include "linux/device.h"
910#include <linux/platform_data/x86/asus-wmi.h>
1011#include <linux/platform_device.h>
1112#include "linux/pm.h"
13+ #include "linux/printk.h"
1214#include "linux/slab.h"
1315#include <linux/hid.h>
1416#include <linux/types.h>
@@ -262,6 +264,17 @@ struct deadzone {
262264 u8 outer ;
263265};
264266
267+ struct response_curve {
268+ uint8_t move_pct_1 ;
269+ uint8_t response_pct_1 ;
270+ uint8_t move_pct_2 ;
271+ uint8_t response_pct_2 ;
272+ uint8_t move_pct_3 ;
273+ uint8_t response_pct_3 ;
274+ uint8_t move_pct_4 ;
275+ uint8_t response_pct_4 ;
276+ } __packed ;
277+
265278/* ROG Ally has many settings related to the gamepad, all using the same n-key endpoint */
266279struct ally_gamepad_cfg {
267280 struct hid_device * hdev ;
@@ -286,6 +299,9 @@ struct ally_gamepad_cfg {
286299 /* anti-deadzones */
287300 u8 ls_adz ; // left stick
288301 u8 rs_adz ; // right stick
302+ /* joystick response curves */
303+ struct response_curve ls_rc ;
304+ struct response_curve rs_rc ;
289305};
290306
291307/* The hatswitch outputs integers, we use them to index this X|Y pair */
@@ -720,10 +736,85 @@ static ssize_t axis_xy_right_anti_deadzone_store(struct device *dev,
720736}
721737ALLY_DEVICE_ATTR_RW (axis_xy_right_anti_deadzone , anti_deadzone );
722738
739+ /* JS RESPONSE CURVES *****************************************************************************/
740+ static void _gamepad_set_js_response_curves_default (struct ally_gamepad_cfg * ally_cfg )
741+ {
742+ struct response_curve * js1_rc = & ally_cfg -> ls_rc ;
743+ struct response_curve * js2_rc = & ally_cfg -> rs_rc ;
744+ js1_rc -> move_pct_1 = js2_rc -> move_pct_1 = 0x16 ; // 25%
745+ js1_rc -> move_pct_2 = js2_rc -> move_pct_2 = 0x32 ; // 50%
746+ js1_rc -> move_pct_3 = js2_rc -> move_pct_3 = 0x48 ; // 75%
747+ js1_rc -> move_pct_4 = js2_rc -> move_pct_4 = 0x64 ; // 100%
748+ js1_rc -> response_pct_1 = js2_rc -> response_pct_1 = 0x16 ;
749+ js1_rc -> response_pct_2 = js2_rc -> response_pct_2 = 0x32 ;
750+ js1_rc -> response_pct_3 = js2_rc -> response_pct_3 = 0x48 ;
751+ js1_rc -> response_pct_4 = js2_rc -> response_pct_4 = 0x64 ;
752+ }
753+
754+ static ssize_t _gamepad_apply_response_curves (struct hid_device * hdev ,
755+ struct ally_gamepad_cfg * ally_cfg )
756+ {
757+ u8 * hidbuf ;
758+ int ret ;
759+
760+ hidbuf = kzalloc (FEATURE_ROG_ALLY_REPORT_SIZE , GFP_KERNEL );
761+ if (!hidbuf )
762+ return - ENOMEM ;
763+
764+ hidbuf [0 ] = FEATURE_ROG_ALLY_REPORT_ID ;
765+ hidbuf [1 ] = FEATURE_ROG_ALLY_CODE_PAGE ;
766+ memcpy (& hidbuf [2 ], & ally_cfg -> ls_rc , sizeof (ally_cfg -> ls_rc ));
767+
768+ ret = ally_gamepad_check_ready (hdev );
769+ if (ret < 0 )
770+ goto report_fail ;
771+
772+ hidbuf [4 ] = 0x02 ;
773+ memcpy (& hidbuf [5 ], & ally_cfg -> rs_rc , sizeof (ally_cfg -> rs_rc ));
774+
775+ ret = ally_gamepad_check_ready (hdev );
776+ if (ret < 0 )
777+ goto report_fail ;
778+
779+ ret = asus_dev_set_report (hdev , hidbuf , FEATURE_ROG_ALLY_REPORT_SIZE );
780+ if (ret < 0 )
781+ goto report_fail ;
782+
783+ report_fail :
784+ kfree (hidbuf );
785+ return ret ;
786+ }
787+
788+ ALLY_JS_RC_POINT (axis_xy_left , move , 1 );
789+ ALLY_JS_RC_POINT (axis_xy_left , move , 2 );
790+ ALLY_JS_RC_POINT (axis_xy_left , move , 3 );
791+ ALLY_JS_RC_POINT (axis_xy_left , move , 4 );
792+ ALLY_JS_RC_POINT (axis_xy_left , response , 1 );
793+ ALLY_JS_RC_POINT (axis_xy_left , response , 2 );
794+ ALLY_JS_RC_POINT (axis_xy_left , response , 3 );
795+ ALLY_JS_RC_POINT (axis_xy_left , response , 4 );
796+
797+ ALLY_JS_RC_POINT (axis_xy_right , move , 1 );
798+ ALLY_JS_RC_POINT (axis_xy_right , move , 2 );
799+ ALLY_JS_RC_POINT (axis_xy_right , move , 3 );
800+ ALLY_JS_RC_POINT (axis_xy_right , move , 4 );
801+ ALLY_JS_RC_POINT (axis_xy_right , response , 1 );
802+ ALLY_JS_RC_POINT (axis_xy_right , response , 2 );
803+ ALLY_JS_RC_POINT (axis_xy_right , response , 3 );
804+ ALLY_JS_RC_POINT (axis_xy_right , response , 4 );
805+
723806static struct attribute * axis_xy_left_attrs [] = {
724807 & dev_attr_axis_xy_left_anti_deadzone .attr ,
725808 & dev_attr_axis_xy_left_deadzone .attr ,
726809 & dev_attr_axis_xyz_deadzone_index .attr ,
810+ & dev_attr_axis_xy_left_move_1 .attr ,
811+ & dev_attr_axis_xy_left_move_2 .attr ,
812+ & dev_attr_axis_xy_left_move_3 .attr ,
813+ & dev_attr_axis_xy_left_move_4 .attr ,
814+ & dev_attr_axis_xy_left_response_1 .attr ,
815+ & dev_attr_axis_xy_left_response_2 .attr ,
816+ & dev_attr_axis_xy_left_response_3 .attr ,
817+ & dev_attr_axis_xy_left_response_4 .attr ,
727818 NULL
728819};
729820static const struct attribute_group axis_xy_left_attr_group = {
@@ -735,6 +826,14 @@ static struct attribute *axis_xy_right_attrs[] = {
735826 & dev_attr_axis_xy_right_anti_deadzone .attr ,
736827 & dev_attr_axis_xy_right_deadzone .attr ,
737828 & dev_attr_axis_xyz_deadzone_index .attr ,
829+ & dev_attr_axis_xy_right_move_1 .attr ,
830+ & dev_attr_axis_xy_right_move_2 .attr ,
831+ & dev_attr_axis_xy_right_move_3 .attr ,
832+ & dev_attr_axis_xy_right_move_4 .attr ,
833+ & dev_attr_axis_xy_right_response_1 .attr ,
834+ & dev_attr_axis_xy_right_response_2 .attr ,
835+ & dev_attr_axis_xy_right_response_3 .attr ,
836+ & dev_attr_axis_xy_right_response_4 .attr ,
738837 NULL
739838};
740839static const struct attribute_group axis_xy_right_attr_group = {
@@ -930,6 +1029,9 @@ static ssize_t _gamepad_apply_all(struct hid_device *hdev, struct ally_gamepad_c
9301029 if (ret < 0 )
9311030 return ret ;
9321031 ret = _gamepad_apply_js_ADZ (hdev , ally_cfg );
1032+ if (ret < 0 )
1033+ return ret ;
1034+ ret = _gamepad_apply_response_curves (hdev , ally_cfg );
9331035 if (ret < 0 )
9341036 return ret ;
9351037
@@ -1177,6 +1279,7 @@ static struct ally_gamepad_cfg *ally_gamepad_cfg_create(struct hid_device *hdev)
11771279 ally_cfg -> vibration_intensity [1 ] = 0x64 ;
11781280 _gamepad_set_deadzones_default (ally_cfg );
11791281 _gamepad_set_anti_deadzones_default (ally_cfg );
1282+ _gamepad_set_js_response_curves_default (ally_cfg );
11801283
11811284 drvdata .gamepad_cfg = ally_cfg ; // Must asign before attr group setup
11821285 if (sysfs_create_groups (& hdev -> dev .kobj , gamepad_device_attr_groups )) {
0 commit comments