git: 059360287e33 - main - evdev: Give short aliases to items of evdev_mt_slot array

Vladimir Kondratyev wulf at FreeBSD.org
Tue Aug 24 23:04:18 UTC 2021


The branch main has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=059360287e3344f48f5a7839e2d6d54016b18b19

commit 059360287e3344f48f5a7839e2d6d54016b18b19
Author:     Vladimir Kondratyev <wulf at FreeBSD.org>
AuthorDate: 2021-08-24 22:47:34 +0000
Commit:     Vladimir Kondratyev <wulf at FreeBSD.org>
CommitDate: 2021-08-24 22:47:34 +0000

    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.
    
    MFC after:      2 weeks
---
 sys/dev/evdev/evdev.h    | 24 ++++++++++++++++++
 sys/dev/evdev/evdev_mt.c | 63 +++++++++++++++++++++++++++++++++++++-----------
 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


More information about the dev-commits-src-all mailing list