The orientation of the touching ellipse. The value should describe a signed
quarter of a revolution clockwise around the touch center. The signed value
range is arbitrary, but zero should be returned for an ellipse aligned with
- the Y axis of the surface, a negative value when the ellipse is turned to
- the left, and a positive value when the ellipse is turned to the
- right. When completely aligned with the X axis, the range max should be
- returned.
+ the Y axis (north) of the surface, a negative value when the ellipse is
+ turned to the left, and a positive value when the ellipse is turned to the
+ right. When aligned with the X axis in the positive direction, the range
+ max should be returned; when aligned with the X axis in the negative
+ direction, the range -max should be returned.
Touch ellipsis are symmetrical by default. For devices capable of true 360
degree orientation, the reported orientation must exceed the range max to
#define MT_IO_FLAGS_PENDING_SLOTS 2
struct mt_slot {
- __s32 x, y, cx, cy, p, w, h;
+ __s32 x, y, cx, cy, p, w, h, a;
__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? */
bool confidence_state; /* is the touch made by a finger? */
+ bool has_azimuth; /* the contact reports azimuth */
};
struct mt_class {
if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
cls->sn_height);
- input_set_abs_params(hi->input,
- ABS_MT_ORIENTATION, 0, 1, 0, 0);
+
+ /*
+ * Only set ABS_MT_ORIENTATION if it is not
+ * already set by the HID_DG_AZIMUTH usage.
+ */
+ if (!test_bit(ABS_MT_ORIENTATION,
+ hi->input->absbit))
+ input_set_abs_params(hi->input,
+ ABS_MT_ORIENTATION, 0, 1, 0, 0);
}
mt_store_field(usage, td, hi);
return 1;
td->cc_index = field->index;
td->cc_value_index = usage->usage_index;
return 1;
+ case HID_DG_AZIMUTH:
+ hid_map_usage(hi, usage, bit, max,
+ EV_ABS, ABS_MT_ORIENTATION);
+ /*
+ * Azimuth has the range of [0, MAX) representing a full
+ * revolution. Set ABS_MT_ORIENTATION to a quarter of
+ * MAX according the definition of ABS_MT_ORIENTATION
+ */
+ input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+ -field->logical_maximum / 4,
+ field->logical_maximum / 4,
+ cls->sn_move ?
+ field->logical_maximum / cls->sn_move : 0, 0);
+ mt_store_field(usage, td, hi);
+ return 1;
case HID_DG_CONTACTMAX:
/* we don't set td->last_slot_field as contactcount and
* contact max are global to the report */
int wide = (s->w > s->h);
int major = max(s->w, s->h);
int minor = min(s->w, s->h);
+ int orientation = wide;
+
+ if (s->has_azimuth)
+ orientation = s->a;
/*
* divided by two to match visual scale of touch
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_ORIENTATION,
+ orientation);
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
break;
case HID_DG_CONTACTCOUNT:
break;
+ case HID_DG_AZIMUTH:
+ /*
+ * Azimuth is counter-clockwise and ranges from [0, MAX)
+ * (a full revolution). Convert it to clockwise ranging
+ * [-MAX/2, MAX/2].
+ *
+ * Note that ABS_MT_ORIENTATION require us to report
+ * the limit of [-MAX/4, MAX/4], but the value can go
+ * out of range to [-MAX/2, MAX/2] to report an upside
+ * down ellipsis.
+ */
+ if (value > field->logical_maximum / 2)
+ value -= field->logical_maximum;
+ td->curdata.a = -value;
+ td->curdata.has_azimuth = true;
+ break;
case HID_DG_TOUCH:
/* do nothing */
break;