@@ -50,8 +50,13 @@ EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping);
bool hid_haptic_is_forcepad(struct hid_haptic_device *haptic,
struct hid_input *hi, struct hid_field *field)
{
- if (field->unit == HID_UNIT_GRAM || field->unit == HID_UNIT_NEWTON)
+ if (field->unit == HID_UNIT_GRAM || field->unit == HID_UNIT_NEWTON) {
+ haptic->force_logical_minimum = field->logical_minimum;
+ haptic->force_physical_minimum = field->physical_minimum;
+ haptic->force_resolution = input_abs_get_res(hi->input,
+ ABS_MT_PRESSURE);
haptic->is_forcepad = true;
+ }
return haptic->is_forcepad;
}
EXPORT_SYMBOL_GPL(hid_haptic_is_forcepad);
@@ -346,6 +351,12 @@ static void hid_haptic_destroy(struct ff_device *ff)
module_put(THIS_MODULE);
}
+static u32 convert_force_to_logical(struct hid_haptic_device *haptic, u32 value)
+{
+ return (value - haptic->force_physical_minimum) *
+ haptic->force_resolution + haptic->force_logical_minimum;
+}
+
int hid_haptic_init(struct hid_device *hdev,
struct hid_haptic_device **haptic_ptr)
{
@@ -479,9 +490,16 @@ int hid_haptic_init(struct hid_device *hdev,
goto input_free;
}
+ haptic->mode = HID_HAPTIC_MODE_DEVICE;
+
if (!haptic->is_forcepad)
goto exit;
+ haptic->press_threshold = convert_force_to_logical(haptic,
+ HID_HAPTIC_PRESS_THRESH);
+ haptic->release_threshold = convert_force_to_logical(haptic,
+ HID_HAPTIC_RELEASE_THRESH);
+
effect_set_default(&release_effect);
if (haptic->release_ordinal_orig)
release_effect.u.hid.hid_usage = HID_HP_WAVEFORMRELEASE &
@@ -547,3 +565,56 @@ int hid_haptic_init(struct hid_device *hdev,
return ret;
}
EXPORT_SYMBOL_GPL(hid_haptic_init);
+
+void hid_haptic_handle_press_release(struct hid_haptic_device *haptic)
+{
+ int prev_pressed_state = haptic->pressed_state;
+ struct input_dev *input = haptic->input_dev;
+ unsigned long flags;
+
+ if (!haptic->is_forcepad)
+ return;
+
+ if (haptic->pressure > haptic->press_threshold)
+ haptic->pressed_state = 1;
+ else if (haptic->pressure < haptic->release_threshold)
+ haptic->pressed_state = 0;
+ if (!prev_pressed_state && haptic->pressed_state &&
+ haptic->mode == HID_HAPTIC_MODE_KERNEL) {
+ spin_lock_irqsave(&input->event_lock, flags);
+ input->ff->playback(input, PRESS_HID_EFFECT_ID, 1);
+ spin_unlock_irqrestore(&input->event_lock, flags);
+ }
+ if (prev_pressed_state && !haptic->pressed_state &&
+ haptic->mode == HID_HAPTIC_MODE_KERNEL) {
+ spin_lock_irqsave(&input->event_lock, flags);
+ input->ff->playback(input, RELEASE_HID_EFFECT_ID, 1);
+ spin_unlock_irqrestore(&input->event_lock, flags);
+ }
+}
+EXPORT_SYMBOL_GPL(hid_haptic_handle_press_release);
+
+bool hid_haptic_handle_input(struct hid_haptic_device *haptic)
+{
+ if (haptic->is_forcepad && haptic->mode == HID_HAPTIC_MODE_KERNEL) {
+ input_event(haptic->input_dev, EV_KEY, BTN_LEFT,
+ haptic->pressed_state);
+ return true;
+ }
+ return false;
+}
+EXPORT_SYMBOL_GPL(hid_haptic_handle_input);
+
+void hid_haptic_pressure_reset(struct hid_haptic_device *haptic)
+{
+ haptic->pressure = 0;
+}
+EXPORT_SYMBOL_GPL(hid_haptic_pressure_reset);
+
+void hid_haptic_pressure_update(struct hid_haptic_device *haptic,
+ __s32 pressure)
+{
+ if (pressure > haptic->pressure)
+ haptic->pressure = pressure;
+}
+EXPORT_SYMBOL_GPL(hid_haptic_pressure_update);
@@ -83,6 +83,11 @@ int hid_haptic_input_mapping(struct hid_device *hdev,
bool hid_haptic_input_configured(struct hid_device *hdev,
struct hid_haptic_device *haptic);
int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr);
+void hid_haptic_handle_press_release(struct hid_haptic_device *haptic);
+bool hid_haptic_handle_input(struct hid_haptic_device *haptic);
+void hid_haptic_pressure_reset(struct hid_haptic_device *haptic);
+void hid_haptic_pressure_update(struct hid_haptic_device *haptic,
+ __s32 pressure);
#else
static inline
void hid_haptic_feature_mapping(struct hid_device *hdev,
@@ -116,4 +121,17 @@ int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_p
{
return 0;
}
+static inline
+void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) {}
+static inline
+bool hid_haptic_handle_input(struct hid_haptic_device *haptic)
+{
+ return false;
+}
+static inline
+void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) {}
+static inline
+void hid_haptic_pressure_update(struct hid_haptic_device *haptic,
+ __s32 pressure)
+{}
#endif
Implement hid_haptic_handle_press_release() which generates haptic feedback as well as saves the pressed state of the haptic device. Function hid_haptic_handle_input() inserts BTN_LEFT and ABS_PRESSURE events if the device is in kernel mode. Add functions to increase and reset the state of the pressure detected by the device. Signed-off-by: Angela Czubak <acz@semihalf.com> --- drivers/hid/hid-haptic.c | 73 +++++++++++++++++++++++++++++++++++++++- drivers/hid/hid-haptic.h | 18 ++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-)