@@ -51,8 +51,13 @@ bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic,
struct hid_input *hi, struct hid_field *field)
{
/* Accepted units are either grams or newtons. */
- if (field->unit == 0x0101 || field->unit == 0xe111)
+ if (field->unit == 0x0101 || field->unit == 0xe111) {
+ 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;
+ }
return false;
}
EXPORT_SYMBOL_GPL(hid_haptic_check_pressure_unit);
@@ -352,6 +357,13 @@ 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)
{
@@ -459,6 +471,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;
@@ -550,3 +569,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);
@@ -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,19 @@ 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
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 | 72 +++++++++++++++++++++++++++++++++++++++- drivers/hid/hid-haptic.h | 20 +++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-)