|
@@ -53,11 +53,13 @@ MODULE_LICENSE("GPL");
|
|
|
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
|
|
|
#define MT_QUIRK_NO_AREA (1 << 9)
|
|
|
#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
|
|
|
+#define MT_QUIRK_HOVERING (1 << 11)
|
|
|
|
|
|
struct mt_slot {
|
|
|
__s32 x, y, cx, cy, p, w, h;
|
|
|
__s32 contactid; /* the device ContactID assigned to this slot */
|
|
|
bool touch_state; /* is the touch valid? */
|
|
|
+ bool inrange_state; /* is the finger in proximity of the sensor? */
|
|
|
};
|
|
|
|
|
|
struct mt_class {
|
|
@@ -391,6 +393,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|
|
case HID_UP_DIGITIZER:
|
|
|
switch (usage->hid) {
|
|
|
case HID_DG_INRANGE:
|
|
|
+ if (cls->quirks & MT_QUIRK_HOVERING) {
|
|
|
+ hid_map_usage(hi, usage, bit, max,
|
|
|
+ EV_ABS, ABS_MT_DISTANCE);
|
|
|
+ input_set_abs_params(hi->input,
|
|
|
+ ABS_MT_DISTANCE, 0, 1, 0, 0);
|
|
|
+ }
|
|
|
mt_store_field(usage, td, hi);
|
|
|
td->last_field_index = field->index;
|
|
|
return 1;
|
|
@@ -520,9 +528,9 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
|
|
|
|
|
input_mt_slot(input, slotnum);
|
|
|
input_mt_report_slot_state(input, MT_TOOL_FINGER,
|
|
|
- s->touch_state);
|
|
|
- if (s->touch_state) {
|
|
|
- /* this finger is on the screen */
|
|
|
+ s->touch_state || s->inrange_state);
|
|
|
+ if (s->touch_state || s->inrange_state) {
|
|
|
+ /* this finger is in proximity of the sensor */
|
|
|
int wide = (s->w > s->h);
|
|
|
/* divided by two to match visual scale of touch */
|
|
|
int major = max(s->w, s->h) >> 1;
|
|
@@ -532,6 +540,8 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
|
|
input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
|
|
|
input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
|
|
|
input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
|
|
|
+ input_event(input, EV_ABS, ABS_MT_DISTANCE,
|
|
|
+ !s->touch_state);
|
|
|
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
|
|
|
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
|
|
|
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
|
|
@@ -564,6 +574,8 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
|
|
|
case HID_DG_INRANGE:
|
|
|
if (quirks & MT_QUIRK_VALID_IS_INRANGE)
|
|
|
td->curvalid = value;
|
|
|
+ if (quirks & MT_QUIRK_HOVERING)
|
|
|
+ td->curdata.inrange_state = value;
|
|
|
break;
|
|
|
case HID_DG_TIPSWITCH:
|
|
|
if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
|