aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2021-08-24 22:47:34 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2021-09-07 23:58:25 +0000
commit759a5cd1efb915dc6eae52ce9c44da4337a9ee90 (patch)
treef156720739ebdcde42bf5ebf20bedb856a1d67f9
parentde6d60ee1c86054563f4ff9eceaf988403d8b56c (diff)
downloadsrc-759a5cd1efb915dc6eae52ce9c44da4337a9ee90.tar.gz
src-759a5cd1efb915dc6eae52ce9c44da4337a9ee90.zip
evdev: Give short aliases to items of evdev_mt_slot array
with using of unioned anonymous structure. Access to the same data by using different members of union generally works despite it is not supported by C specs. Also add helper function to report entire slot state. (cherry picked from commit 059360287e3344f48f5a7839e2d6d54016b18b19)
-rw-r--r--sys/dev/evdev/evdev.h24
-rw-r--r--sys/dev/evdev/evdev_mt.c63
2 files changed, 73 insertions, 14 deletions
diff --git a/sys/dev/evdev/evdev.h b/sys/dev/evdev/evdev.h
index fe21f8cea4c2..64bf75f04efd 100644
--- a/sys/dev/evdev/evdev.h
+++ b/sys/dev/evdev/evdev.h
@@ -102,6 +102,29 @@ struct evdev_methods
evdev_keycode_t *ev_set_keycode;
};
+union evdev_mt_slot {
+ int32_t val[MT_CNT];
+ struct {
+ int32_t maj; /* ABS_MT_TOUCH_MAJOR */
+ int32_t min; /* ABS_MT_TOUCH_MINOR */
+ int32_t w_maj; /* ABS_MT_WIDTH_MAJOR */
+ int32_t w_min; /* ABS_MT_WIDTH_MINOR */
+ int32_t ori; /* ABS_MT_ORIENTATION */
+ int32_t x; /* ABS_MT_POSITION_X */
+ int32_t y; /* ABS_MT_POSITION_Y */
+ int32_t type; /* ABS_MT_TOOL_TYPE */
+ int32_t blob_id; /* ABS_MT_BLOB_ID */
+ int32_t id; /* ABS_MT_TRACKING_ID */
+ int32_t p; /* ABS_MT_PRESSURE */
+ int32_t dist; /* ABS_MT_DISTANCE */
+ int32_t tool_x; /* ABS_MT_TOOL_X */
+ int32_t tool_y; /* ABS_MT_TOOL_Y */
+ };
+};
+_Static_assert(offsetof(union evdev_mt_slot, tool_y) ==
+ offsetof(union evdev_mt_slot, val[ABS_MT_INDEX(ABS_MT_TOOL_Y)]),
+ "evdev_mt_slot array members does not match their structure aliases");
+
/* Input device interface: */
struct evdev_dev *evdev_alloc(void);
void evdev_free(struct evdev_dev *);
@@ -134,6 +157,7 @@ void *evdev_get_softc(struct evdev_dev *);
int evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
void evdev_support_mt_compat(struct evdev_dev *);
void evdev_push_mt_compat(struct evdev_dev *);
+int evdev_mt_push_slot(struct evdev_dev *, int, union evdev_mt_slot *);
void evdev_mt_push_autorel(struct evdev_dev *);
static inline int
evdev_mt_id_to_slot(struct evdev_dev *evdev, int32_t id)
diff --git a/sys/dev/evdev/evdev_mt.c b/sys/dev/evdev/evdev_mt.c
index a3600e837960..6f5cce4a008d 100644
--- a/sys/dev/evdev/evdev_mt.c
+++ b/sys/dev/evdev/evdev_mt.c
@@ -60,10 +60,6 @@ struct {
{ ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH, 15 },
};
-struct evdev_mt_slot {
- int32_t val[MT_CNT];
-};
-
struct evdev_mt {
int last_reported_slot;
u_int mtst_events;
@@ -71,7 +67,7 @@ struct evdev_mt {
slotset_t touches;
/* the set of slots with unsynchronized state */
slotset_t frame;
- struct evdev_mt_slot slots[];
+ union evdev_mt_slot slots[];
};
static void evdev_mt_send_st_compat(struct evdev_dev *);
@@ -91,12 +87,11 @@ evdev_mt_init(struct evdev_dev *evdev)
slots = MAXIMAL_MT_SLOT(evdev) + 1;
evdev->ev_mt = malloc(offsetof(struct evdev_mt, slots) +
- sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
+ sizeof(union evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
/* Initialize multitouch protocol type B states */
for (slot = 0; slot < slots; slot++)
- evdev->ev_mt->slots[slot].val[ABS_MT_INDEX(ABS_MT_TRACKING_ID)]
- = -1;
+ evdev->ev_mt->slots[slot].id = -1;
if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
evdev_support_mt_compat(evdev);
@@ -119,6 +114,49 @@ evdev_mt_sync_frame(struct evdev_dev *evdev)
evdev->ev_mt->frame = 0;
}
+static void
+evdev_mt_send_slot(struct evdev_dev *evdev, int slot,
+ union evdev_mt_slot *state)
+{
+ int i;
+ bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
+
+ EVDEV_LOCK_ASSERT(evdev);
+ MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)));
+ MPASS(!type_a || state != NULL);
+
+ if (!type_a) {
+ evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
+ if (state == NULL) {
+ evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ return;
+ }
+ }
+ bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i)
+ evdev_send_event(evdev, EV_ABS, i,
+ state->val[ABS_MT_INDEX(i)]);
+ if (type_a)
+ evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
+}
+
+int
+evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
+ union evdev_mt_slot *state)
+{
+ bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
+
+ if (type_a && state == NULL)
+ return (EINVAL);
+ if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev)))
+ return (EINVAL);
+
+ EVDEV_ENTER(evdev);
+ evdev_mt_send_slot(evdev, slot, state);
+ EVDEV_EXIT(evdev);
+
+ return (0);
+}
+
int
evdev_mt_get_last_slot(struct evdev_dev *evdev)
{
@@ -170,8 +208,7 @@ evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
int slot;
FOREACHBIT(mt->touches, slot)
- if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) ==
- tracking_id)
+ if (mt->slots[slot].id == tracking_id)
return (slot);
/*
* Do not allow allocation of new slot in a place of just
@@ -278,10 +315,8 @@ evdev_mt_send_autorel(struct evdev_dev *evdev)
EVDEV_LOCK_ASSERT(evdev);
- FOREACHBIT(mt->touches & ~mt->frame, slot) {
- evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
- evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
- }
+ FOREACHBIT(mt->touches & ~mt->frame, slot)
+ evdev_mt_send_slot(evdev, slot, NULL);
}
void