--- v2
+++ v1
@@ -1,151 +1,65 @@
-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.
+Upload shared haptic affects for release and press waveforms if a device
+exposes them.
Signed-off-by: Angela Czubak <acz@semihalf.com>
---
- drivers/hid/hid-haptic.c | 71 +++++++++++++++++++++++++++++++++++++++-
- drivers/hid/hid-haptic.h | 18 ++++++++++
- 2 files changed, 88 insertions(+), 1 deletion(-)
+ drivers/hid/hid-haptic.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c
-index 64e354cb3f2e..4a5d5e7b92d1 100644
+index b66bde7475e4..ad458bc7d4c5 100644
--- a/drivers/hid/hid-haptic.c
+++ b/drivers/hid/hid-haptic.c
-@@ -50,8 +50,13 @@ EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping);
- bool hid_haptic_check_pressure_unit(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);
- return true;
+@@ -367,6 +367,7 @@ int hid_haptic_init(struct hid_device *hdev,
+ char *name;
+ int (*flush)(struct input_dev *dev, struct file *file);
+ int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
++ struct ff_effect release_effect, press_effect;
+
+ haptic->hdev = hdev;
+ haptic->max_waveform_id = max(2u, haptic->max_waveform_id);
+@@ -483,8 +484,41 @@ int hid_haptic_init(struct hid_device *hdev,
+ module_put(THIS_MODULE);
+ goto input_free;
+ }
++
++ effect_set_default(&release_effect);
++ if (haptic->release_ordinal_orig)
++ release_effect.u.hid.hid_usage = HID_HP_WAVEFORMRELEASE &
++ HID_USAGE;
++ ret = input_ff_upload(dev, &release_effect, (struct file *)UINTPTR_MAX);
++ if (ret || release_effect.id != HID_HAPTIC_RELEASE_EFFECT_ID) {
++ if (!ret) {
++ ret = -EBUSY;
++ input_ff_erase(dev, release_effect.id,
++ (struct file *)UINTPTR_MAX);
++ }
++ dev_err(&hdev->dev,
++ "Failed to allocate id 0 for release effect.\n");
++ goto input_free;
+ }
- return false;
- }
- EXPORT_SYMBOL_GPL(hid_haptic_check_pressure_unit);
-@@ -350,6 +355,12 @@ static void hid_haptic_destroy(struct ff_device *ff)
- module_put(THIS_MODULE);
- }
++ effect_set_default(&press_effect);
++ if (haptic->press_ordinal_orig)
++ press_effect.u.hid.hid_usage = HID_HP_WAVEFORMPRESS & HID_USAGE;
++ ret = input_ff_upload(dev, &press_effect, (struct file *)UINTPTR_MAX);
++ if (ret || press_effect.id != HID_HAPTIC_PRESS_EFFECT_ID) {
++ if (!ret) {
++ ret = -EBUSY;
++ input_ff_erase(dev, press_effect.id,
++ (struct file *)UINTPTR_MAX);
++ }
++ dev_err(&hdev->dev,
++ "Failed to allocate id 1 for press effect.\n");
++ goto release_free;
++ }
++
+ return 0;
-+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)
- {
-@@ -457,6 +468,13 @@ int hid_haptic_init(struct hid_device *hdev,
- fill_effect_buf(haptic, &stop_effect, &haptic->stop_effect,
- HID_HAPTIC_ORDINAL_WAVEFORMSTOP);
-
-+ haptic->mode = HID_HAPTIC_MODE_DEVICE;
-+ haptic->press_threshold = convert_force_to_logical(haptic,
-+ HID_HAPTIC_PRESS_THRESH);
-+ haptic->release_threshold = convert_force_to_logical(haptic,
-+ HID_HAPTIC_RELEASE_THRESH);
-+
-+
- input_set_capability(dev, EV_FF, FF_HID);
-
- flush = dev->flush;
-@@ -548,3 +566,54 @@ 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->pressure_sum > haptic->press_threshold)
-+ haptic->pressed_state = 1;
-+ else if (haptic->pressure_sum < 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->mode == HID_HAPTIC_MODE_KERNEL) {
-+ input_event(haptic->input_dev, EV_KEY, BTN_LEFT,
-+ haptic->pressed_state);
-+ input_event(haptic->input_dev, EV_ABS, ABS_PRESSURE,
-+ haptic->pressure_sum);
-+ return true;
-+ }
-+ return false;
-+}
-+EXPORT_SYMBOL_GPL(hid_haptic_handle_input);
-+
-+void hid_haptic_pressure_reset(struct hid_haptic_device *haptic)
-+{
-+ haptic->pressure_sum = 0;
-+}
-+EXPORT_SYMBOL_GPL(hid_haptic_pressure_reset);
-+
-+void hid_haptic_pressure_increase(struct hid_haptic_device *haptic,
-+ __s32 pressure)
-+{
-+ haptic->pressure_sum += pressure;
-+}
-+EXPORT_SYMBOL_GPL(hid_haptic_pressure_increase);
-diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h
-index e686f7ec42b9..586f20be0061 100644
---- a/drivers/hid/hid-haptic.h
-+++ b/drivers/hid/hid-haptic.h
-@@ -83,6 +83,11 @@ int hid_haptic_input_configured(struct hid_device *hdev,
- struct hid_haptic_device *haptic,
- struct hid_input *hi);
- 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_increase(struct hid_haptic_device *haptic,
-+ __s32 pressure);
- #else
- static inline
- void hid_haptic_feature_mapping(struct hid_device *hdev,
-@@ -117,4 +122,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_increase(struct hid_haptic_device *haptic,
-+ __s32 pressure)
-+{}
- #endif
++release_free:
++ input_ff_erase(dev, release_effect.id, (struct file *)UINTPTR_MAX);
+ input_free:
+ input_ff_destroy(dev);
+ /* Do not let double free happen, input_ff_destroy will call
--
-2.34.1.703.g22d0c6ccf7-goog
+2.34.1.307.g9b7440fafd-goog