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 (-32 / +21 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 726-733 evdev_modify_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
726
		else if (!ABS_IS_MT(code))
717
		else if (!ABS_IS_MT(code))
727
			old_value = evdev->ev_absinfo[code].value;
718
			old_value = evdev->ev_absinfo[code].value;
728
		else if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
719
		else if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
729
			old_value = evdev_get_mt_value(evdev,
720
			old_value = evdev_mt_get_value(evdev,
730
			    evdev_get_last_mt_slot(evdev), code);
721
			    evdev_mt_get_last_slot(evdev), code);
731
		else	/* Pass MT protocol type A events as is */
722
		else	/* Pass MT protocol type A events as is */
732
			break;
723
			break;
733
724
Lines 807-813 evdev_sparse_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
807
		switch (code) {
798
		switch (code) {
808
		case ABS_MT_SLOT:
799
		case ABS_MT_SLOT:
809
			/* Postpone ABS_MT_SLOT till next event */
800
			/* Postpone ABS_MT_SLOT till next event */
810
			evdev_set_last_mt_slot(evdev, value);
801
			evdev_mt_set_last_slot(evdev, value);
811
			return (EV_SKIP_EVENT);
802
			return (EV_SKIP_EVENT);
812
803
813
		case ABS_MT_FIRST ... ABS_MT_LAST:
804
		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))
806
			if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
816
				break;
807
				break;
817
			/* Don`t repeat MT protocol type B events */
808
			/* Don`t repeat MT protocol type B events */
818
			last_mt_slot = evdev_get_last_mt_slot(evdev);
809
			last_mt_slot = evdev_mt_get_last_slot(evdev);
819
			if (evdev_get_mt_value(evdev, last_mt_slot, code)
810
			if (evdev_mt_get_value(evdev, last_mt_slot, code)
820
			     == value)
811
			     == value)
821
				return (EV_SKIP_EVENT);
812
				return (EV_SKIP_EVENT);
822
			evdev_set_mt_value(evdev, last_mt_slot, code, value);
813
			evdev_mt_set_value(evdev, last_mt_slot, code, value);
823
			if (last_mt_slot != CURRENT_MT_SLOT(evdev)) {
814
			if (last_mt_slot != CURRENT_MT_SLOT(evdev)) {
824
				CURRENT_MT_SLOT(evdev) = last_mt_slot;
815
				CURRENT_MT_SLOT(evdev) = last_mt_slot;
825
				evdev->ev_report_opened = true;
816
				evdev->ev_report_opened = true;
Lines 895-900 evdev_send_event(struct evdev_dev *evdev, uint16_t type, uint16_t code, Link Here
895
886
896
	EVDEV_LOCK_ASSERT(evdev);
887
	EVDEV_LOCK_ASSERT(evdev);
897
888
889
	evdev_modify_event(evdev, type, code, &value);
898
	sparse =  evdev_sparse_event(evdev, type, code, value);
890
	sparse =  evdev_sparse_event(evdev, type, code, value);
899
	switch (sparse) {
891
	switch (sparse) {
900
	case EV_REPORT_MT_SLOT:
892
	case EV_REPORT_MT_SLOT:
Lines 918-937 evdev_restore_after_kdb(struct evdev_dev *evdev) Link Here
918
	EVDEV_LOCK_ASSERT(evdev);
910
	EVDEV_LOCK_ASSERT(evdev);
919
911
920
	/* Report postponed leds */
912
	/* Report postponed leds */
921
	for (code = 0; code < LED_CNT; code++)
913
	bit_foreach(evdev->ev_kdb_led_states, LED_CNT, code)
922
		if (bit_test(evdev->ev_kdb_led_states, code))
914
		evdev_send_event(evdev, EV_LED, code,
923
			evdev_send_event(evdev, EV_LED, code,
915
		    !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);
916
	bit_nclear(evdev->ev_kdb_led_states, 0, LED_MAX);
926
917
927
	/* Release stuck keys (CTRL + ALT + ESC) */
918
	/* Release stuck keys (CTRL + ALT + ESC) */
928
	evdev_stop_repeat(evdev);
919
	evdev_stop_repeat(evdev);
929
	for (code = 0; code < KEY_CNT; code++) {
920
	bit_foreach(evdev->ev_key_states, KEY_CNT, code)
930
		if (bit_test(evdev->ev_key_states, code)) {
921
		evdev_send_event(evdev, EV_KEY, code, KEY_EVENT_UP);
931
			evdev_send_event(evdev, EV_KEY, code, KEY_EVENT_UP);
922
	evdev_send_event(evdev, EV_SYN, SYN_REPORT, 1);
932
			evdev_send_event(evdev, EV_SYN, SYN_REPORT, 1);
933
		}
934
	}
935
}
923
}
936
924
937
int
925
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);
950
		evdev_restore_after_kdb(evdev);
963
	}
951
	}
964
952
965
	evdev_modify_event(evdev, type, code, &value);
966
	if (type == EV_SYN && code == SYN_REPORT &&
953
	if (type == EV_SYN && code == SYN_REPORT &&
967
	     bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
954
	    bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
968
		evdev_send_mt_autorel(evdev);
955
		evdev_mt_sync_frame(evdev);
969
	if (type == EV_SYN && code == SYN_REPORT && evdev->ev_report_opened &&
956
	else
970
	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
957
		if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) &&
971
		evdev_send_mt_compat(evdev);
958
		    evdev_mt_record_event(evdev, type, code, value))
972
	evdev_send_event(evdev, type, code, value);
959
			goto exit;
973
960
961
	evdev_send_event(evdev, type, code, value);
962
exit:
974
	EVDEV_EXIT(evdev);
963
	EVDEV_EXIT(evdev);
975
964
976
	return (0);
965
	return (0);
(-)b/sys/dev/evdev/evdev.h (-3 / +36 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 */
93
#define	EVDEV_FLAG_MAX		0x1F
94
#define	EVDEV_FLAG_MAX		0x1F
94
#define	EVDEV_FLAG_CNT		(EVDEV_FLAG_MAX + 1)
95
#define	EVDEV_FLAG_CNT		(EVDEV_FLAG_MAX + 1)
95
96
Lines 102-107 struct evdev_methods Link Here
102
	evdev_keycode_t		*ev_set_keycode;
103
	evdev_keycode_t		*ev_set_keycode;
103
};
104
};
104
105
106
union evdev_mt_slot {
107
	int32_t         states[MT_CNT];
108
	struct {
109
		int32_t maj;		/* ABS_MT_TOUCH_MAJOR */
110
		int32_t min;		/* ABS_MT_TOUCH_MINOR */
111
		int32_t w_maj;		/* ABS_MT_WIDTH_MAJOR */
112
		int32_t w_min;		/* ABS_MT_WIDTH_MINOR */
113
		int32_t ori;		/* ABS_MT_ORIENTATION */
114
		int32_t x;		/* ABS_MT_POSITION_X */
115
		int32_t y;		/* ABS_MT_POSITION_Y */
116
		int32_t type;		/* ABS_MT_TOOL_TYPE */
117
		int32_t blob_id;	/* ABS_MT_BLOB_ID */
118
		int32_t id;		/* ABS_MT_TRACKING_ID */
119
		int32_t p;		/* ABS_MT_PRESSURE */
120
		int32_t dist;		/* ABS_MT_DISTANCE */
121
		int32_t tool_x;		/* ABS_MT_TOOL_X */
122
		int32_t tool_y;		/* ABS_MT_TOOL_Y */
123
	};
124
};
125
_Static_assert(offsetof(union evdev_mt_slot, tool_y) ==
126
    offsetof(union evdev_mt_slot, states[ABS_MT_INDEX(ABS_MT_TOOL_Y)]),
127
    "evdev_mt_slot array members does not match their structure aliases");
128
105
/* Input device interface: */
129
/* Input device interface: */
106
struct evdev_dev *evdev_alloc(void);
130
struct evdev_dev *evdev_alloc(void);
107
void evdev_free(struct evdev_dev *);
131
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 *);
155
void *evdev_get_softc(struct evdev_dev *);
132
156
133
/* Multitouch related functions: */
157
/* Multitouch related functions: */
134
int32_t evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
158
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 *);
159
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 *);
160
void evdev_push_mt_compat(struct evdev_dev *);
161
int evdev_mt_push_slot(struct evdev_dev *, int, union evdev_mt_slot *);
162
int evdev_mt_push_frame(struct evdev_dev *, union evdev_mt_slot *, int);
163
union evdev_mt_slot *evdev_mt_get_match_slots(struct evdev_dev *);
164
void evdev_mt_push_autorel(struct evdev_dev *);
165
static __inline int
166
evdev_mt_id_to_slot(struct evdev_dev *evdev, int32_t id)
167
{
168
	return (evdev_get_mt_slot_by_tracking_id(evdev, id));
169
}
139
170
140
/* Utility functions: */
171
/* Utility functions: */
141
uint16_t evdev_hid2key(int);
172
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);
175
void evdev_push_mouse_btn(struct evdev_dev *, int);
145
void evdev_push_leds(struct evdev_dev *, int);
176
void evdev_push_leds(struct evdev_dev *, int);
146
void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
177
void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
178
void evdev_support_nfingers(struct evdev_dev *, int);
179
void evdev_push_nfingers(struct evdev_dev *, int);
147
180
148
/* Event reporting shortcuts: */
181
/* Event reporting shortcuts: */
149
static __inline int
182
static __inline int
(-)b/sys/dev/evdev/evdev_mt.c (-135 / +472 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
#define FOREACHBIT(v, i) \
46
	BTN_TOOL_FINGER,
61
	for ((i) = ffs(v) - 1; (i) != -1; (i) = ffs((v) & (~1 << (i))) - 1)
47
	BTN_TOOL_DOUBLETAP,
48
	BTN_TOOL_TRIPLETAP,
49
	BTN_TOOL_QUADTAP,
50
	BTN_TOOL_QUINTTAP,
51
};
52
62
53
static uint16_t evdev_mtstmap[][2] = {
63
#define	INITIAL_SLOT	-1
54
	{ ABS_MT_POSITION_X, ABS_X },
55
	{ ABS_MT_POSITION_Y, ABS_Y },
56
	{ ABS_MT_PRESSURE, ABS_PRESSURE },
57
	{ ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH },
58
};
59
64
60
struct evdev_mt_slot {
65
struct {
61
	uint64_t ev_report;
66
	uint16_t	mt;
62
	int32_t ev_mt_states[MT_CNT];
67
	uint16_t	st;
68
	int32_t		max;
69
} static evdev_mtstmap[] = {
70
	{ ABS_MT_POSITION_X,	ABS_X,		0 },
71
	{ ABS_MT_POSITION_Y,	ABS_Y,		0 },
72
	{ ABS_MT_PRESSURE,	ABS_PRESSURE,	255 },
73
	{ ABS_MT_TOUCH_MAJOR,	ABS_TOOL_WIDTH,	15 },
63
};
74
};
64
75
65
struct evdev_mt {
76
struct evdev_mt {
66
	int32_t	ev_mt_last_reported_slot;
77
	int			last_reported_slot;
67
	struct evdev_mt_slot ev_mt_slots[];
78
	bool			type_a;
79
	u_int			mtst_events;
80
	/* the set of slots with active touches */
81
	u_int			touches;
82
	/* the set of slots with unsynchronized state */
83
	u_int			frame;
84
	/* the set of slots to match with active touches */
85
	u_int			match_frame;
86
	int			match_slot;
87
	union evdev_mt_slot	*match_slots;
88
	int			*matrix;
89
	union evdev_mt_slot	slots[];
68
};
90
};
91
_Static_assert(MAX_MT_SLOTS <= sizeof(((struct evdev_mt *)0)->touches) * 8,
92
    "MAX_MT_SLOTS exceeds size of touches member of struct evdev_mt");
93
94
static void	evdev_mt_send_st_compat(struct evdev_dev *);
95
static void	evdev_mt_send_autorel(struct evdev_dev *);
96
static void	evdev_mt_replay_events(struct evdev_dev *);
69
97
70
void
98
void
71
evdev_mt_init(struct evdev_dev *evdev)
99
evdev_mt_init(struct evdev_dev *evdev)
72
{
100
{
73
	int32_t slot, slots;
101
	struct evdev_mt *mt;
102
	int slot, slots;
103
	size_t size = offsetof(struct evdev_mt, slots);
74
104
75
	slots = MAXIMAL_MT_SLOT(evdev) + 1;
105
	slots = MAXIMAL_MT_SLOT(evdev) + 1;
106
	size += sizeof(mt->slots[0]) * slots;
107
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
108
		size += sizeof(mt->match_slots[0]) * slots;
109
		size += sizeof(mt->matrix[0]) * (slots + 6) * slots;
110
	}
76
111
77
	evdev->ev_mt = malloc(offsetof(struct evdev_mt, ev_mt_slots) +
112
	mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO);
78
	     sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
113
	evdev->ev_mt = mt;
79
114
80
	/* Initialize multitouch protocol type B states */
115
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
81
	for (slot = 0; slot < slots; slot++) {
82
		/*
116
		/*
83
		 * .ev_report should not be initialized to initial value of
117
		 * We can not distinct MT type A/B protocols by MT_SLOT event
84
		 * report counter (0) as it brokes free slot detection in
118
		 * as it defines number of touches so use ABS_MT_TRACKING_ID.
85
		 * evdev_get_mt_slot_by_tracking_id. So initialize it to -1
86
		 */
119
		 */
87
		evdev->ev_mt->ev_mt_slots[slot] = (struct evdev_mt_slot) {
120
		if (!bit_test(evdev->ev_abs_flags, ABS_MT_TRACKING_ID))
88
			.ev_report = 0xFFFFFFFFFFFFFFFFULL,
121
			mt->type_a = true;
89
			.ev_mt_states[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] = -1,
122
		evdev_support_abs(evdev,
90
		};
123
		    ABS_MT_TRACKING_ID, -1, slots - 1, 0, 0, 0);
124
		mt->match_slots = evdev->ev_mt->slots + slots;
125
		mt->matrix = (int *)(mt->match_slots + slots);
91
	}
126
	}
92
127
128
	/* Initialize multitouch protocol type B states */
129
	for (slot = 0; slot < slots; slot++)
130
		mt->slots[slot].id = -1;
131
93
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
132
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
94
		evdev_support_mt_compat(evdev);
133
		evdev_support_mt_compat(evdev);
95
}
134
}
Lines 97-251 evdev_mt_init(struct evdev_dev *evdev) Link Here
97
void
136
void
98
evdev_mt_free(struct evdev_dev *evdev)
137
evdev_mt_free(struct evdev_dev *evdev)
99
{
138
{
100
101
	free(evdev->ev_mt, M_EVDEV);
139
	free(evdev->ev_mt, M_EVDEV);
102
}
140
}
103
141
104
int32_t
142
void
105
evdev_get_last_mt_slot(struct evdev_dev *evdev)
143
evdev_mt_sync_frame(struct evdev_dev *evdev)
144
{
145
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
146
		evdev_mt_replay_events(evdev);
147
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
148
		evdev_mt_send_autorel(evdev);
149
	if (evdev->ev_report_opened &&
150
	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
151
		evdev_mt_send_st_compat(evdev);
152
	evdev->ev_mt->frame = 0;
153
}
154
155
static void
156
evdev_mt_send_slot(struct evdev_dev *evdev, int slot,
157
    union evdev_mt_slot *state)
106
{
158
{
159
	int i;
160
161
	EVDEV_LOCK_ASSERT(evdev);
162
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
107
163
108
	return (evdev->ev_mt->ev_mt_last_reported_slot);
164
	evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
165
	if (state == NULL) {
166
		evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
167
		return;
168
	}
169
	bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i)
170
		evdev_send_event(evdev, EV_ABS, i,
171
		    state->states[ABS_MT_INDEX(i)]);
109
}
172
}
110
173
111
void
174
int
112
evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
175
evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
176
    union evdev_mt_slot *state)
113
{
177
{
178
	struct evdev_mt *mt = evdev->ev_mt;
179
180
	if (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev))
181
		return (EINVAL);
114
182
115
	evdev->ev_mt->ev_mt_slots[slot].ev_report = evdev->ev_report_count;
183
	EVDEV_ENTER(evdev);
116
	evdev->ev_mt->ev_mt_last_reported_slot = slot;
184
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
185
		evdev_mt_record_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
186
		if (state != NULL)
187
			mt->match_slots[mt->match_slot] = *state;
188
		else
189
			evdev_mt_record_event(evdev, EV_ABS,
190
			    ABS_MT_TRACKING_ID, -1);
191
	} else
192
		evdev_mt_send_slot(evdev, slot, state);
193
	EVDEV_EXIT(evdev);
194
195
	return (0);
117
}
196
}
118
197
119
inline int32_t
198
/*
120
evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
199
 * Find a minimum-weight matching for an m-by-n matrix.
200
 *
201
 * m must be greater than or equal to n. The size of the buffer must be
202
 * at least 3m + 3n.
203
 *
204
 * On return, the first m elements of the buffer contain the row-to-
205
 * column mappings, i.e., buffer[i] is the column index for row i, or -1
206
 * if there is no assignment for that row (which may happen if n < m).
207
 *
208
 * Wrong results because of overflows will not occur with input values
209
 * in the range of 0 to INT_MAX / 2 inclusive.
210
 *
211
 * The function applies the Dinic-Kronrod algorithm. It is not modern or
212
 * popular, but it seems to be a good choice for small matrices at least.
213
 * The original form of the algorithm is modified as follows: There is no
214
 * initial search for row minima, the initial assignments are in a
215
 * "virtual" column with the index -1 and zero values. This permits inputs
216
 * with n < m, and it simplifies the reassignments.
217
 */
218
static void
219
evdev_mt_matching(int *matrix, int m, int n, int *buffer)
220
{
221
	int i, j, k, d, e, row, col, delta;
222
	int *p;
223
	int *r2c = buffer;	/* row-to-column assignments */
224
	int *red = r2c + m;	/* reduced values of the assignments */
225
	int *mc = red + m;	/* row-wise minimal elements of cs */
226
	int *cs = mc + m;	/* the column set */
227
	int *c2r = cs + n;	/* column-to-row assignments in cs */
228
	int *cd = c2r + n;	/* column deltas (reduction) */
229
230
	for (p = r2c; p < red; *p++ = -1) {}
231
	for (; p < mc; *p++ = 0) {}
232
	for (col = 0; col < n; col++) {
233
		delta = INT_MAX;
234
		for (i = 0, p = matrix + col; i < m; i++, p += n) {
235
			d = *p - red[i];
236
			if (d < delta || (d == delta && r2c[i] < 0)) {
237
				delta = d;
238
				row = i;
239
			}
240
		}
241
		cd[col] = delta;
242
		if (r2c[row] < 0) {
243
			r2c[row] = col;
244
			continue;
245
		}
246
		for (p = mc; p < cs; *p++ = col) {}
247
		for (k = 0; (j = r2c[row]) >= 0;) {
248
			cs[k++] = j;
249
			c2r[j] = row;
250
			mc[row] -= n;
251
			delta = INT_MAX;
252
			for (i = 0, p = matrix; i < m; i++, p += n)
253
				if (mc[i] >= 0) {
254
					d = p[mc[i]] - cd[mc[i]];
255
					e = p[j] - cd[j];
256
					if (e < d) {
257
						d = e;
258
						mc[i] = j;
259
					}
260
					d -= red[i];
261
					if (d < delta || (d == delta
262
					    && r2c[i] < 0)) {
263
						delta = d;
264
						row = i;
265
					}
266
				}
267
			cd[col] += delta;
268
			for (i = 0; i < k; i++) {
269
				cd[cs[i]] += delta;
270
				red[c2r[cs[i]]] -= delta;
271
			}
272
		}
273
		for (j = mc[row]; (r2c[row] = j) != col;) {
274
			row = c2r[j];
275
			j = mc[row] + n;
276
		}
277
	}
278
}
279
280
/*
281
 * Assign slot numbers to the points in the pt array, and update all slots by
282
 * calling evdev_mt_send_slot internally.  The slot numbers are passed to the
283
 * caller in the pt->slot fields.
284
 *
285
 * The slot assignment pairs the points with points of the previous frame in
286
 * such a way that the sum of the squared distances is minimal.  Using
287
 * squares instead of simple distances favours assignments with more uniform
288
 * distances, and it is faster.
289
 */
290
static void
291
evdev_mt_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
121
{
292
{
293
	struct evdev_mt *mt = evdev->ev_mt;
294
	int i, j, m, n, dx, dy, slot, num_touches;
295
	int *p, *r2c, *c2r;
296
	u_int touches;
297
298
	EVDEV_LOCK_ASSERT(evdev);
299
	MPASS(mt->matrix != NULL);
300
	MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
301
302
	p = mt->matrix;
303
	touches = mt->touches;
304
	num_touches = bitcount(touches);
305
	if (num_touches >= size) {
306
		FOREACHBIT(touches, slot)
307
			for (i = 0; i < size; i++) {
308
				dx = pt[i].x - mt->slots[slot].x;
309
				dy = pt[i].y - mt->slots[slot].y;
310
				*p++ = dx * dx + dy * dy;
311
			}
312
		m = num_touches;
313
		n = size;
314
	} else {
315
		for (i = 0; i < size; i++)
316
			FOREACHBIT(touches, slot) {
317
				dx = pt[i].x - mt->slots[slot].x;
318
				dy = pt[i].y - mt->slots[slot].y;
319
				*p++ = dx * dx + dy * dy;
320
			}
321
		m = size;
322
		n = num_touches;
323
	}
324
	evdev_mt_matching(mt->matrix, m, n, p);
325
326
	r2c = p;
327
	c2r = p + m;
328
	for (i = 0; i < m; i++)
329
		if ((j = r2c[i]) >= 0)
330
			c2r[j] = i;
331
332
	p = (n == size ? c2r : r2c);
333
	for (i = 0; i < size; i++)
334
		if (*p++ < 0) {
335
			slot = ffs(~(mt->touches | mt->frame)) - 1;
336
			if (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev))
337
				break;
338
			pt[i].id = slot;
339
			evdev_mt_send_slot(evdev, slot, pt + i);
340
		}
122
341
123
	return (evdev->ev_mt->
342
	p = (n == size ? r2c : c2r);
124
	    ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
343
	FOREACHBIT(touches, slot)
344
		if ((i = *p++) >= 0) {
345
			pt[i].id = slot;
346
			evdev_mt_send_slot(evdev, slot, pt + i);
347
		} else {
348
			evdev_mt_send_slot(evdev, slot, NULL);
349
		}
125
}
350
}
126
351
127
inline void
352
int
128
evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
353
evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
129
    int32_t value)
130
{
354
{
355
	if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1)
356
		return (EINVAL);
357
358
	EVDEV_ENTER(evdev);
359
	evdev_mt_frame(evdev, pt, size);
360
	EVDEV_EXIT(evdev);
131
361
132
	evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
362
	return (0);
133
	    value;
134
}
363
}
135
364
136
int32_t
365
bool
137
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
366
evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
367
    int32_t value)
138
{
368
{
139
	int32_t tr_id, slot, free_slot = -1;
369
	struct evdev_mt *mt = evdev->ev_mt;
140
370
141
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
371
	EVDEV_LOCK_ASSERT(evdev);
142
		tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
372
143
		if (tr_id == tracking_id)
373
	switch (type) {
144
			return (slot);
374
	case EV_SYN:
145
		/*
375
		if (code == SYN_MT_REPORT) {
146
		 * Its possible that slot will be reassigned in a place of just
376
			/* MT protocol type A support */
147
		 * released one within the same report. To avoid this compare
377
			KASSERT(mt->type_a, ("Not a MT type A protocol"));
148
		 * report counter with slot`s report number updated with each
378
			mt->match_frame |= 1U << mt->match_slot;
149
		 * ABS_MT_TRACKING_ID change.
379
			mt->match_slot++;
150
		 */
380
			return (true);
151
		if (free_slot == -1 && tr_id == -1 &&
381
		}
152
		    evdev->ev_mt->ev_mt_slots[slot].ev_report !=
382
		break;
153
		    evdev->ev_report_count)
383
	case EV_ABS:
154
			free_slot = slot;
384
		if (code == ABS_MT_SLOT) {
385
			/* MT protocol type B support */
386
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
387
			KASSERT(value >= 0, ("Negative slot number"));
388
			mt->match_slot = value;
389
			mt->match_frame |= 1U << mt->match_slot;
390
			return (true);
391
		} else if (code == ABS_MT_TRACKING_ID) {
392
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
393
			if (value == -1)
394
				mt->match_frame &= ~(1U << mt->match_slot);
395
			return (true);
396
		} else if (ABS_IS_MT(code)) {
397
			KASSERT(mt->match_slot >= 0, ("Negative slot"));
398
			KASSERT(mt->match_slot <= MAXIMAL_MT_SLOT(evdev),
399
			    ("Slot number too big"));
400
			mt->match_slots[mt->match_slot].
401
			    states[ABS_MT_INDEX(code)] = value;
402
			return (true);
403
		}
404
		break;
405
	default:
406
		break;
155
	}
407
	}
156
408
157
	return (free_slot);
409
	return (false);
158
}
410
}
159
411
160
void
412
static void
161
evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
413
evdev_mt_replay_events(struct evdev_dev *evdev)
162
{
414
{
163
	int32_t i;
415
	struct evdev_mt *mt = evdev->ev_mt;
416
	int slot, size = 0;
417
418
	EVDEV_LOCK_ASSERT(evdev);
164
419
165
	for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
420
	FOREACHBIT(mt->match_frame, slot) {
166
		evdev_support_key(evdev, evdev_fngmap[i]);
421
		if (slot != size)
422
			mt->match_slots[size] = mt->match_slots[slot];
423
		size++;
424
	}
425
	if (size != 0)
426
		evdev_mt_frame(evdev, mt->match_slots, size);
427
	mt->match_slot = mt->type_a ? 0 : INITIAL_SLOT;
428
	mt->match_frame = 0;
167
}
429
}
168
430
169
void
431
union evdev_mt_slot *
170
evdev_support_mt_compat(struct evdev_dev *evdev)
432
evdev_mt_get_match_slots(struct evdev_dev *evdev)
171
{
433
{
172
	int32_t i;
434
	return (evdev->ev_mt->match_slots);
435
}
173
436
174
	if (evdev->ev_absinfo == NULL)
437
int
175
		return;
438
evdev_mt_get_last_slot(struct evdev_dev *evdev)
439
{
440
	return (evdev->ev_mt->last_reported_slot);
441
}
176
442
177
	evdev_support_event(evdev, EV_KEY);
443
void
178
	evdev_support_key(evdev, BTN_TOUCH);
444
evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
445
{
446
	struct evdev_mt *mt = evdev->ev_mt;
179
447
180
	/* Touchscreens should not advertise tap tool capabilities */
448
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
181
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
182
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
183
449
184
	/* Echo 0-th MT-slot as ST-slot */
450
	mt->frame |= 1U << slot;
185
	for (i = 0; i < nitems(evdev_mtstmap); i++)
451
	mt->last_reported_slot = slot;
186
		if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
187
			evdev_support_abs(evdev, evdev_mtstmap[i][1],
188
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
189
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
190
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
191
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
192
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
193
}
452
}
194
453
195
static int32_t
454
int32_t
196
evdev_count_fingers(struct evdev_dev *evdev)
455
evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code)
197
{
456
{
198
	int32_t nfingers = 0, i;
457
	struct evdev_mt *mt = evdev->ev_mt;
199
458
200
	for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
459
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
201
		if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
202
			nfingers++;
203
460
204
	return (nfingers);
461
	return (mt->slots[slot].states[ABS_MT_INDEX(code)]);
205
}
462
}
206
463
207
static void
464
void
208
evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
465
evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
466
    int32_t value)
209
{
467
{
210
	int32_t i;
468
	struct evdev_mt *mt = evdev->ev_mt;
211
469
212
	EVDEV_LOCK_ASSERT(evdev);
470
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
471
472
	if (code == ABS_MT_TRACKING_ID) {
473
		if (value != -1)
474
			mt->touches |= 1U << slot;
475
		else
476
			mt->touches &= ~(1U << slot);
477
	}
478
	mt->slots[slot].states[ABS_MT_INDEX(code)] = value;
479
}
213
480
214
	if (nfingers > nitems(evdev_fngmap))
481
int
215
		nfingers = nitems(evdev_fngmap);
482
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
483
{
484
	struct evdev_mt *mt = evdev->ev_mt;
485
	int slot;
486
487
	KASSERT(!mt->type_a, ("Not a MT type B protocol"));
488
489
	/*
490
	 * Ignore tracking_id if slot assignment is performed by evdev.
491
	 * Events are written sequentially to temporary matching buffer.
492
	 */
493
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
494
		if (mt->match_slot == INITIAL_SLOT)
495
			return (0);
496
		if ((mt->match_frame & (1U << mt->match_slot)) == 0)
497
			return (mt->match_slot);
498
		if (mt->match_slot >= MAXIMAL_MT_SLOT(evdev))
499
			return (-1);
500
		return (mt->match_slot + 1);
501
	}
502
	FOREACHBIT(mt->touches, slot)
503
		if (mt->slots[slot].id == tracking_id)
504
			return (slot);
505
	/*
506
	 * Do not allow allocation of new slot in a place of just
507
	 * released one within the same report.
508
	 */
509
	return (ffs(~(mt->touches | mt->frame)) - 1);
510
}
216
511
217
	for (i = 0; i < nitems(evdev_fngmap); i++)
512
static inline int32_t
218
		evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
513
evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
219
		    nfingers == i + 1);
514
{
515
	if (stmax != 0 && mtmax != mtmin) {
516
		value = (value - mtmin) * stmax / (mtmax - mtmin);
517
		value = MAX(MIN(value, stmax), 0);
518
	}
519
	return (value);
220
}
520
}
221
521
222
void
522
void
223
evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
523
evdev_support_mt_compat(struct evdev_dev *evdev)
224
{
524
{
525
	struct input_absinfo *ai;
526
	int i;
225
527
226
	EVDEV_ENTER(evdev);
528
	if (evdev->ev_absinfo == NULL)
227
	evdev_send_nfingers(evdev, nfingers);
529
		return;
228
	EVDEV_EXIT(evdev);
530
531
	evdev_support_event(evdev, EV_KEY);
532
	evdev_support_key(evdev, BTN_TOUCH);
533
534
	/* Touchscreens should not advertise tap tool capabilities */
535
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
536
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
537
538
	/* Echo 0-th MT-slot as ST-slot */
539
	for (i = 0; i < nitems(evdev_mtstmap); i++) {
540
		if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) ||
541
		     bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st))
542
			continue;
543
		ai = evdev->ev_absinfo + evdev_mtstmap[i].mt;
544
		evdev->ev_mt->mtst_events |= 1U << i;
545
		if (evdev_mtstmap[i].max != 0)
546
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
547
			    0,
548
			    evdev_mtstmap[i].max,
549
			    0,
550
			    evdev_mt_normalize(
551
			      ai->flat, 0, ai->maximum, evdev_mtstmap[i].max),
552
			    0);
553
		else
554
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
555
			    ai->minimum,
556
			    ai->maximum,
557
			    0,
558
			    ai->flat,
559
			    ai->resolution);
560
	}
229
}
561
}
230
562
231
void
563
static void
232
evdev_send_mt_compat(struct evdev_dev *evdev)
564
evdev_mt_send_st_compat(struct evdev_dev *evdev)
233
{
565
{
234
	int32_t nfingers, i;
566
	struct evdev_mt *mt = evdev->ev_mt;
567
	int nfingers, i, st_slot;
235
568
236
	EVDEV_LOCK_ASSERT(evdev);
569
	EVDEV_LOCK_ASSERT(evdev);
237
570
238
	nfingers = evdev_count_fingers(evdev);
571
	nfingers = bitcount(mt->touches);
239
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
572
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
240
573
241
	if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
574
	/* Send first active MT-slot state as single touch report */
242
		/* Echo 0-th MT-slot as ST-slot */
575
	st_slot = ffs(mt->touches) - 1;
243
		for (i = 0; i < nitems(evdev_mtstmap); i++)
576
	if (st_slot != -1)
244
			if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
577
		FOREACHBIT(mt->mtst_events, i)
245
				evdev_send_event(evdev, EV_ABS,
578
			evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st,
246
				    evdev_mtstmap[i][1],
579
			    evdev_mt_normalize(evdev_mt_get_value(evdev,
247
				    evdev_get_mt_value(evdev, 0,
580
			      st_slot, evdev_mtstmap[i].mt),
248
				    evdev_mtstmap[i][0]));
581
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum,
582
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum,
583
			      evdev_mtstmap[i].max));
249
584
250
	/* Touchscreens should not report tool taps */
585
	/* Touchscreens should not report tool taps */
251
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
586
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
Lines 260-283 evdev_push_mt_compat(struct evdev_dev *evdev) Link Here
260
{
595
{
261
596
262
	EVDEV_ENTER(evdev);
597
	EVDEV_ENTER(evdev);
263
	evdev_send_mt_compat(evdev);
598
	evdev_mt_send_st_compat(evdev);
264
	EVDEV_EXIT(evdev);
599
	EVDEV_EXIT(evdev);
265
}
600
}
266
601
267
void
602
static void
268
evdev_send_mt_autorel(struct evdev_dev *evdev)
603
evdev_mt_send_autorel(struct evdev_dev *evdev)
269
{
604
{
270
	int32_t slot;
605
	struct evdev_mt *mt = evdev->ev_mt;
606
	int slot;
271
607
272
	EVDEV_LOCK_ASSERT(evdev);
608
	EVDEV_LOCK_ASSERT(evdev);
273
609
274
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
610
	FOREACHBIT(mt->touches & ~mt->frame, slot)
275
		if (evdev->ev_mt->ev_mt_slots[slot].ev_report !=
611
		evdev_mt_send_slot(evdev, slot, NULL);
276
		    evdev->ev_report_count &&
612
}
277
		    evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
613
278
			evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
614
void
279
			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,
615
evdev_mt_push_autorel(struct evdev_dev *evdev)
280
			    -1);
616
{
281
		}
617
	EVDEV_ENTER(evdev);
282
	}
618
	evdev_mt_send_autorel(evdev);
619
	EVDEV_EXIT(evdev);
283
}
620
}
(-)b/sys/dev/evdev/evdev_private.h (-6 / +23 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);
278
294
279
/* Utility functions: */
295
/* Utility functions: */
280
void evdev_client_dumpqueue(struct evdev_client *);
296
void evdev_client_dumpqueue(struct evdev_client *);
297
void evdev_send_nfingers(struct evdev_dev *, int);
281
298
282
#endif	/* _DEV_EVDEV_EVDEV_PRIVATE_H */
299
#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/usb/input/wsp.c (-10 / +263 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
	    0, MAX_FINGERS - 1, 0, 0, 0);
980
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
981
	/* Synaptics compatibility events */
982
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
983
984
	err = evdev_register(sc->sc_evdev);
985
	if (err)
986
		goto detach;
987
#endif
988
819
	return (0);
989
	return (0);
820
990
821
detach:
991
detach:
Lines 837-842 wsp_detach(device_t dev) Link Here
837
1007
838
	usb_fifo_detach(&sc->sc_fifo);
1008
	usb_fifo_detach(&sc->sc_fifo);
839
1009
1010
#ifdef EVDEV_SUPPORT
1011
	evdev_free(sc->sc_evdev);
1012
#endif
1013
840
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
1014
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
841
1015
842
	mtx_destroy(&sc->sc_mutex);
1016
	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;
1103
			sc->pos_x[i] = f->abs_x;
930
			sc->pos_y[i] = -f->abs_y;
1104
			sc->pos_y[i] = -f->abs_y;
931
			sc->index[i] = f;
1105
			sc->index[i] = f;
1106
#ifdef EVDEV_SUPPORT
1107
			if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1108
				union evdev_mt_slot slot_data = {
1109
					.id = i,
1110
					.x = f->abs_x,
1111
					.y = params->y.max + params->y.min - f->abs_y,
1112
					.p = f->pressure,
1113
					.maj = f->touch_major << 1,
1114
					.min = f->touch_minor << 1,
1115
					.w_maj = f->tool_major << 1,
1116
					.w_min = f->tool_minor << 1,
1117
					.ori = params->o.max - f->orientation,
1118
				};
1119
				evdev_mt_push_slot(sc->sc_evdev, i, &slot_data);
1120
			}
1121
#endif
932
		}
1122
		}
933
1123
1124
#ifdef EVDEV_SUPPORT
1125
		if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1126
			/*
1127
			 * As EVDEV_FLAG_MT_AUTOREL is not set we should call
1128
			 * evdev_mt_push_autorel explicitly when no touches is
1129
			 * reported.
1130
			 */
1131
			if (ntouch == 0)
1132
				evdev_mt_push_autorel(sc->sc_evdev);
1133
			evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
1134
			evdev_sync(sc->sc_evdev);
1135
		}
1136
#endif
934
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
1137
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
935
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
1138
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
936
		sc->sc_status.obutton = sc->sc_status.button;
1139
		sc->sc_status.obutton = sc->sc_status.button;
Lines 1235-1243 wsp_reset_buf(struct wsp_softc *sc) Link Here
1235
}
1438
}
1236
1439
1237
static void
1440
static void
1238
wsp_start_read(struct usb_fifo *fifo)
1441
wsp_start_read(struct wsp_softc *sc)
1239
{
1442
{
1240
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1241
	int rate;
1443
	int rate;
1242
1444
1243
	/* Check if we should override the default polling interval */
1445
	/* Check if we should override the default polling interval */
Lines 1258-1267 wsp_start_read(struct usb_fifo *fifo) Link Here
1258
}
1460
}
1259
1461
1260
static void
1462
static void
1261
wsp_stop_read(struct usb_fifo *fifo)
1463
wsp_stop_read(struct wsp_softc *sc)
1262
{
1464
{
1263
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1264
1265
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1465
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1266
}
1466
}
1267
1467
Lines 1301-1306 wsp_close(struct usb_fifo *fifo, int fflags) Link Here
1301
	}
1501
	}
1302
}
1502
}
1303
1503
1504
static void
1505
wsp_fifo_start_read(struct usb_fifo *fifo)
1506
{
1507
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1508
1509
	if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1510
		wsp_start_read(sc);
1511
	sc->sc_state |= WSP_FIFO_STARTED;
1512
}
1513
1514
static void
1515
wsp_fifo_stop_read(struct usb_fifo *fifo)
1516
{
1517
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1518
1519
	sc->sc_state &= ~WSP_FIFO_STARTED;
1520
	if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1521
		wsp_stop_read(sc);
1522
}
1523
1524
#ifdef EVDEV_SUPPORT
1525
static int
1526
wsp_ev_open(struct evdev_dev *evdev)
1527
{
1528
	struct wsp_softc *sc = evdev_get_softc(evdev);
1529
1530
	mtx_lock(&sc->sc_mutex);
1531
	if ((sc->sc_state & WSP_FIFO_STARTED) == 0)
1532
		wsp_start_read(sc);
1533
	sc->sc_state |= WSP_EVDEV_OPENED;
1534
	mtx_unlock(&sc->sc_mutex);
1535
1536
	return (0);
1537
}
1538
1539
static int
1540
wsp_ev_close(struct evdev_dev *evdev)
1541
{
1542
	struct wsp_softc *sc = evdev_get_softc(evdev);
1543
1544
	mtx_lock(&sc->sc_mutex);
1545
	sc->sc_state &= ~WSP_EVDEV_OPENED;
1546
	if ((sc->sc_state & WSP_FIFO_STARTED) == 0)
1547
		wsp_stop_read(sc);
1548
	mtx_unlock(&sc->sc_mutex);
1549
1550
	return (0);
1551
}
1552
#endif
1553
1304
int
1554
int
1305
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1555
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1306
{
1556
{
Lines 1412-1416 static devclass_t wsp_devclass; Link Here
1412
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1662
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1413
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1663
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1414
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1664
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1665
#ifdef EVDEV_SUPPORT
1666
MODULE_DEPEND(wsp, evdev, 1, 1, 1);
1667
#endif
1415
MODULE_VERSION(wsp, 1);
1668
MODULE_VERSION(wsp, 1);
1416
USB_PNP_HOST_INFO(wsp_devs);
1669
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