View | Details | Raw Unified | Return to bug 252236 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/dev/evdev/cdev.c (-1 / +1 lines)
Lines 621-627 evdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, Link Here
621
		    MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1);
621
		    MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1);
622
		for (int i = 0; i < nvalues; i++)
622
		for (int i = 0; i < nvalues; i++)
623
			((int32_t *)data)[i + 1] =
623
			((int32_t *)data)[i + 1] =
624
			    evdev_get_mt_value(evdev, i, code);
624
			    evdev_mt_get_value(evdev, i, code);
625
		return (0);
625
		return (0);
626
626
627
	case EVIOCGKEY(0):
627
	case EVIOCGKEY(0):
(-)b/sys/dev/evdev/evdev.c (-39 / +39 lines)
Lines 93-107 static void evdev_start_repeat(struct evdev_dev *, uint16_t); Link Here
93
static void evdev_stop_repeat(struct evdev_dev *);
93
static void evdev_stop_repeat(struct evdev_dev *);
94
static int evdev_check_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
94
static int evdev_check_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
95
95
96
static inline void
97
bit_change(bitstr_t *bitstr, int bit, int value)
98
{
99
	if (value)
100
		bit_set(bitstr, bit);
101
	else
102
		bit_clear(bitstr, bit);
103
}
104
105
struct evdev_dev *
96
struct evdev_dev *
106
evdev_alloc(void)
97
evdev_alloc(void)
107
{
98
{
Lines 315-323 evdev_register_common(struct evdev_dev *evdev) Link Here
315
		}
306
		}
316
	}
307
	}
317
308
318
	/* Initialize multitouch protocol type B states */
309
	/* Initialize multitouch protocol type B states or A to B convertor */
319
	if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT) &&
310
	if ((bit_test(evdev->ev_abs_flags, ABS_MT_SLOT) &&
320
	    evdev->ev_absinfo != NULL && MAXIMAL_MT_SLOT(evdev) > 0)
311
	     evdev->ev_absinfo != NULL && MAXIMAL_MT_SLOT(evdev) > 0) ||
312
	    (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) &&
313
	     bit_test(evdev->ev_abs_flags, ABS_MT_POSITION_X) &&
314
	     bit_test(evdev->ev_abs_flags, ABS_MT_POSITION_Y)))
321
		evdev_mt_init(evdev);
315
		evdev_mt_init(evdev);
322
316
323
	/* Estimate maximum report size */
317
	/* Estimate maximum report size */
Lines 720-734 evdev_modify_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
720
		break;
714
		break;
721
715
722
	case EV_ABS:
716
	case EV_ABS:
723
		fuzz = evdev->ev_absinfo[code].fuzz;
717
		if (code == ABS_MT_SLOT)
724
		if (fuzz == 0 || code == ABS_MT_SLOT)
725
			break;
718
			break;
726
		else if (!ABS_IS_MT(code))
719
		else if (!ABS_IS_MT(code))
727
			old_value = evdev->ev_absinfo[code].value;
720
			old_value = evdev->ev_absinfo[code].value;
728
		else if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
721
		else if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
729
			old_value = evdev_get_mt_value(evdev,
722
			/* Pass MT protocol type A events as is */
730
			    evdev_get_last_mt_slot(evdev), code);
723
			break;
731
		else	/* Pass MT protocol type A events as is */
724
		else if (code == ABS_MT_TRACKING_ID) {
725
			*value = evdev_mt_reassign_id(evdev,
726
			    evdev_mt_get_last_slot(evdev), *value);
727
			break;
728
		} else
729
			old_value = evdev_mt_get_value(evdev,
730
			    evdev_mt_get_last_slot(evdev), code);
731
732
		fuzz = evdev->ev_absinfo[code].fuzz;
733
		if (fuzz == 0)
732
			break;
734
			break;
733
735
734
		abs_change = abs(*value - old_value);
736
		abs_change = abs(*value - old_value);
Lines 807-813 evdev_sparse_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
807
		switch (code) {
809
		switch (code) {
808
		case ABS_MT_SLOT:
810
		case ABS_MT_SLOT:
809
			/* Postpone ABS_MT_SLOT till next event */
811
			/* Postpone ABS_MT_SLOT till next event */
810
			evdev_set_last_mt_slot(evdev, value);
812
			evdev_mt_set_last_slot(evdev, value);
811
			return (EV_SKIP_EVENT);
813
			return (EV_SKIP_EVENT);
812
814
813
		case ABS_MT_FIRST ... ABS_MT_LAST:
815
		case ABS_MT_FIRST ... ABS_MT_LAST:
Lines 815-825 evdev_sparse_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
815
			if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
817
			if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
816
				break;
818
				break;
817
			/* Don`t repeat MT protocol type B events */
819
			/* Don`t repeat MT protocol type B events */
818
			last_mt_slot = evdev_get_last_mt_slot(evdev);
820
			last_mt_slot = evdev_mt_get_last_slot(evdev);
819
			if (evdev_get_mt_value(evdev, last_mt_slot, code)
821
			if (evdev_mt_get_value(evdev, last_mt_slot, code)
820
			     == value)
822
			     == value)
821
				return (EV_SKIP_EVENT);
823
				return (EV_SKIP_EVENT);
822
			evdev_set_mt_value(evdev, last_mt_slot, code, value);
824
			evdev_mt_set_value(evdev, last_mt_slot, code, value);
823
			if (last_mt_slot != CURRENT_MT_SLOT(evdev)) {
825
			if (last_mt_slot != CURRENT_MT_SLOT(evdev)) {
824
				CURRENT_MT_SLOT(evdev) = last_mt_slot;
826
				CURRENT_MT_SLOT(evdev) = last_mt_slot;
825
				evdev->ev_report_opened = true;
827
				evdev->ev_report_opened = true;
Lines 895-900 evdev_send_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
895
897
896
	EVDEV_LOCK_ASSERT(evdev);
898
	EVDEV_LOCK_ASSERT(evdev);
897
899
900
	evdev_modify_event(evdev, type, code, &value);
898
	sparse =  evdev_sparse_event(evdev, type, code, value);
901
	sparse =  evdev_sparse_event(evdev, type, code, value);
899
	switch (sparse) {
902
	switch (sparse) {
900
	case EV_REPORT_MT_SLOT:
903
	case EV_REPORT_MT_SLOT:
Lines 918-937 evdev_restore_after_kdb(struct evdev_dev *evdev) Link Here
918
	EVDEV_LOCK_ASSERT(evdev);
921
	EVDEV_LOCK_ASSERT(evdev);
919
922
920
	/* Report postponed leds */
923
	/* Report postponed leds */
921
	for (code = 0; code < LED_CNT; code++)
924
	bit_foreach(evdev->ev_kdb_led_states, LED_CNT, code)
922
		if (bit_test(evdev->ev_kdb_led_states, code))
925
		evdev_send_event(evdev, EV_LED, code,
923
			evdev_send_event(evdev, EV_LED, code,
926
		    !bit_test(evdev->ev_led_states, code));
924
			    !bit_test(evdev->ev_led_states, code));
925
	bit_nclear(evdev->ev_kdb_led_states, 0, LED_MAX);
927
	bit_nclear(evdev->ev_kdb_led_states, 0, LED_MAX);
926
928
927
	/* Release stuck keys (CTRL + ALT + ESC) */
929
	/* Release stuck keys (CTRL + ALT + ESC) */
928
	evdev_stop_repeat(evdev);
930
	evdev_stop_repeat(evdev);
929
	for (code = 0; code < KEY_CNT; code++) {
931
	bit_foreach(evdev->ev_key_states, KEY_CNT, code)
930
		if (bit_test(evdev->ev_key_states, code)) {
932
		evdev_send_event(evdev, EV_KEY, code, KEY_EVENT_UP);
931
			evdev_send_event(evdev, EV_KEY, code, KEY_EVENT_UP);
933
	evdev_send_event(evdev, EV_SYN, SYN_REPORT, 1);
932
			evdev_send_event(evdev, EV_SYN, SYN_REPORT, 1);
933
		}
934
	}
935
}
934
}
936
935
937
int
936
int
Lines 962-976 evdev_push_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
962
		evdev_restore_after_kdb(evdev);
961
		evdev_restore_after_kdb(evdev);
963
	}
962
	}
964
963
965
	evdev_modify_event(evdev, type, code, &value);
966
	if (type == EV_SYN && code == SYN_REPORT &&
964
	if (type == EV_SYN && code == SYN_REPORT &&
967
	     bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
965
	    bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
968
		evdev_send_mt_autorel(evdev);
966
		evdev_mt_sync_frame(evdev);
969
	if (type == EV_SYN && code == SYN_REPORT && evdev->ev_report_opened &&
967
	else
970
	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
968
		if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) &&
971
		evdev_send_mt_compat(evdev);
969
		    evdev_mt_record_event(evdev, type, code, value))
972
	evdev_send_event(evdev, type, code, value);
970
			goto exit;
973
971
972
	evdev_send_event(evdev, type, code, value);
973
exit:
974
	EVDEV_EXIT(evdev);
974
	EVDEV_EXIT(evdev);
975
975
976
	return (0);
976
	return (0);
(-)b/sys/dev/evdev/evdev.h (-3 / +38 lines)
Lines 90-95 extern int evdev_sysmouse_t_axis; Link Here
90
					 * current MT protocol type B report */
90
					 * current MT protocol type B report */
91
#define	EVDEV_FLAG_EXT_EPOCH	0x03	/* evdev_push_* is allways called with
91
#define	EVDEV_FLAG_EXT_EPOCH	0x03	/* evdev_push_* is allways called with
92
					 * input (global) epoch entered */
92
					 * input (global) epoch entered */
93
#define	EVDEV_FLAG_MT_TRACK	0x04	/* Assign touch to slot by evdev */
94
#define	EVDEV_FLAG_MT_KEEPID	0x05	/* Do not reassign tracking ID */
93
#define	EVDEV_FLAG_MAX		0x1F
95
#define	EVDEV_FLAG_MAX		0x1F
94
#define	EVDEV_FLAG_CNT		(EVDEV_FLAG_MAX + 1)
96
#define	EVDEV_FLAG_CNT		(EVDEV_FLAG_MAX + 1)
95
97
Lines 102-107 struct evdev_methods Link Here
102
	evdev_keycode_t		*ev_set_keycode;
104
	evdev_keycode_t		*ev_set_keycode;
103
};
105
};
104
106
107
union evdev_mt_slot {
108
	int32_t         val[MT_CNT];
109
	struct {
110
		int32_t maj;		/* ABS_MT_TOUCH_MAJOR */
111
		int32_t min;		/* ABS_MT_TOUCH_MINOR */
112
		int32_t w_maj;		/* ABS_MT_WIDTH_MAJOR */
113
		int32_t w_min;		/* ABS_MT_WIDTH_MINOR */
114
		int32_t ori;		/* ABS_MT_ORIENTATION */
115
		int32_t x;		/* ABS_MT_POSITION_X */
116
		int32_t y;		/* ABS_MT_POSITION_Y */
117
		int32_t type;		/* ABS_MT_TOOL_TYPE */
118
		int32_t blob_id;	/* ABS_MT_BLOB_ID */
119
		int32_t id;		/* ABS_MT_TRACKING_ID */
120
		int32_t p;		/* ABS_MT_PRESSURE */
121
		int32_t dist;		/* ABS_MT_DISTANCE */
122
		int32_t tool_x;		/* ABS_MT_TOOL_X */
123
		int32_t tool_y;		/* ABS_MT_TOOL_Y */
124
	};
125
};
126
_Static_assert(offsetof(union evdev_mt_slot, tool_y) ==
127
    offsetof(union evdev_mt_slot, val[ABS_MT_INDEX(ABS_MT_TOOL_Y)]),
128
    "evdev_mt_slot array members does not match their structure aliases");
129
105
/* Input device interface: */
130
/* Input device interface: */
106
struct evdev_dev *evdev_alloc(void);
131
struct evdev_dev *evdev_alloc(void);
107
void evdev_free(struct evdev_dev *);
132
void evdev_free(struct evdev_dev *);
Lines 131-141 void evdev_set_flag(struct evdev_dev *, uint16_t); Link Here
131
void *evdev_get_softc(struct evdev_dev *);
156
void *evdev_get_softc(struct evdev_dev *);
132
157
133
/* Multitouch related functions: */
158
/* Multitouch related functions: */
134
int32_t evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
159
int evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
135
void evdev_support_nfingers(struct evdev_dev *, int32_t);
136
void evdev_support_mt_compat(struct evdev_dev *);
160
void evdev_support_mt_compat(struct evdev_dev *);
137
void evdev_push_nfingers(struct evdev_dev *, int32_t);
138
void evdev_push_mt_compat(struct evdev_dev *);
161
void evdev_push_mt_compat(struct evdev_dev *);
162
int evdev_mt_push_slot(struct evdev_dev *, int, union evdev_mt_slot *);
163
int evdev_mt_push_frame(struct evdev_dev *, union evdev_mt_slot *, int);
164
void evdev_mt_match_frame(struct evdev_dev *, union evdev_mt_slot *, int);
165
union evdev_mt_slot *evdev_mt_get_match_slots(struct evdev_dev *);
166
void evdev_mt_push_autorel(struct evdev_dev *);
167
static __inline int
168
evdev_mt_id_to_slot(struct evdev_dev *evdev, int32_t id)
169
{
170
	return (evdev_get_mt_slot_by_tracking_id(evdev, id));
171
}
139
172
140
/* Utility functions: */
173
/* Utility functions: */
141
uint16_t evdev_hid2key(int);
174
uint16_t evdev_hid2key(int);
Lines 144-149 uint16_t evdev_scancode2key(int *, int); Link Here
144
void evdev_push_mouse_btn(struct evdev_dev *, int);
177
void evdev_push_mouse_btn(struct evdev_dev *, int);
145
void evdev_push_leds(struct evdev_dev *, int);
178
void evdev_push_leds(struct evdev_dev *, int);
146
void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
179
void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
180
void evdev_support_nfingers(struct evdev_dev *, int);
181
void evdev_push_nfingers(struct evdev_dev *, int);
147
182
148
/* Event reporting shortcuts: */
183
/* Event reporting shortcuts: */
149
static __inline int
184
static __inline int
(-)b/sys/dev/evdev/evdev_mt.c (-134 / +528 lines)
Lines 1-5 Link Here
1
/*-
1
/*-
2
 * Copyright (c) 2016 Vladimir Kondratyev <wulf@FreeBSD.org>
2
 * Copyright (c) 2016, 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
Lines 25-30 Link Here
25
 *
25
 *
26
 * $FreeBSD$
26
 * $FreeBSD$
27
 */
27
 */
28
/*-
29
 * Copyright (c) 2015, 2016 Ulf Brosziewski
30
 *
31
 * Permission to use, copy, modify, and distribute this software for any
32
 * purpose with or without fee is hereby granted, provided that the above
33
 * copyright notice and this permission notice appear in all copies.
34
 *
35
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
36
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
37
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
38
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
39
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
40
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
41
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42
 */
28
43
29
#include <sys/param.h>
44
#include <sys/param.h>
30
#include <sys/lock.h>
45
#include <sys/lock.h>
Lines 42-95 Link Here
42
#define	debugf(fmt, args...)
57
#define	debugf(fmt, args...)
43
#endif
58
#endif
44
59
45
static uint16_t evdev_fngmap[] = {
60
typedef	u_int	slotset_t;
46
	BTN_TOOL_FINGER,
47
	BTN_TOOL_DOUBLETAP,
48
	BTN_TOOL_TRIPLETAP,
49
	BTN_TOOL_QUADTAP,
50
	BTN_TOOL_QUINTTAP,
51
};
52
61
53
static uint16_t evdev_mtstmap[][2] = {
62
_Static_assert(MAX_MT_SLOTS < sizeof(slotset_t) * 8, "MAX_MT_SLOTS too big");
54
	{ ABS_MT_POSITION_X, ABS_X },
63
55
	{ ABS_MT_POSITION_Y, ABS_Y },
64
#define FOREACHBIT(v, i) \
56
	{ ABS_MT_PRESSURE, ABS_PRESSURE },
65
	for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1)
57
	{ ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH },
58
};
59
66
60
struct evdev_mt_slot {
67
struct {
61
	uint64_t ev_report;
68
	uint16_t	mt;
62
	int32_t ev_mt_states[MT_CNT];
69
	uint16_t	st;
70
	int32_t		max;
71
} static evdev_mtstmap[] = {
72
	{ ABS_MT_POSITION_X,	ABS_X,		0 },
73
	{ ABS_MT_POSITION_Y,	ABS_Y,		0 },
74
	{ ABS_MT_PRESSURE,	ABS_PRESSURE,	255 },
75
	{ ABS_MT_TOUCH_MAJOR,	ABS_TOOL_WIDTH,	15 },
63
};
76
};
64
77
65
struct evdev_mt {
78
struct evdev_mt {
66
	int32_t	ev_mt_last_reported_slot;
79
	int			last_reported_slot;
67
	struct evdev_mt_slot ev_mt_slots[];
80
	uint16_t		tracking_id;
81
	int32_t			tracking_ids[MAX_MT_SLOTS];
82
	bool			type_a;
83
	u_int			mtst_events;
84
	/* the set of slots with active touches */
85
	slotset_t		touches;
86
	/* the set of slots with unsynchronized state */
87
	slotset_t		frame;
88
	/* the set of slots to match with active touches */
89
	slotset_t		match_frame;
90
	int			match_slot;
91
	union evdev_mt_slot	*match_slots;
92
	int			*matrix;
93
	union evdev_mt_slot	slots[];
68
};
94
};
69
95
96
static void	evdev_mt_send_st_compat(struct evdev_dev *);
97
static void	evdev_mt_send_autorel(struct evdev_dev *);
98
static void	evdev_mt_replay_events(struct evdev_dev *);
99
100
static inline int
101
ffc_slot(struct evdev_dev *evdev, slotset_t slots)
102
{
103
	return (ffs(~slots & (2U << MAXIMAL_MT_SLOT(evdev)) - 1) - 1);
104
}
105
70
void
106
void
71
evdev_mt_init(struct evdev_dev *evdev)
107
evdev_mt_init(struct evdev_dev *evdev)
72
{
108
{
73
	int32_t slot, slots;
109
	struct evdev_mt *mt;
110
	size_t size = offsetof(struct evdev_mt, slots);
111
	int slot, slots;
112
	bool type_a;
113
114
	type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
115
	if (type_a) {
116
		/* Add events produced by MT type A to type B convertor */
117
		evdev_support_abs(evdev,
118
		    ABS_MT_SLOT, 0, MAX_MT_SLOTS - 1, 0, 0, 0);
119
		if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID))
120
			evdev_support_abs(evdev,
121
			    ABS_MT_TRACKING_ID, -1, MAX_MT_SLOTS - 1, 0, 0, 0);
122
	}
74
123
75
	slots = MAXIMAL_MT_SLOT(evdev) + 1;
124
	slots = MAXIMAL_MT_SLOT(evdev) + 1;
125
	size += sizeof(mt->slots[0]) * slots;
126
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
127
		size += sizeof(mt->match_slots[0]) * slots;
128
		size += sizeof(mt->matrix[0]) * (slots + 6) * slots;
129
	}
76
130
77
	evdev->ev_mt = malloc(offsetof(struct evdev_mt, ev_mt_slots) +
131
	mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO);
78
	     sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
132
	evdev->ev_mt = mt;
133
	mt->type_a = type_a;
79
134
80
	/* Initialize multitouch protocol type B states */
135
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
81
	for (slot = 0; slot < slots; slot++) {
136
		mt->match_slots = mt->slots + slots;
82
		/*
137
		mt->matrix = (int *)(mt->match_slots + slots);
83
		 * .ev_report should not be initialized to initial value of
84
		 * report counter (0) as it brokes free slot detection in
85
		 * evdev_get_mt_slot_by_tracking_id. So initialize it to -1
86
		 */
87
		evdev->ev_mt->ev_mt_slots[slot] = (struct evdev_mt_slot) {
88
			.ev_report = 0xFFFFFFFFFFFFFFFFULL,
89
			.ev_mt_states[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] = -1,
90
		};
91
	}
138
	}
92
139
140
	/* Initialize multitouch protocol type B states */
141
	for (slot = 0; slot < slots; slot++)
142
		mt->slots[slot].id = -1;
143
144
	if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID))
145
		evdev_support_abs(evdev,
146
		    ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0);
93
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
147
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
94
		evdev_support_mt_compat(evdev);
148
		evdev_support_mt_compat(evdev);
95
}
149
}
Lines 97-251 evdev_mt_init(struct evdev_dev *evdev) Link Here
97
void
151
void
98
evdev_mt_free(struct evdev_dev *evdev)
152
evdev_mt_free(struct evdev_dev *evdev)
99
{
153
{
100
101
	free(evdev->ev_mt, M_EVDEV);
154
	free(evdev->ev_mt, M_EVDEV);
102
}
155
}
103
156
104
int32_t
157
void
105
evdev_get_last_mt_slot(struct evdev_dev *evdev)
158
evdev_mt_sync_frame(struct evdev_dev *evdev)
159
{
160
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
161
		evdev_mt_replay_events(evdev);
162
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
163
		evdev_mt_send_autorel(evdev);
164
	if (evdev->ev_report_opened &&
165
	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
166
		evdev_mt_send_st_compat(evdev);
167
	evdev->ev_mt->frame = 0;
168
}
169
170
static void
171
evdev_mt_send_slot(struct evdev_dev *evdev, int slot,
172
    union evdev_mt_slot *state)
106
{
173
{
174
	int i;
175
	bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
176
177
	EVDEV_LOCK_ASSERT(evdev);
178
	MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)));
179
	MPASS(!type_a || state != NULL);
180
181
	if (!type_a) {
182
		evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
183
		if (state == NULL) {
184
			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
185
			return;
186
		}
187
	}
188
	bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i)
189
		evdev_send_event(evdev, EV_ABS, i,
190
		    state->val[ABS_MT_INDEX(i)]);
191
	if (type_a)
192
		evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
193
}
194
195
int
196
evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
197
    union evdev_mt_slot *state)
198
{
199
	struct evdev_mt *mt = evdev->ev_mt;
200
	bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
201
202
	if ((type_a || (mt != NULL && mt->type_a)) && state == NULL)
203
		return (EINVAL);
204
	if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev)))
205
		return (EINVAL);
206
207
	EVDEV_ENTER(evdev);
208
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) && mt->type_a) {
209
		mt->match_slots[mt->match_slot] = *state;
210
		evdev_mt_record_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
211
	} else if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
212
		evdev_mt_record_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
213
		if (state != NULL)
214
			mt->match_slots[mt->match_slot] = *state;
215
		else
216
			evdev_mt_record_event(evdev, EV_ABS,
217
			    ABS_MT_TRACKING_ID, -1);
218
	} else
219
		evdev_mt_send_slot(evdev, slot, state);
220
	EVDEV_EXIT(evdev);
221
222
	return (0);
223
}
107
224
108
	return (evdev->ev_mt->ev_mt_last_reported_slot);
225
/*
226
 * Find a minimum-weight matching for an m-by-n matrix.
227
 *
228
 * m must be greater than or equal to n. The size of the buffer must be
229
 * at least 3m + 3n.
230
 *
231
 * On return, the first m elements of the buffer contain the row-to-
232
 * column mappings, i.e., buffer[i] is the column index for row i, or -1
233
 * if there is no assignment for that row (which may happen if n < m).
234
 *
235
 * Wrong results because of overflows will not occur with input values
236
 * in the range of 0 to INT_MAX / 2 inclusive.
237
 *
238
 * The function applies the Dinic-Kronrod algorithm. It is not modern or
239
 * popular, but it seems to be a good choice for small matrices at least.
240
 * The original form of the algorithm is modified as follows: There is no
241
 * initial search for row minima, the initial assignments are in a
242
 * "virtual" column with the index -1 and zero values. This permits inputs
243
 * with n < m, and it simplifies the reassignments.
244
 */
245
static void
246
evdev_mt_matching(int *matrix, int m, int n, int *buffer)
247
{
248
	int i, j, k, d, e, row, col, delta;
249
	int *p;
250
	int *r2c = buffer;	/* row-to-column assignments */
251
	int *red = r2c + m;	/* reduced values of the assignments */
252
	int *mc = red + m;	/* row-wise minimal elements of cs */
253
	int *cs = mc + m;	/* the column set */
254
	int *c2r = cs + n;	/* column-to-row assignments in cs */
255
	int *cd = c2r + n;	/* column deltas (reduction) */
256
257
	for (p = r2c; p < red; *p++ = -1) {}
258
	for (; p < mc; *p++ = 0) {}
259
	for (col = 0; col < n; col++) {
260
		delta = INT_MAX;
261
		for (i = 0, p = matrix + col; i < m; i++, p += n) {
262
			d = *p - red[i];
263
			if (d < delta || (d == delta && r2c[i] < 0)) {
264
				delta = d;
265
				row = i;
266
			}
267
		}
268
		cd[col] = delta;
269
		if (r2c[row] < 0) {
270
			r2c[row] = col;
271
			continue;
272
		}
273
		for (p = mc; p < cs; *p++ = col) {}
274
		for (k = 0; (j = r2c[row]) >= 0;) {
275
			cs[k++] = j;
276
			c2r[j] = row;
277
			mc[row] -= n;
278
			delta = INT_MAX;
279
			for (i = 0, p = matrix; i < m; i++, p += n)
280
				if (mc[i] >= 0) {
281
					d = p[mc[i]] - cd[mc[i]];
282
					e = p[j] - cd[j];
283
					if (e < d) {
284
						d = e;
285
						mc[i] = j;
286
					}
287
					d -= red[i];
288
					if (d < delta || (d == delta
289
					    && r2c[i] < 0)) {
290
						delta = d;
291
						row = i;
292
					}
293
				}
294
			cd[col] += delta;
295
			for (i = 0; i < k; i++) {
296
				cd[cs[i]] += delta;
297
				red[c2r[cs[i]]] -= delta;
298
			}
299
		}
300
		for (j = mc[row]; (r2c[row] = j) != col;) {
301
			row = c2r[j];
302
			j = mc[row] + n;
303
		}
304
	}
109
}
305
}
110
306
307
/*
308
 * Assign slot numbers to the points in the pt array.  The slot numbers are
309
 * passed to the caller in the pt->id fields.
310
 *
311
 * The slot assignment pairs the points with points of the previous frame in
312
 * such a way that the sum of the squared distances is minimal.  Using
313
 * squares instead of simple distances favours assignments with more uniform
314
 * distances, and it is faster.
315
 */
111
void
316
void
112
evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
317
evdev_mt_match_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt,
318
    int size)
113
{
319
{
320
	struct evdev_mt *mt = evdev->ev_mt;
321
	int i, j, m, n, dx, dy, slot, num_touches;
322
	int *p, *r2c, *c2r;
323
	u_int touches;
324
325
	EVDEV_LOCK_ASSERT(evdev);
326
	MPASS(mt->matrix != NULL);
327
	MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
114
328
115
	evdev->ev_mt->ev_mt_slots[slot].ev_report = evdev->ev_report_count;
329
	if (size == 0)
116
	evdev->ev_mt->ev_mt_last_reported_slot = slot;
330
		return;
331
332
	p = mt->matrix;
333
	touches = mt->touches;
334
	num_touches = bitcount(touches);
335
	if (num_touches >= size) {
336
		FOREACHBIT(touches, slot)
337
			for (i = 0; i < size; i++) {
338
				dx = pt[i].x - mt->slots[slot].x;
339
				dy = pt[i].y - mt->slots[slot].y;
340
				*p++ = dx * dx + dy * dy;
341
			}
342
		m = num_touches;
343
		n = size;
344
	} else {
345
		for (i = 0; i < size; i++)
346
			FOREACHBIT(touches, slot) {
347
				dx = pt[i].x - mt->slots[slot].x;
348
				dy = pt[i].y - mt->slots[slot].y;
349
				*p++ = dx * dx + dy * dy;
350
			}
351
		m = size;
352
		n = num_touches;
353
	}
354
	evdev_mt_matching(mt->matrix, m, n, p);
355
356
	r2c = p;
357
	c2r = p + m;
358
	for (i = 0; i < m; i++)
359
		if ((j = r2c[i]) >= 0)
360
			c2r[j] = i;
361
362
	p = (n == size ? r2c : c2r);
363
	FOREACHBIT(touches, slot)
364
		if ((i = *p++) >= 0)
365
			pt[i].id = slot;
366
367
	p = (n == size ? c2r : r2c);
368
	for (i = 0; i < size; i++)
369
		if (*p++ < 0 && (pt[i].id = ffc_slot(evdev, touches)) >= 0)
370
			touches |= 1U << pt[i].id;
117
}
371
}
118
372
119
inline int32_t
373
static void
120
evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
374
evdev_mt_send_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
121
{
375
{
376
	union evdev_mt_slot *slot;
377
378
	EVDEV_LOCK_ASSERT(evdev);
379
	MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
122
380
123
	return (evdev->ev_mt->
381
	for (slot = pt; slot < pt + size; slot++)
124
	    ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
382
		if (slot->id >= 0)
383
			evdev_mt_send_slot(evdev, slot->id, slot);
125
}
384
}
126
385
127
inline void
386
int
128
evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
387
evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
388
{
389
	if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1)
390
		return (EINVAL);
391
392
	EVDEV_ENTER(evdev);
393
	evdev_mt_send_frame(evdev, pt, size);
394
	EVDEV_EXIT(evdev);
395
396
	return (0);
397
}
398
399
bool
400
evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
129
    int32_t value)
401
    int32_t value)
130
{
402
{
403
	struct evdev_mt *mt = evdev->ev_mt;
404
405
	EVDEV_LOCK_ASSERT(evdev);
406
407
	switch (type) {
408
	case EV_SYN:
409
		if (code == SYN_MT_REPORT) {
410
			/* MT protocol type A support */
411
			KASSERT(mt->type_a, ("Not a MT type A protocol"));
412
			mt->match_frame |= 1U << mt->match_slot;
413
			mt->match_slot++;
414
			return (true);
415
		}
416
		break;
417
	case EV_ABS:
418
		if (code == ABS_MT_SLOT) {
419
			/* MT protocol type B support */
420
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
421
			KASSERT(value >= 0, ("Negative slot number"));
422
			mt->match_slot = value;
423
			mt->match_frame |= 1U << mt->match_slot;
424
			return (true);
425
		} else if (code == ABS_MT_TRACKING_ID) {
426
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
427
			if (value == -1)
428
				mt->match_frame &= ~(1U << mt->match_slot);
429
			return (true);
430
		} else if (ABS_IS_MT(code)) {
431
			KASSERT(mt->match_slot >= 0, ("Negative slot"));
432
			KASSERT(mt->match_slot <= MAXIMAL_MT_SLOT(evdev),
433
			    ("Slot number too big"));
434
			mt->match_slots[mt->match_slot].
435
			    val[ABS_MT_INDEX(code)] = value;
436
			return (true);
437
		}
438
		break;
439
	default:
440
		break;
441
	}
131
442
132
	evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
443
	return (false);
133
	    value;
134
}
444
}
135
445
136
int32_t
446
static void
137
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
447
evdev_mt_replay_events(struct evdev_dev *evdev)
138
{
448
{
139
	int32_t tr_id, slot, free_slot = -1;
449
	struct evdev_mt *mt = evdev->ev_mt;
450
	int slot, size = 0;
140
451
141
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
452
	EVDEV_LOCK_ASSERT(evdev);
142
		tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
453
143
		if (tr_id == tracking_id)
454
	FOREACHBIT(mt->match_frame, slot) {
144
			return (slot);
455
		if (slot != size)
145
		/*
456
			mt->match_slots[size] = mt->match_slots[slot];
146
		 * Its possible that slot will be reassigned in a place of just
457
		size++;
147
		 * released one within the same report. To avoid this compare
148
		 * report counter with slot`s report number updated with each
149
		 * ABS_MT_TRACKING_ID change.
150
		 */
151
		if (free_slot == -1 && tr_id == -1 &&
152
		    evdev->ev_mt->ev_mt_slots[slot].ev_report !=
153
		    evdev->ev_report_count)
154
			free_slot = slot;
155
	}
458
	}
459
	evdev_mt_match_frame(evdev, mt->match_slots, size);
460
	evdev_mt_send_frame(evdev, mt->match_slots, size);
461
	mt->match_slot = 0;
462
	mt->match_frame = 0;
463
}
464
465
union evdev_mt_slot *
466
evdev_mt_get_match_slots(struct evdev_dev *evdev)
467
{
468
	return (evdev->ev_mt->match_slots);
469
}
156
470
157
	return (free_slot);
471
int
472
evdev_mt_get_last_slot(struct evdev_dev *evdev)
473
{
474
	return (evdev->ev_mt->last_reported_slot);
158
}
475
}
159
476
160
void
477
void
161
evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
478
evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
162
{
479
{
163
	int32_t i;
480
	struct evdev_mt *mt = evdev->ev_mt;
164
481
165
	for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
482
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
166
		evdev_support_key(evdev, evdev_fngmap[i]);
483
484
	mt->frame |= 1U << slot;
485
	mt->last_reported_slot = slot;
167
}
486
}
168
487
169
void
488
int32_t
170
evdev_support_mt_compat(struct evdev_dev *evdev)
489
evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code)
171
{
490
{
172
	int32_t i;
491
	struct evdev_mt *mt = evdev->ev_mt;
173
492
174
	if (evdev->ev_absinfo == NULL)
493
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
175
		return;
176
494
177
	evdev_support_event(evdev, EV_KEY);
495
	return (mt->slots[slot].val[ABS_MT_INDEX(code)]);
178
	evdev_support_key(evdev, BTN_TOUCH);
496
}
179
497
180
	/* Touchscreens should not advertise tap tool capabilities */
498
void
181
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
499
evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
182
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
500
    int32_t value)
501
{
502
	struct evdev_mt *mt = evdev->ev_mt;
183
503
184
	/* Echo 0-th MT-slot as ST-slot */
504
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
185
	for (i = 0; i < nitems(evdev_mtstmap); i++)
505
186
		if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
506
	if (code == ABS_MT_TRACKING_ID) {
187
			evdev_support_abs(evdev, evdev_mtstmap[i][1],
507
		if (value != -1)
188
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
508
			mt->touches |= 1U << slot;
189
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
509
		else
190
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
510
			mt->touches &= ~(1U << slot);
191
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
511
	}
192
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
512
	mt->slots[slot].val[ABS_MT_INDEX(code)] = value;
193
}
513
}
194
514
195
static int32_t
515
int
196
evdev_count_fingers(struct evdev_dev *evdev)
516
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
197
{
517
{
198
	int32_t nfingers = 0, i;
518
	struct evdev_mt *mt = evdev->ev_mt;
519
	int slot;
199
520
200
	for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
521
	KASSERT(!mt->type_a, ("Not a MT type B protocol"));
201
		if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
202
			nfingers++;
203
522
204
	return (nfingers);
523
	/*
524
	 * Ignore tracking_id if slot assignment is performed by evdev.
525
	 * Events are written sequentially to temporary matching buffer.
526
	 */
527
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
528
		return (ffc_slot(evdev, mt->match_frame));
529
530
	FOREACHBIT(mt->touches, slot)
531
		if (mt->tracking_ids[slot] == tracking_id)
532
			return (slot);
533
	/*
534
	 * Do not allow allocation of new slot in a place of just
535
	 * released one within the same report.
536
	 */
537
	return (ffc_slot(evdev, mt->touches | mt->frame));
205
}
538
}
206
539
207
static void
540
int32_t
208
evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
541
evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id)
209
{
542
{
210
	int32_t i;
543
	struct evdev_mt *mt = evdev->ev_mt;
544
	int32_t nid;
211
545
212
	EVDEV_LOCK_ASSERT(evdev);
546
	if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) {
547
		mt->tracking_ids[slot] = id;
548
		return (id);
549
	}
213
550
214
	if (nfingers > nitems(evdev_fngmap))
551
	nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
215
		nfingers = nitems(evdev_fngmap);
552
	if (nid != -1) {
553
		KASSERT(id == mt->tracking_ids[slot],
554
		    ("MT-slot tracking id has changed"));
555
		return (nid);
556
	}
216
557
217
	for (i = 0; i < nitems(evdev_fngmap); i++)
558
	mt->tracking_ids[slot] = id;
218
		evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
559
again:
219
		    nfingers == i + 1);
560
	nid = mt->tracking_id++;
561
	FOREACHBIT(mt->touches, slot)
562
		if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid)
563
			goto again;
564
565
	return (nid);
566
}
567
568
static inline int32_t
569
evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
570
{
571
	if (stmax != 0 && mtmax != mtmin) {
572
		value = (value - mtmin) * stmax / (mtmax - mtmin);
573
		value = MAX(MIN(value, stmax), 0);
574
	}
575
	return (value);
220
}
576
}
221
577
222
void
578
void
223
evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
579
evdev_support_mt_compat(struct evdev_dev *evdev)
224
{
580
{
581
	struct input_absinfo *ai;
582
	int i;
225
583
226
	EVDEV_ENTER(evdev);
584
	if (evdev->ev_absinfo == NULL)
227
	evdev_send_nfingers(evdev, nfingers);
585
		return;
228
	EVDEV_EXIT(evdev);
586
587
	evdev_support_event(evdev, EV_KEY);
588
	evdev_support_key(evdev, BTN_TOUCH);
589
590
	/* Touchscreens should not advertise tap tool capabilities */
591
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
592
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
593
594
	/* Echo 0-th MT-slot as ST-slot */
595
	for (i = 0; i < nitems(evdev_mtstmap); i++) {
596
		if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) ||
597
		     bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st))
598
			continue;
599
		ai = evdev->ev_absinfo + evdev_mtstmap[i].mt;
600
		evdev->ev_mt->mtst_events |= 1U << i;
601
		if (evdev_mtstmap[i].max != 0)
602
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
603
			    0,
604
			    evdev_mtstmap[i].max,
605
			    0,
606
			    evdev_mt_normalize(
607
			      ai->flat, 0, ai->maximum, evdev_mtstmap[i].max),
608
			    0);
609
		else
610
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
611
			    ai->minimum,
612
			    ai->maximum,
613
			    0,
614
			    ai->flat,
615
			    ai->resolution);
616
	}
229
}
617
}
230
618
231
void
619
static void
232
evdev_send_mt_compat(struct evdev_dev *evdev)
620
evdev_mt_send_st_compat(struct evdev_dev *evdev)
233
{
621
{
234
	int32_t nfingers, i;
622
	struct evdev_mt *mt = evdev->ev_mt;
623
	int nfingers, i, st_slot;
235
624
236
	EVDEV_LOCK_ASSERT(evdev);
625
	EVDEV_LOCK_ASSERT(evdev);
237
626
238
	nfingers = evdev_count_fingers(evdev);
627
	nfingers = bitcount(mt->touches);
239
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
628
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
240
629
241
	if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
630
	/* Send first active MT-slot state as single touch report */
242
		/* Echo 0-th MT-slot as ST-slot */
631
	st_slot = ffs(mt->touches) - 1;
243
		for (i = 0; i < nitems(evdev_mtstmap); i++)
632
	if (st_slot != -1)
244
			if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
633
		FOREACHBIT(mt->mtst_events, i)
245
				evdev_send_event(evdev, EV_ABS,
634
			evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st,
246
				    evdev_mtstmap[i][1],
635
			    evdev_mt_normalize(evdev_mt_get_value(evdev,
247
				    evdev_get_mt_value(evdev, 0,
636
			      st_slot, evdev_mtstmap[i].mt),
248
				    evdev_mtstmap[i][0]));
637
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum,
638
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum,
639
			      evdev_mtstmap[i].max));
249
640
250
	/* Touchscreens should not report tool taps */
641
	/* Touchscreens should not report tool taps */
251
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
642
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
Lines 260-283 evdev_push_mt_compat(struct evdev_dev *evdev) Link Here
260
{
651
{
261
652
262
	EVDEV_ENTER(evdev);
653
	EVDEV_ENTER(evdev);
263
	evdev_send_mt_compat(evdev);
654
	evdev_mt_send_st_compat(evdev);
264
	EVDEV_EXIT(evdev);
655
	EVDEV_EXIT(evdev);
265
}
656
}
266
657
267
void
658
static void
268
evdev_send_mt_autorel(struct evdev_dev *evdev)
659
evdev_mt_send_autorel(struct evdev_dev *evdev)
269
{
660
{
270
	int32_t slot;
661
	struct evdev_mt *mt = evdev->ev_mt;
662
	int slot;
271
663
272
	EVDEV_LOCK_ASSERT(evdev);
664
	EVDEV_LOCK_ASSERT(evdev);
665
	KASSERT(mt->match_frame == 0, ("Unmatched events exist"));
273
666
274
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
667
	FOREACHBIT(mt->touches & ~mt->frame, slot)
275
		if (evdev->ev_mt->ev_mt_slots[slot].ev_report !=
668
		evdev_mt_send_slot(evdev, slot, NULL);
276
		    evdev->ev_report_count &&
669
}
277
		    evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
670
278
			evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
671
void
279
			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,
672
evdev_mt_push_autorel(struct evdev_dev *evdev)
280
			    -1);
673
{
281
		}
674
	EVDEV_ENTER(evdev);
282
	}
675
	evdev_mt_send_autorel(evdev);
676
	EVDEV_EXIT(evdev);
283
}
677
}
(-)b/sys/dev/evdev/evdev_private.h (-6 / +24 lines)
Lines 247-252 struct evdev_client Link Here
247
    (((client)->ec_buffer_ready + (client)->ec_buffer_size - \
247
    (((client)->ec_buffer_ready + (client)->ec_buffer_size - \
248
      (client)->ec_buffer_head) % (client)->ec_buffer_size)
248
      (client)->ec_buffer_head) % (client)->ec_buffer_size)
249
249
250
/* bitstring(3) helpers */
251
static inline void
252
bit_change(bitstr_t *bitstr, int bit, int value)
253
{
254
	if (value)
255
		bit_set(bitstr, bit);
256
	else
257
		bit_clear(bitstr, bit);
258
}
259
#define	bit_foreach_at(_bitstr, _start, _nbits, _iter)			\
260
	for (bit_ffs_at((_bitstr), (_start), (_nbits), &(_iter));	\
261
	     (_iter) != -1;						\
262
	     bit_ffs_at((_bitstr), (_iter) + 1, (_nbits), &(_iter)))
263
#define	bit_foreach(_bitstr, _nbits, _iter)				\
264
	bit_foreach_at(_bitstr, /*start*/0, _nbits, _iter)
265
250
/* Input device interface: */
266
/* Input device interface: */
251
void evdev_send_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
267
void evdev_send_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
252
int evdev_inject_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
268
int evdev_inject_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
Lines 269-282 void evdev_revoke_client(struct evdev_client *); Link Here
269
/* Multitouch related functions: */
285
/* Multitouch related functions: */
270
void evdev_mt_init(struct evdev_dev *);
286
void evdev_mt_init(struct evdev_dev *);
271
void evdev_mt_free(struct evdev_dev *);
287
void evdev_mt_free(struct evdev_dev *);
272
int32_t evdev_get_last_mt_slot(struct evdev_dev *);
288
void evdev_mt_sync_frame(struct evdev_dev *);
273
void evdev_set_last_mt_slot(struct evdev_dev *, int32_t);
289
int evdev_mt_get_last_slot(struct evdev_dev *);
274
int32_t evdev_get_mt_value(struct evdev_dev *, int32_t, int16_t);
290
void evdev_mt_set_last_slot(struct evdev_dev *, int);
275
void evdev_set_mt_value(struct evdev_dev *, int32_t, int16_t, int32_t);
291
int32_t evdev_mt_get_value(struct evdev_dev *, int, int16_t);
276
void evdev_send_mt_compat(struct evdev_dev *);
292
void evdev_mt_set_value(struct evdev_dev *, int, int16_t, int32_t);
277
void evdev_send_mt_autorel(struct evdev_dev *);
293
bool evdev_mt_record_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
294
int32_t evdev_mt_reassign_id(struct evdev_dev *, int, int32_t);
278
295
279
/* Utility functions: */
296
/* Utility functions: */
280
void evdev_client_dumpqueue(struct evdev_client *);
297
void evdev_client_dumpqueue(struct evdev_client *);
298
void evdev_send_nfingers(struct evdev_dev *, int);
281
299
282
#endif	/* _DEV_EVDEV_EVDEV_PRIVATE_H */
300
#endif	/* _DEV_EVDEV_EVDEV_PRIVATE_H */
(-)b/sys/dev/evdev/evdev_utils.c (+41 lines)
Lines 38-43 Link Here
38
#include <sys/systm.h>
38
#include <sys/systm.h>
39
39
40
#include <dev/evdev/evdev.h>
40
#include <dev/evdev/evdev.h>
41
#include <dev/evdev/evdev_private.h>
41
#include <dev/evdev/input.h>
42
#include <dev/evdev/input.h>
42
43
43
#define	NONE	KEY_RESERVED
44
#define	NONE	KEY_RESERVED
Lines 205-210 static uint16_t evdev_led_codes[] = { Link Here
205
	LED_SCROLLL,	/* SLKED */
206
	LED_SCROLLL,	/* SLKED */
206
};
207
};
207
208
209
static uint16_t evdev_nfinger_codes[] = {
210
	BTN_TOOL_FINGER,
211
	BTN_TOOL_DOUBLETAP,
212
	BTN_TOOL_TRIPLETAP,
213
	BTN_TOOL_QUADTAP,
214
	BTN_TOOL_QUINTTAP,
215
};
216
208
uint16_t
217
uint16_t
209
evdev_hid2key(int scancode)
218
evdev_hid2key(int scancode)
210
{
219
{
Lines 300-302 evdev_push_repeats(struct evdev_dev *evdev, keyboard_t *kbd) Link Here
300
	evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
309
	evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
301
	evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
310
	evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
302
}
311
}
312
313
void
314
evdev_support_nfingers(struct evdev_dev *evdev, int nfingers)
315
{
316
	int i;
317
318
	for (i = 0; i < MIN(nitems(evdev_nfinger_codes), nfingers); i++)
319
		evdev_support_key(evdev, evdev_nfinger_codes[i]);
320
}
321
322
void
323
evdev_send_nfingers(struct evdev_dev *evdev, int nfingers)
324
{
325
	int i;
326
327
	EVDEV_LOCK_ASSERT(evdev);
328
329
	if (nfingers > nitems(evdev_nfinger_codes))
330
		nfingers = nitems(evdev_nfinger_codes);
331
332
	for (i = 0; i < nitems(evdev_nfinger_codes); i++)
333
		evdev_send_event(evdev, EV_KEY, evdev_nfinger_codes[i],
334
			nfingers == i + 1);
335
}
336
337
void
338
evdev_push_nfingers(struct evdev_dev *evdev, int nfingers)
339
{
340
	EVDEV_ENTER(evdev);
341
	evdev_send_nfingers(evdev, nfingers);
342
	EVDEV_EXIT(evdev);
343
}
(-)b/sys/dev/evdev/uinput.c (+1 lines)
Lines 495-500 uinput_ioctl_sub(struct uinput_cdev_state *state, u_long cmd, caddr_t data) Link Here
495
495
496
		evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods);
496
		evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods);
497
		evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT);
497
		evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT);
498
		evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_MT_KEEPID);
498
		ret = evdev_register(state->ucs_evdev);
499
		ret = evdev_register(state->ucs_evdev);
499
		if (ret == 0)
500
		if (ret == 0)
500
			state->ucs_state = UINPUT_RUNNING;
501
			state->ucs_state = UINPUT_RUNNING;
(-)b/sys/dev/usb/input/wsp.c (-10 / +257 lines)
Lines 29-34 Link Here
29
#include <sys/cdefs.h>
29
#include <sys/cdefs.h>
30
__FBSDID("$FreeBSD$");
30
__FBSDID("$FreeBSD$");
31
31
32
#include "opt_evdev.h"
33
32
#include <sys/param.h>
34
#include <sys/param.h>
33
#include <sys/systm.h>
35
#include <sys/systm.h>
34
#include <sys/kernel.h>
36
#include <sys/kernel.h>
Lines 56-61 __FBSDID("$FreeBSD$"); Link Here
56
#define	USB_DEBUG_VAR wsp_debug
58
#define	USB_DEBUG_VAR wsp_debug
57
#include <dev/usb/usb_debug.h>
59
#include <dev/usb/usb_debug.h>
58
60
61
#ifdef EVDEV_SUPPORT
62
#include <dev/evdev/input.h>
63
#include <dev/evdev/evdev.h>
64
#endif
65
59
#include <sys/mouse.h>
66
#include <sys/mouse.h>
60
67
61
#define	WSP_DRIVER_NAME "wsp"
68
#define	WSP_DRIVER_NAME "wsp"
Lines 226-234 struct tp_finger { Link Here
226
} __packed;
233
} __packed;
227
234
228
/* trackpad finger data size, empirically at least ten fingers */
235
/* trackpad finger data size, empirically at least ten fingers */
236
#ifdef EVDEV_SUPPORT
237
#define	MAX_FINGERS		MAX_MT_SLOTS
238
#else
229
#define	MAX_FINGERS		16
239
#define	MAX_FINGERS		16
240
#endif
230
#define	SIZEOF_FINGER		sizeof(struct tp_finger)
241
#define	SIZEOF_FINGER		sizeof(struct tp_finger)
231
#define	SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
242
#define	SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
243
#define	MAX_FINGER_ORIENTATION	16384
232
244
233
#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
245
#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
234
#error "WSP_BUFFER_MAX is too small"
246
#error "WSP_BUFFER_MAX is too small"
Lines 251-256 enum { Link Here
251
	WSP_FLAG_MAX,
263
	WSP_FLAG_MAX,
252
};
264
};
253
265
266
/* device-specific parameters */
267
struct wsp_param {
268
	int snratio;			/* signal-to-noise ratio */
269
	int min;			/* device minimum reading */
270
	int max;			/* device maximum reading */
271
};
272
254
/* device-specific configuration */
273
/* device-specific configuration */
255
struct wsp_dev_params {
274
struct wsp_dev_params {
256
	uint8_t	caps;			/* device capability bitmask */
275
	uint8_t	caps;			/* device capability bitmask */
Lines 266-273 struct wsp_dev_params { Link Here
266
	uint8_t um_switch_idx;		/* usb control message mode switch index */
285
	uint8_t um_switch_idx;		/* usb control message mode switch index */
267
	uint8_t um_switch_on;		/* usb control message mode switch on */
286
	uint8_t um_switch_on;		/* usb control message mode switch on */
268
	uint8_t um_switch_off;		/* usb control message mode switch off */
287
	uint8_t um_switch_off;		/* usb control message mode switch off */
288
	struct wsp_param p;		/* finger pressure limits */
289
	struct wsp_param w;		/* finger width limits */
290
	struct wsp_param x;		/* horizontal limits */
291
	struct wsp_param y;		/* vertical limits */
292
	struct wsp_param o;		/* orientation limits */
269
};
293
};
270
294
295
/* logical signal quality */
296
#define	SN_PRESSURE	45		/* pressure signal-to-noise ratio */
297
#define	SN_WIDTH	25		/* width signal-to-noise ratio */
298
#define	SN_COORD	250		/* coordinate signal-to-noise ratio */
299
#define	SN_ORIENT	10		/* orientation signal-to-noise ratio */
300
271
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
301
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
272
	[WSP_FLAG_WELLSPRING1] = {
302
	[WSP_FLAG_WELLSPRING1] = {
273
		.caps = 0,
303
		.caps = 0,
Lines 283-288 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
283
		.um_switch_idx = 0,
313
		.um_switch_idx = 0,
284
		.um_switch_on = 0x01,
314
		.um_switch_on = 0x01,
285
		.um_switch_off = 0x08,
315
		.um_switch_off = 0x08,
316
		.p = { SN_PRESSURE, 0, 256 },
317
		.w = { SN_WIDTH, 0, 2048 },
318
		.x = { SN_COORD, -4824, 5342 },
319
		.y = { SN_COORD, -172, 5820 },
320
		.o = { SN_ORIENT,
321
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
286
	},
322
	},
287
	[WSP_FLAG_WELLSPRING2] = {
323
	[WSP_FLAG_WELLSPRING2] = {
288
		.caps = 0,
324
		.caps = 0,
Lines 298-303 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
298
		.um_switch_idx = 0,
334
		.um_switch_idx = 0,
299
		.um_switch_on = 0x01,
335
		.um_switch_on = 0x01,
300
		.um_switch_off = 0x08,
336
		.um_switch_off = 0x08,
337
		.p = { SN_PRESSURE, 0, 256 },
338
		.w = { SN_WIDTH, 0, 2048 },
339
		.x = { SN_COORD, -4824, 4824 },
340
		.y = { SN_COORD, -172, 4290 },
341
		.o = { SN_ORIENT,
342
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
301
	},
343
	},
302
	[WSP_FLAG_WELLSPRING3] = {
344
	[WSP_FLAG_WELLSPRING3] = {
303
		.caps = HAS_INTEGRATED_BUTTON,
345
		.caps = HAS_INTEGRATED_BUTTON,
Lines 313-318 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
313
		.um_switch_idx = 0,
355
		.um_switch_idx = 0,
314
		.um_switch_on = 0x01,
356
		.um_switch_on = 0x01,
315
		.um_switch_off = 0x08,
357
		.um_switch_off = 0x08,
358
		.p = { SN_PRESSURE, 0, 300 },
359
		.w = { SN_WIDTH, 0, 2048 },
360
		.x = { SN_COORD, -4460, 5166 },
361
		.y = { SN_COORD, -75, 6700 },
362
		.o = { SN_ORIENT,
363
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
316
	},
364
	},
317
	[WSP_FLAG_WELLSPRING4] = {
365
	[WSP_FLAG_WELLSPRING4] = {
318
		.caps = HAS_INTEGRATED_BUTTON,
366
		.caps = HAS_INTEGRATED_BUTTON,
Lines 328-333 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
328
		.um_switch_idx = 0,
376
		.um_switch_idx = 0,
329
		.um_switch_on = 0x01,
377
		.um_switch_on = 0x01,
330
		.um_switch_off = 0x08,
378
		.um_switch_off = 0x08,
379
		.p = { SN_PRESSURE, 0, 300 },
380
		.w = { SN_WIDTH, 0, 2048 },
381
		.x = { SN_COORD, -4620, 5140 },
382
		.y = { SN_COORD, -150, 6600 },
383
		.o = { SN_ORIENT,
384
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
331
	},
385
	},
332
	[WSP_FLAG_WELLSPRING4A] = {
386
	[WSP_FLAG_WELLSPRING4A] = {
333
		.caps = HAS_INTEGRATED_BUTTON,
387
		.caps = HAS_INTEGRATED_BUTTON,
Lines 343-348 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
343
		.um_switch_idx = 0,
397
		.um_switch_idx = 0,
344
		.um_switch_on = 0x01,
398
		.um_switch_on = 0x01,
345
		.um_switch_off = 0x08,
399
		.um_switch_off = 0x08,
400
		.p = { SN_PRESSURE, 0, 300 },
401
		.w = { SN_WIDTH, 0, 2048 },
402
		.x = { SN_COORD, -4616, 5112 },
403
		.y = { SN_COORD, -142, 5234 },
404
		.o = { SN_ORIENT,
405
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
346
	},
406
	},
347
	[WSP_FLAG_WELLSPRING5] = {
407
	[WSP_FLAG_WELLSPRING5] = {
348
		.caps = HAS_INTEGRATED_BUTTON,
408
		.caps = HAS_INTEGRATED_BUTTON,
Lines 358-363 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
358
		.um_switch_idx = 0,
418
		.um_switch_idx = 0,
359
		.um_switch_on = 0x01,
419
		.um_switch_on = 0x01,
360
		.um_switch_off = 0x08,
420
		.um_switch_off = 0x08,
421
		.p = { SN_PRESSURE, 0, 300 },
422
		.w = { SN_WIDTH, 0, 2048 },
423
		.x = { SN_COORD, -4415, 5050 },
424
		.y = { SN_COORD, -55, 6680 },
425
		.o = { SN_ORIENT,
426
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
361
	},
427
	},
362
	[WSP_FLAG_WELLSPRING6] = {
428
	[WSP_FLAG_WELLSPRING6] = {
363
		.caps = HAS_INTEGRATED_BUTTON,
429
		.caps = HAS_INTEGRATED_BUTTON,
Lines 373-378 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
373
		.um_switch_idx = 0,
439
		.um_switch_idx = 0,
374
		.um_switch_on = 0x01,
440
		.um_switch_on = 0x01,
375
		.um_switch_off = 0x08,
441
		.um_switch_off = 0x08,
442
		.p = { SN_PRESSURE, 0, 300 },
443
		.w = { SN_WIDTH, 0, 2048 },
444
		.x = { SN_COORD, -4620, 5140 },
445
		.y = { SN_COORD, -150, 6600 },
446
		.o = { SN_ORIENT,
447
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
376
	},
448
	},
377
	[WSP_FLAG_WELLSPRING5A] = {
449
	[WSP_FLAG_WELLSPRING5A] = {
378
		.caps = HAS_INTEGRATED_BUTTON,
450
		.caps = HAS_INTEGRATED_BUTTON,
Lines 388-393 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
388
		.um_switch_idx = 0,
460
		.um_switch_idx = 0,
389
		.um_switch_on = 0x01,
461
		.um_switch_on = 0x01,
390
		.um_switch_off = 0x08,
462
		.um_switch_off = 0x08,
463
		.p = { SN_PRESSURE, 0, 300 },
464
		.w = { SN_WIDTH, 0, 2048 },
465
		.x = { SN_COORD, -4750, 5280 },
466
		.y = { SN_COORD, -150, 6730 },
467
		.o = { SN_ORIENT,
468
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
391
	},
469
	},
392
	[WSP_FLAG_WELLSPRING6A] = {
470
	[WSP_FLAG_WELLSPRING6A] = {
393
		.caps = HAS_INTEGRATED_BUTTON,
471
		.caps = HAS_INTEGRATED_BUTTON,
Lines 402-407 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
402
		.um_switch_idx = 0,
480
		.um_switch_idx = 0,
403
		.um_switch_on = 0x01,
481
		.um_switch_on = 0x01,
404
		.um_switch_off = 0x08,
482
		.um_switch_off = 0x08,
483
		.p = { SN_PRESSURE, 0, 300 },
484
		.w = { SN_WIDTH, 0, 2048 },
485
		.x = { SN_COORD, -4620, 5140 },
486
		.y = { SN_COORD, -150, 6600 },
487
		.o = { SN_ORIENT,
488
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
405
	},
489
	},
406
	[WSP_FLAG_WELLSPRING7] = {
490
	[WSP_FLAG_WELLSPRING7] = {
407
		.caps = HAS_INTEGRATED_BUTTON,
491
		.caps = HAS_INTEGRATED_BUTTON,
Lines 417-422 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
417
		.um_switch_idx = 0,
501
		.um_switch_idx = 0,
418
		.um_switch_on = 0x01,
502
		.um_switch_on = 0x01,
419
		.um_switch_off = 0x08,
503
		.um_switch_off = 0x08,
504
		.p = { SN_PRESSURE, 0, 300 },
505
		.w = { SN_WIDTH, 0, 2048 },
506
		.x = { SN_COORD, -4750, 5280 },
507
		.y = { SN_COORD, -150, 6730 },
508
		.o = { SN_ORIENT,
509
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
420
	},
510
	},
421
	[WSP_FLAG_WELLSPRING7A] = {
511
	[WSP_FLAG_WELLSPRING7A] = {
422
		.caps = HAS_INTEGRATED_BUTTON,
512
		.caps = HAS_INTEGRATED_BUTTON,
Lines 432-437 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
432
		.um_switch_idx = 0,
522
		.um_switch_idx = 0,
433
		.um_switch_on = 0x01,
523
		.um_switch_on = 0x01,
434
		.um_switch_off = 0x08,
524
		.um_switch_off = 0x08,
525
		.p = { SN_PRESSURE, 0, 300 },
526
		.w = { SN_WIDTH, 0, 2048 },
527
		.x = { SN_COORD, -4750, 5280 },
528
		.y = { SN_COORD, -150, 6730 },
529
		.o = { SN_ORIENT,
530
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
435
	},
531
	},
436
	[WSP_FLAG_WELLSPRING8] = {
532
	[WSP_FLAG_WELLSPRING8] = {
437
		.caps = HAS_INTEGRATED_BUTTON,
533
		.caps = HAS_INTEGRATED_BUTTON,
Lines 447-452 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
447
		.um_switch_idx = 0,
543
		.um_switch_idx = 0,
448
		.um_switch_on = 0x01,
544
		.um_switch_on = 0x01,
449
		.um_switch_off = 0x08,
545
		.um_switch_off = 0x08,
546
		.p = { SN_PRESSURE, 0, 300 },
547
		.w = { SN_WIDTH, 0, 2048 },
548
		.x = { SN_COORD, -4620, 5140 },
549
		.y = { SN_COORD, -150, 6600 },
550
		.o = { SN_ORIENT,
551
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
450
	},
552
	},
451
	[WSP_FLAG_WELLSPRING9] = {
553
	[WSP_FLAG_WELLSPRING9] = {
452
		.caps = HAS_INTEGRATED_BUTTON,
554
		.caps = HAS_INTEGRATED_BUTTON,
Lines 462-467 static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = { Link Here
462
		.um_switch_idx = 1,
564
		.um_switch_idx = 1,
463
		.um_switch_on = 0x01,
565
		.um_switch_on = 0x01,
464
		.um_switch_off = 0x00,
566
		.um_switch_off = 0x00,
567
		.p = { SN_PRESSURE, 0, 300 },
568
		.w = { SN_WIDTH, 0, 2048 },
569
		.x = { SN_COORD, -4828, 5345 },
570
		.y = { SN_COORD, -203, 6803 },
571
		.o = { SN_ORIENT,
572
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
465
	},
573
	},
466
};
574
};
467
#define	WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
575
#define	WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
Lines 550-561 struct wsp_softc { Link Here
550
658
551
	const struct wsp_dev_params *sc_params;	/* device configuration */
659
	const struct wsp_dev_params *sc_params;	/* device configuration */
552
660
661
#ifdef EVDEV_SUPPORT
662
	struct evdev_dev *sc_evdev;
663
#endif
553
	mousehw_t sc_hw;
664
	mousehw_t sc_hw;
554
	mousemode_t sc_mode;
665
	mousemode_t sc_mode;
555
	u_int	sc_pollrate;
666
	u_int	sc_pollrate;
556
	mousestatus_t sc_status;
667
	mousestatus_t sc_status;
557
	u_int	sc_state;
668
	u_int	sc_state;
558
#define	WSP_ENABLED	       0x01
669
#define	WSP_ENABLED		0x01
670
#define	WSP_FIFO_STARTED	0x02
671
#define	WSP_EVDEV_OPENED	0x04
559
672
560
	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
673
	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
561
	int16_t	pos_x[MAX_FINGERS];	/* position array */
674
	int16_t	pos_x[MAX_FINGERS];	/* position array */
Lines 596-603 struct wsp_softc { Link Here
596
/*
709
/*
597
 * function prototypes
710
 * function prototypes
598
 */
711
 */
599
static usb_fifo_cmd_t wsp_start_read;
712
static usb_fifo_cmd_t wsp_fifo_start_read;
600
static usb_fifo_cmd_t wsp_stop_read;
713
static usb_fifo_cmd_t wsp_fifo_stop_read;
601
static usb_fifo_open_t wsp_open;
714
static usb_fifo_open_t wsp_open;
602
static usb_fifo_close_t wsp_close;
715
static usb_fifo_close_t wsp_close;
603
static usb_fifo_ioctl_t wsp_ioctl;
716
static usb_fifo_ioctl_t wsp_ioctl;
Lines 606-616 static struct usb_fifo_methods wsp_fifo_methods = { Link Here
606
	.f_open = &wsp_open,
719
	.f_open = &wsp_open,
607
	.f_close = &wsp_close,
720
	.f_close = &wsp_close,
608
	.f_ioctl = &wsp_ioctl,
721
	.f_ioctl = &wsp_ioctl,
609
	.f_start_read = &wsp_start_read,
722
	.f_start_read = &wsp_fifo_start_read,
610
	.f_stop_read = &wsp_stop_read,
723
	.f_stop_read = &wsp_fifo_stop_read,
611
	.basename[0] = WSP_DRIVER_NAME,
724
	.basename[0] = WSP_DRIVER_NAME,
612
};
725
};
613
726
727
#ifdef EVDEV_SUPPORT
728
static evdev_open_t wsp_ev_open;
729
static evdev_close_t wsp_ev_close;
730
static const struct evdev_methods wsp_evdev_methods = {
731
	.ev_open = &wsp_ev_open,
732
	.ev_close = &wsp_ev_close,
733
};
734
#endif
735
614
/* device initialization and shutdown */
736
/* device initialization and shutdown */
615
static int wsp_enable(struct wsp_softc *sc);
737
static int wsp_enable(struct wsp_softc *sc);
616
static void wsp_disable(struct wsp_softc *sc);
738
static void wsp_disable(struct wsp_softc *sc);
Lines 816-821 wsp_attach(device_t dev) Link Here
816
	sc->sc_touch = WSP_UNTOUCH;
938
	sc->sc_touch = WSP_UNTOUCH;
817
	sc->scr_mode = WSP_SCR_NONE;
939
	sc->scr_mode = WSP_SCR_NONE;
818
940
941
#ifdef EVDEV_SUPPORT
942
	sc->sc_evdev = evdev_alloc();
943
	evdev_set_name(sc->sc_evdev, device_get_desc(dev));
944
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
945
	evdev_set_id(sc->sc_evdev, BUS_USB, uaa->info.idVendor,
946
	    uaa->info.idProduct, 0);
947
	evdev_set_serial(sc->sc_evdev, usb_get_serial(uaa->device));
948
	evdev_set_methods(sc->sc_evdev, sc, &wsp_evdev_methods);
949
	evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
950
	evdev_support_event(sc->sc_evdev, EV_SYN);
951
	evdev_support_event(sc->sc_evdev, EV_ABS);
952
	evdev_support_event(sc->sc_evdev, EV_KEY);
953
954
#define WSP_SUPPORT_ABS(evdev, code, param)				\
955
	evdev_support_abs((evdev), (code), (param).min, (param).max,	\
956
	((param).max - (param).min) / (param).snratio, 0, 0);
957
958
	/* finger position */
959
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
960
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
961
	/* finger pressure */
962
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
963
	/* finger touch area */
964
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
965
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
966
	/* finger approach area */
967
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
968
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
969
	/* finger orientation */
970
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
971
	/* button properties */
972
	evdev_support_key(sc->sc_evdev, BTN_LEFT);
973
	if ((sc->sc_params->caps & HAS_INTEGRATED_BUTTON) != 0)
974
		evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
975
	/* Enable automatic touch assignment for type B MT protocol */
976
	evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
977
	    0, MAX_FINGERS - 1, 0, 0, 0);
978
	evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
979
	    -1, MAX_FINGERS - 1, 0, 0, 0);
980
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
981
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
982
	/* Synaptics compatibility events */
983
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
984
985
	err = evdev_register(sc->sc_evdev);
986
	if (err)
987
		goto detach;
988
#endif
989
819
	return (0);
990
	return (0);
820
991
821
detach:
992
detach:
Lines 837-842 wsp_detach(device_t dev) Link Here
837
1008
838
	usb_fifo_detach(&sc->sc_fifo);
1009
	usb_fifo_detach(&sc->sc_fifo);
839
1010
1011
#ifdef EVDEV_SUPPORT
1012
	evdev_free(sc->sc_evdev);
1013
#endif
1014
840
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
1015
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
841
1016
842
	mtx_destroy(&sc->sc_mutex);
1017
	mtx_destroy(&sc->sc_mutex);
Lines 929-936 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
929
			sc->pos_x[i] = f->abs_x;
1104
			sc->pos_x[i] = f->abs_x;
930
			sc->pos_y[i] = -f->abs_y;
1105
			sc->pos_y[i] = -f->abs_y;
931
			sc->index[i] = f;
1106
			sc->index[i] = f;
1107
#ifdef EVDEV_SUPPORT
1108
			if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1109
				union evdev_mt_slot slot_data = {
1110
					.id = i,
1111
					.x = f->abs_x,
1112
					.y = params->y.max + params->y.min - f->abs_y,
1113
					.p = f->pressure,
1114
					.maj = f->touch_major << 1,
1115
					.min = f->touch_minor << 1,
1116
					.w_maj = f->tool_major << 1,
1117
					.w_min = f->tool_minor << 1,
1118
					.ori = params->o.max - f->orientation,
1119
				};
1120
				evdev_mt_push_slot(sc->sc_evdev, i, &slot_data);
1121
			}
1122
#endif
932
		}
1123
		}
933
1124
1125
#ifdef EVDEV_SUPPORT
1126
		if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1127
			evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
1128
			evdev_sync(sc->sc_evdev);
1129
		}
1130
#endif
934
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
1131
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
935
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
1132
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
936
		sc->sc_status.obutton = sc->sc_status.button;
1133
		sc->sc_status.obutton = sc->sc_status.button;
Lines 1235-1243 wsp_reset_buf(struct wsp_softc *sc) Link Here
1235
}
1432
}
1236
1433
1237
static void
1434
static void
1238
wsp_start_read(struct usb_fifo *fifo)
1435
wsp_start_read(struct wsp_softc *sc)
1239
{
1436
{
1240
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1241
	int rate;
1437
	int rate;
1242
1438
1243
	/* Check if we should override the default polling interval */
1439
	/* Check if we should override the default polling interval */
Lines 1258-1267 wsp_start_read(struct usb_fifo *fifo) Link Here
1258
}
1454
}
1259
1455
1260
static void
1456
static void
1261
wsp_stop_read(struct usb_fifo *fifo)
1457
wsp_stop_read(struct wsp_softc *sc)
1262
{
1458
{
1263
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1264
1265
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1459
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1266
}
1460
}
1267
1461
Lines 1301-1306 wsp_close(struct usb_fifo *fifo, int fflags) Link Here
1301
	}
1495
	}
1302
}
1496
}
1303
1497
1498
static void
1499
wsp_fifo_start_read(struct usb_fifo *fifo)
1500
{
1501
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1502
1503
	if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1504
		wsp_start_read(sc);
1505
	sc->sc_state |= WSP_FIFO_STARTED;
1506
}
1507
1508
static void
1509
wsp_fifo_stop_read(struct usb_fifo *fifo)
1510
{
1511
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1512
1513
	sc->sc_state &= ~WSP_FIFO_STARTED;
1514
	if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1515
		wsp_stop_read(sc);
1516
}
1517
1518
#ifdef EVDEV_SUPPORT
1519
static int
1520
wsp_ev_open(struct evdev_dev *evdev)
1521
{
1522
	struct wsp_softc *sc = evdev_get_softc(evdev);
1523
1524
	mtx_lock(&sc->sc_mutex);
1525
	if ((sc->sc_state & WSP_FIFO_STARTED) == 0)
1526
		wsp_start_read(sc);
1527
	sc->sc_state |= WSP_EVDEV_OPENED;
1528
	mtx_unlock(&sc->sc_mutex);
1529
1530
	return (0);
1531
}
1532
1533
static int
1534
wsp_ev_close(struct evdev_dev *evdev)
1535
{
1536
	struct wsp_softc *sc = evdev_get_softc(evdev);
1537
1538
	mtx_lock(&sc->sc_mutex);
1539
	sc->sc_state &= ~WSP_EVDEV_OPENED;
1540
	if ((sc->sc_state & WSP_FIFO_STARTED) == 0)
1541
		wsp_stop_read(sc);
1542
	mtx_unlock(&sc->sc_mutex);
1543
1544
	return (0);
1545
}
1546
#endif
1547
1304
int
1548
int
1305
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1549
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1306
{
1550
{
Lines 1412-1416 static devclass_t wsp_devclass; Link Here
1412
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1656
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1413
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1657
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1414
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1658
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1659
#ifdef EVDEV_SUPPORT
1660
MODULE_DEPEND(wsp, evdev, 1, 1, 1);
1661
#endif
1415
MODULE_VERSION(wsp, 1);
1662
MODULE_VERSION(wsp, 1);
1416
USB_PNP_HOST_INFO(wsp_devs);
1663
USB_PNP_HOST_INFO(wsp_devs);
(-)b/sys/modules/usb/wsp/Makefile (-2 / +2 lines)
Lines 30-36 S= ${SRCTOP}/sys Link Here
30
.PATH: $S/dev/usb/input
30
.PATH: $S/dev/usb/input
31
31
32
KMOD=	wsp
32
KMOD=	wsp
33
SRCS=	opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \
33
SRCS=	opt_bus.h opt_evdev.h opt_usb.h device_if.h bus_if.h usb_if.h \
34
	wsp.c
34
	vnode_if.h usbdevs.h wsp.c
35
35
36
.include <bsd.kmod.mk>
36
.include <bsd.kmod.mk>

Return to bug 252236