mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
HID: hid-oxp: Add Vibration Intensity Attribute
Adds attribute for setting the rumble intensity level. This setting must be re-applied after the gamepad mode is set as doing so resets this to the default value. Reviewed-by: Zhouwang Huang <honjow311@gmail.com> Tested-by: Zhouwang Huang <honjow311@gmail.com> Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
committed by
Jiri Kosina
parent
e4c850a6e7
commit
99bde1dfe8
@@ -34,6 +34,7 @@ enum oxp_function_index {
|
||||
OXP_FID_GEN1_RGB_SET = 0x07,
|
||||
OXP_FID_GEN1_RGB_REPLY = 0x0f,
|
||||
OXP_FID_GEN2_TOGGLE_MODE = 0xb2,
|
||||
OXP_FID_GEN2_RUMBLE_SET = 0xb3,
|
||||
OXP_FID_GEN2_KEY_STATE = 0xb4,
|
||||
OXP_FID_GEN2_STATUS_EVENT = 0xb8,
|
||||
};
|
||||
@@ -181,6 +182,7 @@ static struct oxp_hid_cfg {
|
||||
struct mutex cfg_mutex; /*ensure single synchronous output report*/
|
||||
u8 rgb_brightness;
|
||||
u8 gamepad_mode;
|
||||
u8 rumble_intensity;
|
||||
u8 rgb_effect;
|
||||
u8 rgb_speed;
|
||||
u8 rgb_en;
|
||||
@@ -266,6 +268,11 @@ static const char *const oxp_rgb_effect_text[] = {
|
||||
[OXP_EFFECT_MONO_LIST] = "monocolor",
|
||||
};
|
||||
|
||||
enum oxp_rumble_side_index {
|
||||
OXP_RUMBLE_LEFT = 0x00,
|
||||
OXP_RUMBLE_RIGHT,
|
||||
};
|
||||
|
||||
struct oxp_gen_1_rgb_report {
|
||||
u8 report_id;
|
||||
u8 message_id;
|
||||
@@ -341,6 +348,7 @@ static int oxp_hid_raw_event_gen_1(struct hid_device *hdev,
|
||||
|
||||
static int oxp_gen_2_property_out(enum oxp_function_index fid, u8 *data, u8 data_size);
|
||||
static int oxp_set_buttons(void);
|
||||
static int oxp_rumble_intensity_set(u8 intensity);
|
||||
|
||||
static void oxp_mcu_init_fn(struct work_struct *work)
|
||||
{
|
||||
@@ -368,6 +376,12 @@ static void oxp_mcu_init_fn(struct work_struct *work)
|
||||
if (ret)
|
||||
dev_err(&drvdata.hdev->dev,
|
||||
"Error: Failed to set gamepad mode: %i\n", ret);
|
||||
|
||||
/* Set vibration level */
|
||||
ret = oxp_rumble_intensity_set(drvdata.rumble_intensity);
|
||||
if (ret)
|
||||
dev_err(&drvdata.hdev->dev,
|
||||
"Error: Failed to set rumble intensity: %i\n", ret);
|
||||
}
|
||||
|
||||
static int oxp_hid_raw_event_gen_2(struct hid_device *hdev,
|
||||
@@ -514,6 +528,14 @@ static ssize_t gamepad_mode_store(struct device *dev,
|
||||
|
||||
drvdata.gamepad_mode = data[0];
|
||||
|
||||
if (drvdata.gamepad_mode == OXP_GP_MODE_DEBUG)
|
||||
return count;
|
||||
|
||||
/* Re-apply rumble settings as switching gamepad mode will override */
|
||||
ret = oxp_rumble_intensity_set(drvdata.rumble_intensity);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -857,6 +879,59 @@ static ssize_t button_mapping_options_show(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR_RO(button_mapping_options);
|
||||
|
||||
static int oxp_rumble_intensity_set(u8 intensity)
|
||||
{
|
||||
u8 header[15] = { 0x02, 0x38, 0x02, 0xe3, 0x39, 0xe3, 0x39, 0xe3,
|
||||
0x39, 0x01, intensity, 0x05, 0xe3, 0x39, 0xe3 };
|
||||
u8 footer[9] = { 0x39, 0xe3, 0x39, 0xe3, 0xe3, 0x02, 0x04, 0x39, 0x39 };
|
||||
size_t footer_size = ARRAY_SIZE(footer);
|
||||
size_t header_size = ARRAY_SIZE(header);
|
||||
u8 data[59] = { 0x0 };
|
||||
size_t data_size = ARRAY_SIZE(data);
|
||||
|
||||
memcpy(data, header, header_size);
|
||||
memcpy(data + data_size - footer_size, footer, footer_size);
|
||||
|
||||
return oxp_gen_2_property_out(OXP_FID_GEN2_RUMBLE_SET, data, data_size);
|
||||
}
|
||||
|
||||
static ssize_t rumble_intensity_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
ret = kstrtou8(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val < 0 || val > 5)
|
||||
return -EINVAL;
|
||||
|
||||
ret = oxp_rumble_intensity_set(val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drvdata.rumble_intensity = val;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t rumble_intensity_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%i\n", drvdata.rumble_intensity);
|
||||
}
|
||||
static DEVICE_ATTR_RW(rumble_intensity);
|
||||
|
||||
static ssize_t rumble_intensity_range_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "0-5\n");
|
||||
}
|
||||
static DEVICE_ATTR_RO(rumble_intensity_range);
|
||||
|
||||
#define OXP_DEVICE_ATTR_RW(_name, _group) \
|
||||
static ssize_t _name##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
@@ -948,6 +1023,8 @@ static struct attribute *oxp_cfg_attrs[] = {
|
||||
&dev_attr_gamepad_mode.attr,
|
||||
&dev_attr_gamepad_mode_index.attr,
|
||||
&dev_attr_reset_buttons.attr,
|
||||
&dev_attr_rumble_intensity.attr,
|
||||
&dev_attr_rumble_intensity_range.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1422,6 +1499,7 @@ static int oxp_cfg_probe(struct hid_device *hdev, u16 up)
|
||||
INIT_DELAYED_WORK(&drvdata.oxp_btn_queue, oxp_btn_queue_fn);
|
||||
|
||||
drvdata.gamepad_mode = OXP_GP_MODE_XINPUT;
|
||||
drvdata.rumble_intensity = 5;
|
||||
|
||||
INIT_DELAYED_WORK(&drvdata.oxp_mcu_init, oxp_mcu_init_fn);
|
||||
mod_delayed_work(system_wq, &drvdata.oxp_mcu_init, msecs_to_jiffies(50));
|
||||
|
||||
Reference in New Issue
Block a user