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

Collapse All | Expand All

(-)b/sys/conf/files (+1 lines)
Lines 1820-1825 dev/gpio/gpio_if.m optional gpio Link Here
1820
dev/gpio/gpiobus_if.m		optional gpio
1820
dev/gpio/gpiobus_if.m		optional gpio
1821
dev/gpio/gpiopps.c		optional gpiopps fdt
1821
dev/gpio/gpiopps.c		optional gpiopps fdt
1822
dev/gpio/ofw_gpiobus.c		optional fdt gpio
1822
dev/gpio/ofw_gpiobus.c		optional fdt gpio
1823
dev/hid/bcm5974.c		optional bcm5974
1823
dev/hid/hconf.c			optional hconf
1824
dev/hid/hconf.c			optional hconf
1824
dev/hid/hcons.c			optional hcons
1825
dev/hid/hcons.c			optional hcons
1825
dev/hid/hgame.c			optional hgame
1826
dev/hid/hgame.c			optional hgame
(-)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_KEEPID	0x04	/* Do not reassign tracking ID */
94
#define	EVDEV_FLAG_MT_TRACK	0x05	/* Assign touch to slot by evdev */
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 / +533 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
		evdev_support_abs(evdev,
120
		    ABS_MT_TRACKING_ID, -1, MAX_MT_SLOTS - 1, 0, 0, 0);
121
	}
74
122
75
	slots = MAXIMAL_MT_SLOT(evdev) + 1;
123
	slots = MAXIMAL_MT_SLOT(evdev) + 1;
124
	size += sizeof(mt->slots[0]) * slots;
125
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
126
		size += sizeof(mt->match_slots[0]) * slots;
127
		size += sizeof(mt->matrix[0]) * (slots + 6) * slots;
128
	}
76
129
77
	evdev->ev_mt = malloc(offsetof(struct evdev_mt, ev_mt_slots) +
130
	mt = malloc(size, M_EVDEV, M_WAITOK | M_ZERO);
78
	     sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
131
	evdev->ev_mt = mt;
132
	mt->type_a = type_a;
79
133
80
	/* Initialize multitouch protocol type B states */
134
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
81
	for (slot = 0; slot < slots; slot++) {
135
		mt->match_slots = mt->slots + slots;
82
		/*
136
		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
	}
137
	}
92
138
139
	/* Initialize multitouch protocol type B states */
140
	for (slot = 0; slot < slots; slot++)
141
		mt->slots[slot].id = -1;
142
143
	if (!bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID))
144
		evdev_support_abs(evdev,
145
		    ABS_MT_TRACKING_ID, -1, UINT16_MAX, 0, 0, 0);
93
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
146
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
94
		evdev_support_mt_compat(evdev);
147
		evdev_support_mt_compat(evdev);
95
}
148
}
Lines 97-251 evdev_mt_init(struct evdev_dev *evdev) Link Here
97
void
150
void
98
evdev_mt_free(struct evdev_dev *evdev)
151
evdev_mt_free(struct evdev_dev *evdev)
99
{
152
{
100
101
	free(evdev->ev_mt, M_EVDEV);
153
	free(evdev->ev_mt, M_EVDEV);
102
}
154
}
103
155
104
int32_t
156
void
105
evdev_get_last_mt_slot(struct evdev_dev *evdev)
157
evdev_mt_sync_frame(struct evdev_dev *evdev)
158
{
159
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
160
		evdev_mt_replay_events(evdev);
161
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_AUTOREL))
162
		evdev_mt_send_autorel(evdev);
163
	if (evdev->ev_report_opened &&
164
	    bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
165
		evdev_mt_send_st_compat(evdev);
166
	evdev->ev_mt->frame = 0;
167
}
168
169
static void
170
evdev_mt_send_slot(struct evdev_dev *evdev, int slot,
171
    union evdev_mt_slot *state)
106
{
172
{
173
	int i;
174
	bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
175
176
	EVDEV_LOCK_ASSERT(evdev);
177
	MPASS(type_a || (slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev)));
178
	MPASS(!type_a || state != NULL);
179
180
	if (!type_a) {
181
		evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
182
		if (state == NULL) {
183
			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID, -1);
184
			return;
185
		}
186
	}
187
	bit_foreach_at(evdev->ev_abs_flags, ABS_MT_FIRST, ABS_MT_LAST + 1, i)
188
		evdev_send_event(evdev, EV_ABS, i,
189
		    state->val[ABS_MT_INDEX(i)]);
190
	if (type_a)
191
		evdev_send_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
192
}
193
194
int
195
evdev_mt_push_slot(struct evdev_dev *evdev, int slot,
196
    union evdev_mt_slot *state)
197
{
198
	struct evdev_mt *mt = evdev->ev_mt;
199
	bool type_a = !bit_test(evdev->ev_abs_flags, ABS_MT_SLOT);
200
201
	if ((type_a || (mt != NULL && mt->type_a)) && state == NULL)
202
		return (EINVAL);
203
	if (!type_a && (slot < 0 || slot > MAXIMAL_MT_SLOT(evdev)))
204
		return (EINVAL);
205
206
	EVDEV_ENTER(evdev);
207
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK) && mt->type_a) {
208
		mt->match_slots[mt->match_slot] = *state;
209
		evdev_mt_record_event(evdev, EV_SYN, SYN_MT_REPORT, 1);
210
	} else if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK)) {
211
		evdev_mt_record_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
212
		if (state != NULL)
213
			mt->match_slots[mt->match_slot] = *state;
214
		else
215
			evdev_mt_record_event(evdev, EV_ABS,
216
			    ABS_MT_TRACKING_ID, -1);
217
	} else
218
		evdev_mt_send_slot(evdev, slot, state);
219
	EVDEV_EXIT(evdev);
220
221
	return (0);
222
}
107
223
108
	return (evdev->ev_mt->ev_mt_last_reported_slot);
224
/*
225
 * Find a minimum-weight matching for an m-by-n matrix.
226
 *
227
 * m must be greater than or equal to n. The size of the buffer must be
228
 * at least 3m + 3n.
229
 *
230
 * On return, the first m elements of the buffer contain the row-to-
231
 * column mappings, i.e., buffer[i] is the column index for row i, or -1
232
 * if there is no assignment for that row (which may happen if n < m).
233
 *
234
 * Wrong results because of overflows will not occur with input values
235
 * in the range of 0 to INT_MAX / 2 inclusive.
236
 *
237
 * The function applies the Dinic-Kronrod algorithm. It is not modern or
238
 * popular, but it seems to be a good choice for small matrices at least.
239
 * The original form of the algorithm is modified as follows: There is no
240
 * initial search for row minima, the initial assignments are in a
241
 * "virtual" column with the index -1 and zero values. This permits inputs
242
 * with n < m, and it simplifies the reassignments.
243
 */
244
static void
245
evdev_mt_matching(int *matrix, int m, int n, int *buffer)
246
{
247
	int i, j, k, d, e, row, col, delta;
248
	int *p;
249
	int *r2c = buffer;	/* row-to-column assignments */
250
	int *red = r2c + m;	/* reduced values of the assignments */
251
	int *mc = red + m;	/* row-wise minimal elements of cs */
252
	int *cs = mc + m;	/* the column set */
253
	int *c2r = cs + n;	/* column-to-row assignments in cs */
254
	int *cd = c2r + n;	/* column deltas (reduction) */
255
256
	for (p = r2c; p < red; *p++ = -1) {}
257
	for (; p < mc; *p++ = 0) {}
258
	for (col = 0; col < n; col++) {
259
		delta = INT_MAX;
260
		for (i = 0, p = matrix + col; i < m; i++, p += n) {
261
			d = *p - red[i];
262
			if (d < delta || (d == delta && r2c[i] < 0)) {
263
				delta = d;
264
				row = i;
265
			}
266
		}
267
		cd[col] = delta;
268
		if (r2c[row] < 0) {
269
			r2c[row] = col;
270
			continue;
271
		}
272
		for (p = mc; p < cs; *p++ = col) {}
273
		for (k = 0; (j = r2c[row]) >= 0;) {
274
			cs[k++] = j;
275
			c2r[j] = row;
276
			mc[row] -= n;
277
			delta = INT_MAX;
278
			for (i = 0, p = matrix; i < m; i++, p += n)
279
				if (mc[i] >= 0) {
280
					d = p[mc[i]] - cd[mc[i]];
281
					e = p[j] - cd[j];
282
					if (e < d) {
283
						d = e;
284
						mc[i] = j;
285
					}
286
					d -= red[i];
287
					if (d < delta || (d == delta
288
					    && r2c[i] < 0)) {
289
						delta = d;
290
						row = i;
291
					}
292
				}
293
			cd[col] += delta;
294
			for (i = 0; i < k; i++) {
295
				cd[cs[i]] += delta;
296
				red[c2r[cs[i]]] -= delta;
297
			}
298
		}
299
		for (j = mc[row]; (r2c[row] = j) != col;) {
300
			row = c2r[j];
301
			j = mc[row] + n;
302
		}
303
	}
109
}
304
}
110
305
306
/*
307
 * Assign tracking IDs to the points in the pt array.  The tracking ID
308
 * assignment pairs the points with points of the previous frame in
309
 * such a way that the sum of the squared distances is minimal.  Using
310
 * squares instead of simple distances favours assignments with more uniform
311
 * distances, and it is faster.
312
 */
111
void
313
void
112
evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
314
evdev_mt_match_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt,
315
    int size)
113
{
316
{
317
	struct evdev_mt *mt = evdev->ev_mt;
318
	int i, j, m, n, dx, dy, slot, num_touches;
319
	int *p, *r2c, *c2r;
320
	u_int touches;
321
322
	EVDEV_LOCK_ASSERT(evdev);
323
	MPASS(mt->matrix != NULL);
324
	MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
325
326
	if (size == 0)
327
		return;
114
328
115
	evdev->ev_mt->ev_mt_slots[slot].ev_report = evdev->ev_report_count;
329
	p = mt->matrix;
116
	evdev->ev_mt->ev_mt_last_reported_slot = slot;
330
	touches = mt->touches;
331
	num_touches = bitcount(touches);
332
	if (num_touches >= size) {
333
		FOREACHBIT(touches, slot)
334
			for (i = 0; i < size; i++) {
335
				dx = pt[i].x - mt->slots[slot].x;
336
				dy = pt[i].y - mt->slots[slot].y;
337
				*p++ = dx * dx + dy * dy;
338
			}
339
		m = num_touches;
340
		n = size;
341
	} else {
342
		for (i = 0; i < size; i++)
343
			FOREACHBIT(touches, slot) {
344
				dx = pt[i].x - mt->slots[slot].x;
345
				dy = pt[i].y - mt->slots[slot].y;
346
				*p++ = dx * dx + dy * dy;
347
			}
348
		m = size;
349
		n = num_touches;
350
	}
351
	evdev_mt_matching(mt->matrix, m, n, p);
352
353
	r2c = p;
354
	c2r = p + m;
355
	for (i = 0; i < m; i++)
356
		if ((j = r2c[i]) >= 0)
357
			c2r[j] = i;
358
359
	p = (n == size ? r2c : c2r);
360
	FOREACHBIT(touches, slot)
361
		if ((i = *p++) >= 0)
362
			pt[i].id = mt->tracking_ids[slot];
363
364
	p = (n == size ? c2r : r2c);
365
	for (i = 0; i < size; i++)
366
		if (*p++ < 0)
367
			pt[i].id = -1;
117
}
368
}
118
369
119
inline int32_t
370
static void
120
evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
371
evdev_mt_send_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
121
{
372
{
373
	struct evdev_mt *mt = evdev->ev_mt;
374
	union evdev_mt_slot *slot;
122
375
123
	return (evdev->ev_mt->
376
	EVDEV_LOCK_ASSERT(evdev);
124
	    ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
377
	MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
378
379
	/*
380
	 * While MT-matching assign tracking IDs of new contacts to be equal
381
	 * to a slot number to make things simpler.
382
	 */
383
	for (slot = pt; slot < pt + size; slot++) {
384
		if (slot->id < 0)
385
			slot->id = ffc_slot(evdev, mt->touches | mt->frame);
386
		if (slot->id >= 0)
387
			evdev_mt_send_slot(evdev, slot->id, slot);
388
	}
125
}
389
}
126
390
127
inline void
391
int
128
evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
392
evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
393
{
394
	if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1)
395
		return (EINVAL);
396
397
	EVDEV_ENTER(evdev);
398
	evdev_mt_send_frame(evdev, pt, size);
399
	EVDEV_EXIT(evdev);
400
401
	return (0);
402
}
403
404
bool
405
evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
129
    int32_t value)
406
    int32_t value)
130
{
407
{
408
	struct evdev_mt *mt = evdev->ev_mt;
409
410
	EVDEV_LOCK_ASSERT(evdev);
411
412
	switch (type) {
413
	case EV_SYN:
414
		if (code == SYN_MT_REPORT) {
415
			/* MT protocol type A support */
416
			KASSERT(mt->type_a, ("Not a MT type A protocol"));
417
			mt->match_frame |= 1U << mt->match_slot;
418
			mt->match_slot++;
419
			return (true);
420
		}
421
		break;
422
	case EV_ABS:
423
		if (code == ABS_MT_SLOT) {
424
			/* MT protocol type B support */
425
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
426
			KASSERT(value >= 0, ("Negative slot number"));
427
			mt->match_slot = value;
428
			mt->match_frame |= 1U << mt->match_slot;
429
			return (true);
430
		} else if (code == ABS_MT_TRACKING_ID) {
431
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
432
			if (value == -1)
433
				mt->match_frame &= ~(1U << mt->match_slot);
434
			return (true);
435
		} else if (ABS_IS_MT(code)) {
436
			KASSERT(mt->match_slot >= 0, ("Negative slot"));
437
			KASSERT(mt->match_slot <= MAXIMAL_MT_SLOT(evdev),
438
			    ("Slot number too big"));
439
			mt->match_slots[mt->match_slot].
440
			    val[ABS_MT_INDEX(code)] = value;
441
			return (true);
442
		}
443
		break;
444
	default:
445
		break;
446
	}
131
447
132
	evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
448
	return (false);
133
	    value;
134
}
449
}
135
450
136
int32_t
451
static void
137
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
452
evdev_mt_replay_events(struct evdev_dev *evdev)
138
{
453
{
139
	int32_t tr_id, slot, free_slot = -1;
454
	struct evdev_mt *mt = evdev->ev_mt;
455
	int slot, size = 0;
140
456
141
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
457
	EVDEV_LOCK_ASSERT(evdev);
142
		tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
458
143
		if (tr_id == tracking_id)
459
	FOREACHBIT(mt->match_frame, slot) {
144
			return (slot);
460
		if (slot != size)
145
		/*
461
			mt->match_slots[size] = mt->match_slots[slot];
146
		 * Its possible that slot will be reassigned in a place of just
462
		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
	}
463
	}
464
	evdev_mt_match_frame(evdev, mt->match_slots, size);
465
	evdev_mt_send_frame(evdev, mt->match_slots, size);
466
	mt->match_slot = 0;
467
	mt->match_frame = 0;
468
}
469
470
union evdev_mt_slot *
471
evdev_mt_get_match_slots(struct evdev_dev *evdev)
472
{
473
	return (evdev->ev_mt->match_slots);
474
}
156
475
157
	return (free_slot);
476
int
477
evdev_mt_get_last_slot(struct evdev_dev *evdev)
478
{
479
	return (evdev->ev_mt->last_reported_slot);
158
}
480
}
159
481
160
void
482
void
161
evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
483
evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
162
{
484
{
163
	int32_t i;
485
	struct evdev_mt *mt = evdev->ev_mt;
486
487
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
164
488
165
	for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
489
	mt->frame |= 1U << slot;
166
		evdev_support_key(evdev, evdev_fngmap[i]);
490
	mt->last_reported_slot = slot;
167
}
491
}
168
492
169
void
493
int32_t
170
evdev_support_mt_compat(struct evdev_dev *evdev)
494
evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code)
171
{
495
{
172
	int32_t i;
496
	struct evdev_mt *mt = evdev->ev_mt;
173
497
174
	if (evdev->ev_absinfo == NULL)
498
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
175
		return;
176
499
177
	evdev_support_event(evdev, EV_KEY);
500
	return (mt->slots[slot].val[ABS_MT_INDEX(code)]);
178
	evdev_support_key(evdev, BTN_TOUCH);
501
}
179
502
180
	/* Touchscreens should not advertise tap tool capabilities */
503
void
181
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
504
evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
182
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
505
    int32_t value)
506
{
507
	struct evdev_mt *mt = evdev->ev_mt;
183
508
184
	/* Echo 0-th MT-slot as ST-slot */
509
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
185
	for (i = 0; i < nitems(evdev_mtstmap); i++)
510
186
		if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
511
	if (code == ABS_MT_TRACKING_ID) {
187
			evdev_support_abs(evdev, evdev_mtstmap[i][1],
512
		if (value != -1)
188
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
513
			mt->touches |= 1U << slot;
189
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
514
		else
190
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
515
			mt->touches &= ~(1U << slot);
191
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
516
	}
192
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
517
	mt->slots[slot].val[ABS_MT_INDEX(code)] = value;
193
}
518
}
194
519
195
static int32_t
520
int
196
evdev_count_fingers(struct evdev_dev *evdev)
521
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
197
{
522
{
198
	int32_t nfingers = 0, i;
523
	struct evdev_mt *mt = evdev->ev_mt;
524
	int slot;
525
526
	KASSERT(!mt->type_a, ("Not a MT type B protocol"));
199
527
200
	for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
528
	/*
201
		if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
529
	 * Ignore tracking_id if slot assignment is performed by evdev.
202
			nfingers++;
530
	 * Events are written sequentially to temporary matching buffer.
531
	 */
532
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
533
		return (ffc_slot(evdev, mt->match_frame));
203
534
204
	return (nfingers);
535
	FOREACHBIT(mt->touches, slot)
536
		if (mt->tracking_ids[slot] == tracking_id)
537
			return (slot);
538
	/*
539
	 * Do not allow allocation of new slot in a place of just
540
	 * released one within the same report.
541
	 */
542
	return (ffc_slot(evdev, mt->touches | mt->frame));
205
}
543
}
206
544
207
static void
545
int32_t
208
evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
546
evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id)
209
{
547
{
210
	int32_t i;
548
	struct evdev_mt *mt = evdev->ev_mt;
549
	int32_t nid;
211
550
212
	EVDEV_LOCK_ASSERT(evdev);
551
	if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) {
552
		mt->tracking_ids[slot] = id;
553
		return (id);
554
	}
555
556
	nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
557
	if (nid != -1) {
558
		KASSERT(id == mt->tracking_ids[slot],
559
		    ("MT-slot tracking id has changed"));
560
		return (nid);
561
	}
213
562
214
	if (nfingers > nitems(evdev_fngmap))
563
	mt->tracking_ids[slot] = id;
215
		nfingers = nitems(evdev_fngmap);
564
again:
565
	nid = mt->tracking_id++;
566
	FOREACHBIT(mt->touches, slot)
567
		if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid)
568
			goto again;
216
569
217
	for (i = 0; i < nitems(evdev_fngmap); i++)
570
	return (nid);
218
		evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
571
}
219
		    nfingers == i + 1);
572
573
static inline int32_t
574
evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
575
{
576
	if (stmax != 0 && mtmax != mtmin) {
577
		value = (value - mtmin) * stmax / (mtmax - mtmin);
578
		value = MAX(MIN(value, stmax), 0);
579
	}
580
	return (value);
220
}
581
}
221
582
222
void
583
void
223
evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
584
evdev_support_mt_compat(struct evdev_dev *evdev)
224
{
585
{
586
	struct input_absinfo *ai;
587
	int i;
225
588
226
	EVDEV_ENTER(evdev);
589
	if (evdev->ev_absinfo == NULL)
227
	evdev_send_nfingers(evdev, nfingers);
590
		return;
228
	EVDEV_EXIT(evdev);
591
592
	evdev_support_event(evdev, EV_KEY);
593
	evdev_support_key(evdev, BTN_TOUCH);
594
595
	/* Touchscreens should not advertise tap tool capabilities */
596
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
597
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
598
599
	/* Echo 0-th MT-slot as ST-slot */
600
	for (i = 0; i < nitems(evdev_mtstmap); i++) {
601
		if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) ||
602
		     bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st))
603
			continue;
604
		ai = evdev->ev_absinfo + evdev_mtstmap[i].mt;
605
		evdev->ev_mt->mtst_events |= 1U << i;
606
		if (evdev_mtstmap[i].max != 0)
607
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
608
			    0,
609
			    evdev_mtstmap[i].max,
610
			    0,
611
			    evdev_mt_normalize(
612
			      ai->flat, 0, ai->maximum, evdev_mtstmap[i].max),
613
			    0);
614
		else
615
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
616
			    ai->minimum,
617
			    ai->maximum,
618
			    0,
619
			    ai->flat,
620
			    ai->resolution);
621
	}
229
}
622
}
230
623
231
void
624
static void
232
evdev_send_mt_compat(struct evdev_dev *evdev)
625
evdev_mt_send_st_compat(struct evdev_dev *evdev)
233
{
626
{
234
	int32_t nfingers, i;
627
	struct evdev_mt *mt = evdev->ev_mt;
628
	int nfingers, i, st_slot;
235
629
236
	EVDEV_LOCK_ASSERT(evdev);
630
	EVDEV_LOCK_ASSERT(evdev);
237
631
238
	nfingers = evdev_count_fingers(evdev);
632
	nfingers = bitcount(mt->touches);
239
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
633
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
240
634
241
	if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
635
	/* Send first active MT-slot state as single touch report */
242
		/* Echo 0-th MT-slot as ST-slot */
636
	st_slot = ffs(mt->touches) - 1;
243
		for (i = 0; i < nitems(evdev_mtstmap); i++)
637
	if (st_slot != -1)
244
			if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
638
		FOREACHBIT(mt->mtst_events, i)
245
				evdev_send_event(evdev, EV_ABS,
639
			evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st,
246
				    evdev_mtstmap[i][1],
640
			    evdev_mt_normalize(evdev_mt_get_value(evdev,
247
				    evdev_get_mt_value(evdev, 0,
641
			      st_slot, evdev_mtstmap[i].mt),
248
				    evdev_mtstmap[i][0]));
642
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum,
643
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum,
644
			      evdev_mtstmap[i].max));
249
645
250
	/* Touchscreens should not report tool taps */
646
	/* Touchscreens should not report tool taps */
251
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
647
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
Lines 260-283 evdev_push_mt_compat(struct evdev_dev *evdev) Link Here
260
{
656
{
261
657
262
	EVDEV_ENTER(evdev);
658
	EVDEV_ENTER(evdev);
263
	evdev_send_mt_compat(evdev);
659
	evdev_mt_send_st_compat(evdev);
264
	EVDEV_EXIT(evdev);
660
	EVDEV_EXIT(evdev);
265
}
661
}
266
662
267
void
663
static void
268
evdev_send_mt_autorel(struct evdev_dev *evdev)
664
evdev_mt_send_autorel(struct evdev_dev *evdev)
269
{
665
{
270
	int32_t slot;
666
	struct evdev_mt *mt = evdev->ev_mt;
667
	int slot;
271
668
272
	EVDEV_LOCK_ASSERT(evdev);
669
	EVDEV_LOCK_ASSERT(evdev);
670
	KASSERT(mt->match_frame == 0, ("Unmatched events exist"));
273
671
274
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
672
	FOREACHBIT(mt->touches & ~mt->frame, slot)
275
		if (evdev->ev_mt->ev_mt_slots[slot].ev_report !=
673
		evdev_mt_send_slot(evdev, slot, NULL);
276
		    evdev->ev_report_count &&
674
}
277
		    evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
675
278
			evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
676
void
279
			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,
677
evdev_mt_push_autorel(struct evdev_dev *evdev)
280
			    -1);
678
{
281
		}
679
	EVDEV_ENTER(evdev);
282
	}
680
	evdev_mt_send_autorel(evdev);
681
	EVDEV_EXIT(evdev);
283
}
682
}
(-)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
int32_t evdev_mt_reassign_id(struct evdev_dev *, int, int32_t);
294
bool evdev_mt_record_event(struct evdev_dev *, uint16_t, uint16_t, 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/hid/bcm5974.c (+668 lines)
Added Link Here
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
4
 * Copyright (c) 2012 Huang Wen Hui
5
 * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org>
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include <sys/cdefs.h>
31
__FBSDID("$FreeBSD$");
32
33
#include <sys/param.h>
34
#include <sys/bus.h>
35
#include <sys/endian.h>
36
#include <sys/kernel.h>
37
#include <sys/malloc.h>
38
#include <sys/module.h>
39
#include <sys/sysctl.h>
40
#include <sys/systm.h>
41
42
#include <dev/evdev/input.h>
43
#include <dev/evdev/evdev.h>
44
45
#define HID_DEBUG_VAR   bcm5974_debug
46
#include <dev/hid/hid.h>
47
#include <dev/hid/hidbus.h>
48
#include <dev/hid/hidquirk.h>
49
50
#include "usbdevs.h"
51
52
#define	BCM5974_BUFFER_MAX	1024
53
#define	BCM5974_TLC_PAGE	HUP_DIGITIZERS
54
#define	BCM5974_TLC_USAGE	HUD_TOUCHPAD
55
56
/* Tunables */
57
static	SYSCTL_NODE(_hw_hid, OID_AUTO, bcm5974, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
58
    "HID wellspring touchpad");
59
60
#ifdef HID_DEBUG
61
enum wsp_log_level {
62
	BCM5974_LLEVEL_DISABLED = 0,
63
	BCM5974_LLEVEL_ERROR,
64
	BCM5974_LLEVEL_DEBUG,		/* for troubleshooting */
65
	BCM5974_LLEVEL_INFO,		/* for diagnostics */
66
};
67
/* the default is to only log errors */
68
static int bcm5974_debug = BCM5974_LLEVEL_ERROR;
69
70
SYSCTL_INT(_hw_hid_bcm5974, OID_AUTO, debug, CTLFLAG_RWTUN,
71
    &bcm5974_debug, BCM5974_LLEVEL_ERROR, "BCM5974 debug level");
72
#endif					/* HID_DEBUG */
73
74
/*
75
 * Some tables, structures, definitions and constant values for the
76
 * touchpad protocol has been copied from Linux's
77
 * "drivers/input/mouse/bcm5974.c" which has the following copyright
78
 * holders under GPLv2. All device specific code in this driver has
79
 * been written from scratch. The decoding algorithm is based on
80
 * output from FreeBSD's usbdump.
81
 *
82
 * Copyright (C) 2008      Henrik Rydberg (rydberg@euromail.se)
83
 * Copyright (C) 2008      Scott Shawcroft (scott.shawcroft@gmail.com)
84
 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
85
 * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
86
 * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
87
 * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
88
 * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
89
 * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
90
 * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
91
 */
92
93
/* button data structure */
94
struct bt_data {
95
	uint8_t	unknown1;		/* constant */
96
	uint8_t	button;			/* left button */
97
	uint8_t	rel_x;			/* relative x coordinate */
98
	uint8_t	rel_y;			/* relative y coordinate */
99
} __packed;
100
101
/* trackpad header types */
102
enum tp_type {
103
	TYPE1,			/* plain trackpad */
104
	TYPE2,			/* button integrated in trackpad */
105
	TYPE3,			/* additional header fields since June 2013 */
106
	TYPE4,                  /* additional header field for pressure data */
107
	TYPE_CNT
108
};
109
110
/* list of device capability bits */
111
#define	HAS_INTEGRATED_BUTTON	1
112
113
struct tp_type_params {
114
	uint8_t	caps;		/* device capability bitmask */
115
	uint8_t	button;		/* offset to button data */
116
	uint8_t	offset;		/* offset to trackpad finger data */
117
	uint8_t delta;		/* offset from header to finger struct */
118
} const static tp[TYPE_CNT] = {
119
	[TYPE1] = {
120
		.caps = 0,
121
		.button = 0,
122
		.offset = 13 * 2,
123
		.delta = 0,
124
	},
125
	[TYPE2] = {
126
		.caps = HAS_INTEGRATED_BUTTON,
127
		.button = 15,
128
		.offset = 15 * 2,
129
		.delta = 0,
130
	},
131
	[TYPE3] = {
132
		.caps = HAS_INTEGRATED_BUTTON,
133
		.button = 23,
134
		.offset = 19 * 2,
135
		.delta = 0,
136
	},
137
	[TYPE4] = {
138
		.caps = HAS_INTEGRATED_BUTTON,
139
		.button = 31,
140
		.offset = 23 * 2,
141
		.delta = 2,
142
	},
143
};
144
145
/* trackpad finger header - little endian */
146
struct tp_header {
147
	uint8_t	flag;
148
	uint8_t	sn0;
149
	uint16_t wFixed0;
150
	uint32_t dwSn1;
151
	uint32_t dwFixed1;
152
	uint16_t wLength;
153
	uint8_t	nfinger;
154
	uint8_t	ibt;
155
	int16_t	wUnknown[6];
156
	uint8_t	q1;
157
	uint8_t	q2;
158
} __packed;
159
160
/* trackpad finger structure - little endian */
161
struct tp_finger {
162
	int16_t	origin;			/* zero when switching track finger */
163
	int16_t	abs_x;			/* absolute x coodinate */
164
	int16_t	abs_y;			/* absolute y coodinate */
165
	int16_t	rel_x;			/* relative x coodinate */
166
	int16_t	rel_y;			/* relative y coodinate */
167
	int16_t	tool_major;		/* tool area, major axis */
168
	int16_t	tool_minor;		/* tool area, minor axis */
169
	int16_t	orientation;		/* 16384 when point, else 15 bit angle */
170
	int16_t	touch_major;		/* touch area, major axis */
171
	int16_t	touch_minor;		/* touch area, minor axis */
172
	int16_t	unused[2];		/* zeros */
173
	int16_t pressure;		/* pressure on forcetouch touchpad */
174
	int16_t	multi;			/* one finger: varies, more fingers:
175
				 	 * constant */
176
} __packed;
177
178
/* trackpad finger data size, empirically at least ten fingers */
179
#define	MAX_FINGERS		MAX_MT_SLOTS
180
181
#define	MAX_FINGER_ORIENTATION	16384
182
183
enum {
184
	BCM5974_FLAG_WELLSPRING1,
185
	BCM5974_FLAG_WELLSPRING2,
186
	BCM5974_FLAG_WELLSPRING3,
187
	BCM5974_FLAG_WELLSPRING4,
188
	BCM5974_FLAG_WELLSPRING4A,
189
	BCM5974_FLAG_WELLSPRING5,
190
	BCM5974_FLAG_WELLSPRING6A,
191
	BCM5974_FLAG_WELLSPRING6,
192
	BCM5974_FLAG_WELLSPRING5A,
193
	BCM5974_FLAG_WELLSPRING7,
194
	BCM5974_FLAG_WELLSPRING7A,
195
	BCM5974_FLAG_WELLSPRING8,
196
	BCM5974_FLAG_WELLSPRING9,
197
	BCM5974_FLAG_MAX,
198
};
199
200
/* device-specific parameters */
201
struct bcm5974_axis {
202
	int snratio;			/* signal-to-noise ratio */
203
	int min;			/* device minimum reading */
204
	int max;			/* device maximum reading */
205
};
206
207
/* device-specific configuration */
208
struct bcm5974_dev_params {
209
	const struct tp_type_params* tp;
210
	struct bcm5974_axis p;		/* finger pressure limits */
211
	struct bcm5974_axis w;		/* finger width limits */
212
	struct bcm5974_axis x;		/* horizontal limits */
213
	struct bcm5974_axis y;		/* vertical limits */
214
	struct bcm5974_axis o;		/* orientation limits */
215
};
216
217
/* logical signal quality */
218
#define	SN_PRESSURE	45		/* pressure signal-to-noise ratio */
219
#define	SN_WIDTH	25		/* width signal-to-noise ratio */
220
#define	SN_COORD	250		/* coordinate signal-to-noise ratio */
221
#define	SN_ORIENT	10		/* orientation signal-to-noise ratio */
222
223
static const struct bcm5974_dev_params bcm5974_dev_params[BCM5974_FLAG_MAX] = {
224
	[BCM5974_FLAG_WELLSPRING1] = {
225
		.tp = tp + TYPE1,
226
		.p = { SN_PRESSURE, 0, 256 },
227
		.w = { SN_WIDTH, 0, 2048 },
228
		.x = { SN_COORD, -4824, 5342 },
229
		.y = { SN_COORD, -172, 5820 },
230
		.o = { SN_ORIENT,
231
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
232
	},
233
	[BCM5974_FLAG_WELLSPRING2] = {
234
		.tp = tp + TYPE1,
235
		.p = { SN_PRESSURE, 0, 256 },
236
		.w = { SN_WIDTH, 0, 2048 },
237
		.x = { SN_COORD, -4824, 4824 },
238
		.y = { SN_COORD, -172, 4290 },
239
		.o = { SN_ORIENT,
240
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
241
	},
242
	[BCM5974_FLAG_WELLSPRING3] = {
243
		.tp = tp + TYPE2,
244
		.p = { SN_PRESSURE, 0, 300 },
245
		.w = { SN_WIDTH, 0, 2048 },
246
		.x = { SN_COORD, -4460, 5166 },
247
		.y = { SN_COORD, -75, 6700 },
248
		.o = { SN_ORIENT,
249
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
250
	},
251
	[BCM5974_FLAG_WELLSPRING4] = {
252
		.tp = tp + TYPE2,
253
		.p = { SN_PRESSURE, 0, 300 },
254
		.w = { SN_WIDTH, 0, 2048 },
255
		.x = { SN_COORD, -4620, 5140 },
256
		.y = { SN_COORD, -150, 6600 },
257
		.o = { SN_ORIENT,
258
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
259
	},
260
	[BCM5974_FLAG_WELLSPRING4A] = {
261
		.tp = tp + TYPE2,
262
		.p = { SN_PRESSURE, 0, 300 },
263
		.w = { SN_WIDTH, 0, 2048 },
264
		.x = { SN_COORD, -4616, 5112 },
265
		.y = { SN_COORD, -142, 5234 },
266
		.o = { SN_ORIENT,
267
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
268
	},
269
	[BCM5974_FLAG_WELLSPRING5] = {
270
		.tp = tp + TYPE2,
271
		.p = { SN_PRESSURE, 0, 300 },
272
		.w = { SN_WIDTH, 0, 2048 },
273
		.x = { SN_COORD, -4415, 5050 },
274
		.y = { SN_COORD, -55, 6680 },
275
		.o = { SN_ORIENT,
276
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
277
	},
278
	[BCM5974_FLAG_WELLSPRING6] = {
279
		.tp = tp + TYPE2,
280
		.p = { SN_PRESSURE, 0, 300 },
281
		.w = { SN_WIDTH, 0, 2048 },
282
		.x = { SN_COORD, -4620, 5140 },
283
		.y = { SN_COORD, -150, 6600 },
284
		.o = { SN_ORIENT,
285
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
286
	},
287
	[BCM5974_FLAG_WELLSPRING5A] = {
288
		.tp = tp + TYPE2,
289
		.p = { SN_PRESSURE, 0, 300 },
290
		.w = { SN_WIDTH, 0, 2048 },
291
		.x = { SN_COORD, -4750, 5280 },
292
		.y = { SN_COORD, -150, 6730 },
293
		.o = { SN_ORIENT,
294
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
295
	},
296
	[BCM5974_FLAG_WELLSPRING6A] = {
297
		.tp = tp + TYPE2,
298
		.p = { SN_PRESSURE, 0, 300 },
299
		.w = { SN_WIDTH, 0, 2048 },
300
		.x = { SN_COORD, -4620, 5140 },
301
		.y = { SN_COORD, -150, 6600 },
302
		.o = { SN_ORIENT,
303
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
304
	},
305
	[BCM5974_FLAG_WELLSPRING7] = {
306
		.tp = tp + TYPE2,
307
		.p = { SN_PRESSURE, 0, 300 },
308
		.w = { SN_WIDTH, 0, 2048 },
309
		.x = { SN_COORD, -4750, 5280 },
310
		.y = { SN_COORD, -150, 6730 },
311
		.o = { SN_ORIENT,
312
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
313
	},
314
	[BCM5974_FLAG_WELLSPRING7A] = {
315
		.tp = tp + TYPE2,
316
		.p = { SN_PRESSURE, 0, 300 },
317
		.w = { SN_WIDTH, 0, 2048 },
318
		.x = { SN_COORD, -4750, 5280 },
319
		.y = { SN_COORD, -150, 6730 },
320
		.o = { SN_ORIENT,
321
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
322
	},
323
	[BCM5974_FLAG_WELLSPRING8] = {
324
		.tp = tp + TYPE3,
325
		.p = { SN_PRESSURE, 0, 300 },
326
		.w = { SN_WIDTH, 0, 2048 },
327
		.x = { SN_COORD, -4620, 5140 },
328
		.y = { SN_COORD, -150, 6600 },
329
		.o = { SN_ORIENT,
330
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
331
	},
332
	[BCM5974_FLAG_WELLSPRING9] = {
333
		.tp = tp + TYPE4,
334
		.p = { SN_PRESSURE, 0, 300 },
335
		.w = { SN_WIDTH, 0, 2048 },
336
		.x = { SN_COORD, -4828, 5345 },
337
		.y = { SN_COORD, -203, 6803 },
338
		.o = { SN_ORIENT,
339
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
340
	},
341
};
342
#define	WSP_DEV(v,p,i)	{						\
343
	HID_BVPI(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i),	\
344
	HID_TLC(BCM5974_TLC_PAGE, BCM5974_TLC_USAGE),			\
345
}
346
347
static const struct hid_device_id bcm5974_devs[] = {
348
	/* MacbookAir6,2 (unibody, June 2013) */
349
	WSP_DEV(APPLE, WELLSPRING8_ANSI, BCM5974_FLAG_WELLSPRING8),
350
	WSP_DEV(APPLE, WELLSPRING8_ISO, BCM5974_FLAG_WELLSPRING8),
351
	WSP_DEV(APPLE, WELLSPRING8_JIS, BCM5974_FLAG_WELLSPRING8),
352
353
	/* MacbookPro12,1 MacbookPro11,4 */
354
	WSP_DEV(APPLE, WELLSPRING9_ANSI, BCM5974_FLAG_WELLSPRING9),
355
	WSP_DEV(APPLE, WELLSPRING9_ISO, BCM5974_FLAG_WELLSPRING9),
356
	WSP_DEV(APPLE, WELLSPRING9_JIS, BCM5974_FLAG_WELLSPRING9),
357
};
358
359
struct bcm5974_softc {
360
	device_t sc_dev;
361
	struct evdev_dev *sc_evdev;
362
	/* device configuration */
363
	const struct bcm5974_dev_params *sc_params;
364
};
365
366
static const uint8_t bcm5974_rdesc[] = {
367
	0x05, BCM5974_TLC_PAGE,	/* Usage Page (BCM5974_TLC_PAGE)	*/
368
	0x09, BCM5974_TLC_USAGE,/* Usage (BCM5974_TLC_USAGE)		*/
369
	0xA1, 0x01,		/* Collection (Application)		*/
370
	0x06, 0x00, 0xFF,	/*   Usage Page (Vendor Defined 0xFF00)	*/
371
	0x09, 0x01,		/*   Usage (0x01)			*/
372
	0x15, 0x00,		/*   Logical Minimum (0)		*/
373
	0x26, 0xFF, 0x00,	/*   Logical Maximum (255)		*/
374
	0x75, 0x08,		/*   Report Size (8)			*/
375
	0x96,			/*   Report Count (BCM5974_BUFFER_MAX)	*/
376
	BCM5974_BUFFER_MAX % 0x100,
377
	BCM5974_BUFFER_MAX / 0x100,
378
	0x81, 0x22,		/*   Input (Data,Var,Abs)		*/
379
	0xC0,			/* End Collection			*/
380
};
381
382
/*
383
 * function prototypes
384
 */
385
static evdev_open_t	bcm5974_ev_open;
386
static evdev_close_t	bcm5974_ev_close;
387
static const struct evdev_methods bcm5974_evdev_methods = {
388
	.ev_open =	&bcm5974_ev_open,
389
	.ev_close =	&bcm5974_ev_close,
390
};
391
static hid_intr_t	bcm5974_intr;
392
393
/* Device methods. */
394
static device_identify_t bcm5974_identify;
395
static device_probe_t	bcm5974_probe;
396
static device_attach_t	bcm5974_attach;
397
static device_detach_t	bcm5974_detach;
398
399
static int
400
bcm5974_set_device_mode(struct bcm5974_softc *sc, bool on)
401
{
402
	const struct bcm5974_dev_params *params = sc->sc_params;
403
	uint8_t	mode_bytes[2];
404
	int err;
405
406
	/* Type 3 does not require a mode switch */
407
	if (params->tp == tp + TYPE3)
408
		return (0);
409
410
	err = hid_get_report(sc->sc_dev, mode_bytes, sizeof(mode_bytes), NULL,
411
	    HID_FEATURE_REPORT, 0x02);
412
	if (err != 0) {
413
		DPRINTF("Failed to read device mode (%d)\n", err);
414
		return (err);
415
	}
416
#if 0
417
	/*
418
	 * XXX Need to wait at least 250ms for hardware to get
419
	 * ready. The device mode handling appears to be handled
420
	 * asynchronously and we should not issue these commands too
421
	 * quickly.
422
	 */
423
	pause("WHW", hz / 4);
424
#endif
425
	mode_bytes[1] = on ? 0x01 : 0x00;
426
427
	return (hid_set_report(sc->sc_dev, mode_bytes, sizeof(mode_bytes),
428
	    HID_FEATURE_REPORT, 0x02));
429
}
430
431
static void
432
bcm5974_identify(driver_t *driver, device_t parent)
433
{
434
	void *d_ptr;
435
	hid_size_t d_len;
436
437
	/*
438
	 * The bcm5974 touchpad has no stable RAW mode TLC in its report
439
	 * descriptor.  So replace existing HID mode mouse TLC with dummy one
440
	 * to set proper transport layer buffer sizes, make driver probe
441
	 * simpler and prevent unwanted hms driver attachment.
442
	 */
443
	if (hid_get_report_descr(parent, &d_ptr, &d_len) == 0 &&
444
	    hid_is_mouse(d_ptr, d_len))
445
		hid_set_report_descr(parent, bcm5974_rdesc,
446
		    sizeof(bcm5974_rdesc));
447
}
448
449
static int
450
bcm5974_probe(device_t dev)
451
{
452
	int err;
453
454
	err = HIDBUS_LOOKUP_DRIVER_INFO(dev, bcm5974_devs);
455
	if (err != 0)
456
		return (err);
457
458
	hidbus_set_desc(dev, "Touchpad");
459
460
	return (BUS_PROBE_DEFAULT);
461
}
462
463
static int
464
bcm5974_attach(device_t dev)
465
{
466
	struct bcm5974_softc *sc = device_get_softc(dev);
467
	const struct hid_device_info *hw = hid_get_device_info(dev);
468
	int err;
469
470
	DPRINTFN(BCM5974_LLEVEL_INFO, "sc=%p\n", sc);
471
472
	sc->sc_dev = dev;
473
474
	/* get device specific configuration */
475
	sc->sc_params = bcm5974_dev_params + hidbus_get_driver_info(dev);
476
477
	sc->sc_evdev = evdev_alloc();
478
	evdev_set_name(sc->sc_evdev, device_get_desc(dev));
479
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
480
	evdev_set_id(sc->sc_evdev, hw->idBus, hw->idVendor, hw->idProduct,
481
	    hw->idVersion);
482
	evdev_set_serial(sc->sc_evdev, hw->serial);
483
	evdev_set_methods(sc->sc_evdev, sc, &bcm5974_evdev_methods);
484
	evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
485
	evdev_support_event(sc->sc_evdev, EV_SYN);
486
	evdev_support_event(sc->sc_evdev, EV_ABS);
487
	evdev_support_event(sc->sc_evdev, EV_KEY);
488
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
489
490
#define BCM5974_ABS(evdev, code, param)					\
491
	evdev_support_abs((evdev), (code), (param).min, (param).max,	\
492
	((param).max - (param).min) / (param).snratio, 0, 0);
493
494
	/* finger position */
495
	BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
496
	BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
497
	/* finger pressure */
498
	BCM5974_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
499
	/* finger touch area */
500
	BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
501
	BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
502
	/* finger approach area */
503
	BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
504
	BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
505
	/* finger orientation */
506
	BCM5974_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
507
	/* button properties */
508
	evdev_support_key(sc->sc_evdev, BTN_LEFT);
509
	if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
510
		evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
511
	/* Enable automatic touch assignment for type B MT protocol */
512
	evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
513
	    0, MAX_FINGERS - 1, 0, 0, 0);
514
	evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
515
	    -1, MAX_FINGERS - 1, 0, 0, 0);
516
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
517
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
518
	/* Synaptics compatibility events */
519
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
520
521
	err = evdev_register(sc->sc_evdev);
522
	if (err)
523
		goto detach;
524
525
	hidbus_set_intr(dev, bcm5974_intr, sc);
526
527
	return (0);
528
529
detach:
530
	bcm5974_detach(dev);
531
	return (ENOMEM);
532
}
533
534
static int
535
bcm5974_detach(device_t dev)
536
{
537
	struct bcm5974_softc *sc = device_get_softc(dev);
538
539
	evdev_free(sc->sc_evdev);
540
541
	return (0);
542
}
543
544
static void
545
bcm5974_intr(void *context, void *data, hid_size_t len)
546
{
547
	struct bcm5974_softc *sc = context;
548
	const struct bcm5974_dev_params *params = sc->sc_params;
549
	union evdev_mt_slot slot_data;
550
	struct tp_finger *f;
551
	int ntouch;			/* the finger number in touch */
552
	int ibt;			/* button status */
553
	int i;
554
	int slot;
555
	uint8_t fsize = sizeof(struct tp_finger) + params->tp->delta;
556
557
	if ((len < params->tp->offset + fsize) ||
558
	    ((len - params->tp->offset) % fsize) != 0) {
559
		DPRINTFN(BCM5974_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
560
		    len, sc->tp_data[0], sc->tp_data[1]);
561
		return;
562
	}
563
564
	ibt = ((uint8_t *)data)[params->tp->button];
565
	ntouch = (len - params->tp->offset) / fsize;
566
567
	for (i = 0, slot = 0; i != ntouch; i++) {
568
		f = (struct tp_finger *)(((uint8_t *)data) +
569
		    params->tp->offset + params->tp->delta + i * fsize);
570
		DPRINTFN(BCM5974_LLEVEL_INFO,
571
		    "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
572
		    "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
573
		    "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
574
		    i, ibt, ntouch, le16toh(f->origin), le16toh(f->abs_x),
575
		    le16toh(f->abs_y), le16toh(f->rel_x), le16toh(f->rel_y),
576
		    le16toh(f->tool_major), le16toh(f->tool_minor),
577
		    le16toh(f->orientation), le16toh(f->touch_major),
578
		    le16toh(f->touch_minor), le16toh(f->pressure),
579
		    le16toh(f->multi));
580
581
		if (f->touch_major == 0)
582
			continue;
583
		slot_data = (union evdev_mt_slot) {
584
			.id = slot,
585
			.x = le16toh(f->abs_x),
586
			.y = params->y.min + params->y.max - le16toh(f->abs_y),
587
			.p = le16toh(f->pressure),
588
			.maj = le16toh(f->touch_major) << 1,
589
			.min = le16toh(f->touch_minor) << 1,
590
			.w_maj = le16toh(f->tool_major) << 1,
591
			.w_min = le16toh(f->tool_minor) << 1,
592
			.ori = params->o.max - le16toh(f->orientation),
593
		};
594
		evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
595
		slot++;
596
	}
597
598
	evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
599
	evdev_sync(sc->sc_evdev);
600
}
601
602
static int
603
bcm5974_ev_open(struct evdev_dev *evdev)
604
{
605
	struct bcm5974_softc *sc = evdev_get_softc(evdev);
606
	int err;
607
608
	/*
609
	 * By default the touchpad behaves like a HID device, sending
610
	 * packets with reportID = 8. Such reports contain only
611
	 * limited information. They encode movement deltas and button
612
	 * events, but do not include data from the pressure
613
	 * sensors. The device input mode can be switched from HID
614
	 * reports to raw sensor data using vendor-specific USB
615
	 * control commands:
616
	 */
617
	err = bcm5974_set_device_mode(sc, true);
618
	if (err != 0) {
619
		DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
620
		return (err);
621
	}
622
623
	return (hidbus_intr_start(sc->sc_dev));
624
}
625
626
static int
627
bcm5974_ev_close(struct evdev_dev *evdev)
628
{
629
	struct bcm5974_softc *sc = evdev_get_softc(evdev);
630
	int err;
631
632
	/*
633
	 * During re-enumeration of the device we need to force the
634
	 * device back into HID mode before switching it to RAW
635
	 * mode. Else the device does not work like expected.
636
	 */
637
	err = bcm5974_set_device_mode(sc, false);
638
	if (err != 0) {
639
		DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
640
		return (err);
641
	}
642
643
	return (hidbus_intr_stop(sc->sc_dev));
644
}
645
646
static device_method_t bcm5974_methods[] = {
647
	/* Device interface */
648
	DEVMETHOD(device_identify,	bcm5974_identify),
649
	DEVMETHOD(device_probe,		bcm5974_probe),
650
	DEVMETHOD(device_attach,	bcm5974_attach),
651
	DEVMETHOD(device_detach,	bcm5974_detach),
652
	DEVMETHOD_END
653
};
654
655
static driver_t bcm5974_driver = {
656
	.name = "bcm5974",
657
	.methods = bcm5974_methods,
658
	.size = sizeof(struct bcm5974_softc)
659
};
660
661
static devclass_t bcm5974_devclass;
662
663
DRIVER_MODULE(bcm5974, hidbus, bcm5974_driver, bcm5974_devclass, NULL, 0);
664
MODULE_DEPEND(bcm5974, hidbus, 1, 1, 1);
665
MODULE_DEPEND(bcm5974, hid, 1, 1, 1);
666
MODULE_DEPEND(bcm5974, evdev, 1, 1, 1);
667
MODULE_VERSION(bcm5974, 1);
668
HID_PNP_INFO(bcm5974_devs);
(-)b/sys/dev/usb/input/atp.c (-2 / +2 lines)
Lines 2175-2185 atp_probe(device_t self) Link Here
2175
2175
2176
	if ((usbd_lookup_id_by_uaa(fg_devs, sizeof(fg_devs), uaa)) == 0)
2176
	if ((usbd_lookup_id_by_uaa(fg_devs, sizeof(fg_devs), uaa)) == 0)
2177
		return ((uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) ?
2177
		return ((uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) ?
2178
			0 : ENXIO);
2178
			BUS_PROBE_DEFAULT : ENXIO);
2179
2179
2180
	if ((usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa)) == 0)
2180
	if ((usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa)) == 0)
2181
		if (uaa->info.bIfaceIndex == WELLSPRING_INTERFACE_INDEX)
2181
		if (uaa->info.bIfaceIndex == WELLSPRING_INTERFACE_INDEX)
2182
			return (0);
2182
			return (BUS_PROBE_DEFAULT);
2183
2183
2184
	return (ENXIO);
2184
	return (ENXIO);
2185
}
2185
}
(-)b/sys/dev/usb/input/wsp.c (-220 / +383 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 169-175 enum tp_type { Link Here
169
	TYPE1,			/* plain trackpad */
176
	TYPE1,			/* plain trackpad */
170
	TYPE2,			/* button integrated in trackpad */
177
	TYPE2,			/* button integrated in trackpad */
171
	TYPE3,			/* additional header fields since June 2013 */
178
	TYPE3,			/* additional header fields since June 2013 */
172
	TYPE4                   /* additional header field for pressure data */
179
	TYPE4,                  /* additional header field for pressure data */
180
	TYPE_CNT
173
};
181
};
174
182
175
/* trackpad finger data offsets, le16-aligned */
183
/* trackpad finger data offsets, le16-aligned */
Lines 192-197 enum tp_type { Link Here
192
#define FSIZE_TYPE3             (14 * 2)
200
#define FSIZE_TYPE3             (14 * 2)
193
#define FSIZE_TYPE4             (15 * 2)
201
#define FSIZE_TYPE4             (15 * 2)
194
202
203
struct tp {
204
	uint8_t	caps;			/* device capability bitmask */
205
	uint8_t	button;			/* offset to button data */
206
	uint8_t	offset;			/* offset to trackpad finger data */
207
	uint8_t fsize;			/* bytes in single finger block */
208
	uint8_t delta;			/* offset from header to finger struct */
209
	uint8_t iface_index;
210
	uint8_t um_size;		/* usb control message length */
211
	uint8_t um_req_idx;		/* usb control message index */
212
	uint8_t um_switch_idx;		/* usb control message mode switch index */
213
	uint8_t um_switch_on;		/* usb control message mode switch on */
214
	uint8_t um_switch_off;		/* usb control message mode switch off */
215
} const static tp[TYPE_CNT] = {
216
	[TYPE1] = {
217
		.caps = 0,
218
		.button = 0,
219
		.offset = FINGER_TYPE1,
220
		.fsize = FSIZE_TYPE1,
221
		.delta = 0,
222
		.iface_index = 0,
223
		.um_size = 8,
224
		.um_req_idx = 0x00,
225
		.um_switch_idx = 0,
226
		.um_switch_on = 0x01,
227
		.um_switch_off = 0x08,
228
	},
229
	[TYPE2] = {
230
		.caps = HAS_INTEGRATED_BUTTON,
231
		.button = BUTTON_TYPE2,
232
		.offset = FINGER_TYPE2,
233
		.fsize = FSIZE_TYPE2,
234
		.delta = 0,
235
		.iface_index = 0,
236
		.um_size = 8,
237
		.um_req_idx = 0x00,
238
		.um_switch_idx = 0,
239
		.um_switch_on = 0x01,
240
		.um_switch_off = 0x08,
241
	},
242
	[TYPE3] = {
243
		.caps = HAS_INTEGRATED_BUTTON,
244
		.button = BUTTON_TYPE3,
245
		.offset = FINGER_TYPE3,
246
		.fsize = FSIZE_TYPE3,
247
		.delta = 0,
248
	},
249
	[TYPE4] = {
250
		.caps = HAS_INTEGRATED_BUTTON,
251
		.button = BUTTON_TYPE4,
252
		.offset = FINGER_TYPE4,
253
		.fsize = FSIZE_TYPE4,
254
		.delta = 2,
255
		.iface_index = 2,
256
		.um_size = 2,
257
		.um_req_idx = 0x02,
258
		.um_switch_idx = 1,
259
		.um_switch_on = 0x01,
260
		.um_switch_off = 0x00,
261
	},
262
};
263
195
/* trackpad finger header - little endian */
264
/* trackpad finger header - little endian */
196
struct tp_header {
265
struct tp_header {
197
	uint8_t	flag;
266
	uint8_t	flag;
Lines 226-234 struct tp_finger { Link Here
226
} __packed;
295
} __packed;
227
296
228
/* trackpad finger data size, empirically at least ten fingers */
297
/* trackpad finger data size, empirically at least ten fingers */
298
#ifdef EVDEV_SUPPORT
299
#define	MAX_FINGERS		MAX_MT_SLOTS
300
#else
229
#define	MAX_FINGERS		16
301
#define	MAX_FINGERS		16
302
#endif
230
#define	SIZEOF_FINGER		sizeof(struct tp_finger)
303
#define	SIZEOF_FINGER		sizeof(struct tp_finger)
231
#define	SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
304
#define	SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
305
#define	MAX_FINGER_ORIENTATION	16384
232
306
233
#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
307
#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
234
#error "WSP_BUFFER_MAX is too small"
308
#error "WSP_BUFFER_MAX is too small"
Lines 251-467 enum { Link Here
251
	WSP_FLAG_MAX,
325
	WSP_FLAG_MAX,
252
};
326
};
253
327
328
/* device-specific parameters */
329
struct wsp_param {
330
	int snratio;			/* signal-to-noise ratio */
331
	int min;			/* device minimum reading */
332
	int max;			/* device maximum reading */
333
};
334
254
/* device-specific configuration */
335
/* device-specific configuration */
255
struct wsp_dev_params {
336
struct wsp_dev_params {
256
	uint8_t	caps;			/* device capability bitmask */
337
	const struct tp* tp;
257
	uint8_t	tp_type;		/* type of trackpad interface */
338
	struct wsp_param p;		/* finger pressure limits */
258
	uint8_t	tp_button;		/* offset to button data */
339
	struct wsp_param w;		/* finger width limits */
259
	uint8_t	tp_offset;		/* offset to trackpad finger data */
340
	struct wsp_param x;		/* horizontal limits */
260
	uint8_t tp_fsize;		/* bytes in single finger block */
341
	struct wsp_param y;		/* vertical limits */
261
	uint8_t tp_delta;		/* offset from header to finger struct */
342
	struct wsp_param o;		/* orientation limits */
262
	uint8_t iface_index;
263
	uint8_t um_size;		/* usb control message length */
264
	uint8_t um_req_val;		/* usb control message value */
265
	uint8_t um_req_idx;		/* usb control message index */
266
	uint8_t um_switch_idx;		/* usb control message mode switch index */
267
	uint8_t um_switch_on;		/* usb control message mode switch on */
268
	uint8_t um_switch_off;		/* usb control message mode switch off */
269
};
343
};
270
344
345
/* logical signal quality */
346
#define	SN_PRESSURE	45		/* pressure signal-to-noise ratio */
347
#define	SN_WIDTH	25		/* width signal-to-noise ratio */
348
#define	SN_COORD	250		/* coordinate signal-to-noise ratio */
349
#define	SN_ORIENT	10		/* orientation signal-to-noise ratio */
350
271
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
351
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
272
	[WSP_FLAG_WELLSPRING1] = {
352
	[WSP_FLAG_WELLSPRING1] = {
273
		.caps = 0,
353
		.tp = tp + TYPE1,
274
		.tp_type = TYPE1,
354
		.p = { SN_PRESSURE, 0, 256 },
275
		.tp_button = 0,
355
		.w = { SN_WIDTH, 0, 2048 },
276
		.tp_offset = FINGER_TYPE1,
356
		.x = { SN_COORD, -4824, 5342 },
277
		.tp_fsize = FSIZE_TYPE1,
357
		.y = { SN_COORD, -172, 5820 },
278
		.tp_delta = 0,
358
		.o = { SN_ORIENT,
279
		.iface_index = 0,
359
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
280
		.um_size = 8,
281
		.um_req_val = 0x03,
282
		.um_req_idx = 0x00,
283
		.um_switch_idx = 0,
284
		.um_switch_on = 0x01,
285
		.um_switch_off = 0x08,
286
	},
360
	},
287
	[WSP_FLAG_WELLSPRING2] = {
361
	[WSP_FLAG_WELLSPRING2] = {
288
		.caps = 0,
362
		.tp = tp + TYPE1,
289
		.tp_type = TYPE1,
363
		.p = { SN_PRESSURE, 0, 256 },
290
		.tp_button = 0,
364
		.w = { SN_WIDTH, 0, 2048 },
291
		.tp_offset = FINGER_TYPE1,
365
		.x = { SN_COORD, -4824, 4824 },
292
		.tp_fsize = FSIZE_TYPE1,
366
		.y = { SN_COORD, -172, 4290 },
293
		.tp_delta = 0,
367
		.o = { SN_ORIENT,
294
		.iface_index = 0,
368
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
295
		.um_size = 8,
296
		.um_req_val = 0x03,
297
		.um_req_idx = 0x00,
298
		.um_switch_idx = 0,
299
		.um_switch_on = 0x01,
300
		.um_switch_off = 0x08,
301
	},
369
	},
302
	[WSP_FLAG_WELLSPRING3] = {
370
	[WSP_FLAG_WELLSPRING3] = {
303
		.caps = HAS_INTEGRATED_BUTTON,
371
		.tp = tp + TYPE2,
304
		.tp_type = TYPE2,
372
		.p = { SN_PRESSURE, 0, 300 },
305
		.tp_button = BUTTON_TYPE2,
373
		.w = { SN_WIDTH, 0, 2048 },
306
		.tp_offset = FINGER_TYPE2,
374
		.x = { SN_COORD, -4460, 5166 },
307
		.tp_fsize = FSIZE_TYPE2,
375
		.y = { SN_COORD, -75, 6700 },
308
		.tp_delta = 0,
376
		.o = { SN_ORIENT,
309
		.iface_index = 0,
377
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
310
		.um_size = 8,
311
		.um_req_val = 0x03,
312
		.um_req_idx = 0x00,
313
		.um_switch_idx = 0,
314
		.um_switch_on = 0x01,
315
		.um_switch_off = 0x08,
316
	},
378
	},
317
	[WSP_FLAG_WELLSPRING4] = {
379
	[WSP_FLAG_WELLSPRING4] = {
318
		.caps = HAS_INTEGRATED_BUTTON,
380
		.tp = tp + TYPE2,
319
		.tp_type = TYPE2,
381
		.p = { SN_PRESSURE, 0, 300 },
320
		.tp_button = BUTTON_TYPE2,
382
		.w = { SN_WIDTH, 0, 2048 },
321
		.tp_offset = FINGER_TYPE2,
383
		.x = { SN_COORD, -4620, 5140 },
322
		.tp_fsize = FSIZE_TYPE2,
384
		.y = { SN_COORD, -150, 6600 },
323
		.tp_delta = 0,
385
		.o = { SN_ORIENT,
324
		.iface_index = 0,
386
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
325
		.um_size = 8,
326
		.um_req_val = 0x03,
327
		.um_req_idx = 0x00,
328
		.um_switch_idx = 0,
329
		.um_switch_on = 0x01,
330
		.um_switch_off = 0x08,
331
	},
387
	},
332
	[WSP_FLAG_WELLSPRING4A] = {
388
	[WSP_FLAG_WELLSPRING4A] = {
333
		.caps = HAS_INTEGRATED_BUTTON,
389
		.tp = tp + TYPE2,
334
		.tp_type = TYPE2,
390
		.p = { SN_PRESSURE, 0, 300 },
335
		.tp_button = BUTTON_TYPE2,
391
		.w = { SN_WIDTH, 0, 2048 },
336
		.tp_offset = FINGER_TYPE2,
392
		.x = { SN_COORD, -4616, 5112 },
337
		.tp_fsize = FSIZE_TYPE2,
393
		.y = { SN_COORD, -142, 5234 },
338
		.tp_delta = 0,
394
		.o = { SN_ORIENT,
339
		.iface_index = 0,
395
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
340
		.um_size = 8,
341
		.um_req_val = 0x03,
342
		.um_req_idx = 0x00,
343
		.um_switch_idx = 0,
344
		.um_switch_on = 0x01,
345
		.um_switch_off = 0x08,
346
	},
396
	},
347
	[WSP_FLAG_WELLSPRING5] = {
397
	[WSP_FLAG_WELLSPRING5] = {
348
		.caps = HAS_INTEGRATED_BUTTON,
398
		.tp = tp + TYPE2,
349
		.tp_type = TYPE2,
399
		.p = { SN_PRESSURE, 0, 300 },
350
		.tp_button = BUTTON_TYPE2,
400
		.w = { SN_WIDTH, 0, 2048 },
351
		.tp_offset = FINGER_TYPE2,
401
		.x = { SN_COORD, -4415, 5050 },
352
		.tp_fsize = FSIZE_TYPE2,
402
		.y = { SN_COORD, -55, 6680 },
353
		.tp_delta = 0,
403
		.o = { SN_ORIENT,
354
		.iface_index = 0,
404
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
355
		.um_size = 8,
356
		.um_req_val = 0x03,
357
		.um_req_idx = 0x00,
358
		.um_switch_idx = 0,
359
		.um_switch_on = 0x01,
360
		.um_switch_off = 0x08,
361
	},
405
	},
362
	[WSP_FLAG_WELLSPRING6] = {
406
	[WSP_FLAG_WELLSPRING6] = {
363
		.caps = HAS_INTEGRATED_BUTTON,
407
		.tp = tp + TYPE2,
364
		.tp_type = TYPE2,
408
		.p = { SN_PRESSURE, 0, 300 },
365
		.tp_button = BUTTON_TYPE2,
409
		.w = { SN_WIDTH, 0, 2048 },
366
		.tp_offset = FINGER_TYPE2,
410
		.x = { SN_COORD, -4620, 5140 },
367
		.tp_fsize = FSIZE_TYPE2,
411
		.y = { SN_COORD, -150, 6600 },
368
		.tp_delta = 0,
412
		.o = { SN_ORIENT,
369
		.iface_index = 0,
413
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
370
		.um_size = 8,
371
		.um_req_val = 0x03,
372
		.um_req_idx = 0x00,
373
		.um_switch_idx = 0,
374
		.um_switch_on = 0x01,
375
		.um_switch_off = 0x08,
376
	},
414
	},
377
	[WSP_FLAG_WELLSPRING5A] = {
415
	[WSP_FLAG_WELLSPRING5A] = {
378
		.caps = HAS_INTEGRATED_BUTTON,
416
		.tp = tp + TYPE2,
379
		.tp_type = TYPE2,
417
		.p = { SN_PRESSURE, 0, 300 },
380
		.tp_button = BUTTON_TYPE2,
418
		.w = { SN_WIDTH, 0, 2048 },
381
		.tp_offset = FINGER_TYPE2,
419
		.x = { SN_COORD, -4750, 5280 },
382
		.tp_fsize = FSIZE_TYPE2,
420
		.y = { SN_COORD, -150, 6730 },
383
		.tp_delta = 0,
421
		.o = { SN_ORIENT,
384
		.iface_index = 0,
422
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
385
		.um_size = 8,
386
		.um_req_val = 0x03,
387
		.um_req_idx = 0x00,
388
		.um_switch_idx = 0,
389
		.um_switch_on = 0x01,
390
		.um_switch_off = 0x08,
391
	},
423
	},
392
	[WSP_FLAG_WELLSPRING6A] = {
424
	[WSP_FLAG_WELLSPRING6A] = {
393
		.caps = HAS_INTEGRATED_BUTTON,
425
		.tp = tp + TYPE2,
394
		.tp_type = TYPE2,
426
		.p = { SN_PRESSURE, 0, 300 },
395
		.tp_button = BUTTON_TYPE2,
427
		.w = { SN_WIDTH, 0, 2048 },
396
		.tp_offset = FINGER_TYPE2,
428
		.x = { SN_COORD, -4620, 5140 },
397
		.tp_fsize = FSIZE_TYPE2,
429
		.y = { SN_COORD, -150, 6600 },
398
		.tp_delta = 0,
430
		.o = { SN_ORIENT,
399
		.um_size = 8,
431
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
400
		.um_req_val = 0x03,
401
		.um_req_idx = 0x00,
402
		.um_switch_idx = 0,
403
		.um_switch_on = 0x01,
404
		.um_switch_off = 0x08,
405
	},
432
	},
406
	[WSP_FLAG_WELLSPRING7] = {
433
	[WSP_FLAG_WELLSPRING7] = {
407
		.caps = HAS_INTEGRATED_BUTTON,
434
		.tp = tp + TYPE2,
408
		.tp_type = TYPE2,
435
		.p = { SN_PRESSURE, 0, 300 },
409
		.tp_button = BUTTON_TYPE2,
436
		.w = { SN_WIDTH, 0, 2048 },
410
		.tp_offset = FINGER_TYPE2,
437
		.x = { SN_COORD, -4750, 5280 },
411
		.tp_fsize = FSIZE_TYPE2,
438
		.y = { SN_COORD, -150, 6730 },
412
		.tp_delta = 0,
439
		.o = { SN_ORIENT,
413
		.iface_index = 0,
440
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
414
		.um_size = 8,
415
		.um_req_val = 0x03,
416
		.um_req_idx = 0x00,
417
		.um_switch_idx = 0,
418
		.um_switch_on = 0x01,
419
		.um_switch_off = 0x08,
420
	},
441
	},
421
	[WSP_FLAG_WELLSPRING7A] = {
442
	[WSP_FLAG_WELLSPRING7A] = {
422
		.caps = HAS_INTEGRATED_BUTTON,
443
		.tp = tp + TYPE2,
423
		.tp_type = TYPE2,
444
		.p = { SN_PRESSURE, 0, 300 },
424
		.tp_button = BUTTON_TYPE2,
445
		.w = { SN_WIDTH, 0, 2048 },
425
		.tp_offset = FINGER_TYPE2,
446
		.x = { SN_COORD, -4750, 5280 },
426
		.tp_fsize = FSIZE_TYPE2,
447
		.y = { SN_COORD, -150, 6730 },
427
		.tp_delta = 0,
448
		.o = { SN_ORIENT,
428
		.iface_index = 0,
449
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
429
		.um_size = 8,
430
		.um_req_val = 0x03,
431
		.um_req_idx = 0x00,
432
		.um_switch_idx = 0,
433
		.um_switch_on = 0x01,
434
		.um_switch_off = 0x08,
435
	},
450
	},
436
	[WSP_FLAG_WELLSPRING8] = {
451
	[WSP_FLAG_WELLSPRING8] = {
437
		.caps = HAS_INTEGRATED_BUTTON,
452
		.tp = tp + TYPE3,
438
		.tp_type = TYPE3,
453
		.p = { SN_PRESSURE, 0, 300 },
439
		.tp_button = BUTTON_TYPE3,
454
		.w = { SN_WIDTH, 0, 2048 },
440
		.tp_offset = FINGER_TYPE3,
455
		.x = { SN_COORD, -4620, 5140 },
441
		.tp_fsize = FSIZE_TYPE3,
456
		.y = { SN_COORD, -150, 6600 },
442
		.tp_delta = 0,
457
		.o = { SN_ORIENT,
443
		.iface_index = 0,
458
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
444
		.um_size = 8,
445
		.um_req_val = 0x03,
446
		.um_req_idx = 0x00,
447
		.um_switch_idx = 0,
448
		.um_switch_on = 0x01,
449
		.um_switch_off = 0x08,
450
	},
459
	},
451
	[WSP_FLAG_WELLSPRING9] = {
460
	[WSP_FLAG_WELLSPRING9] = {
452
		.caps = HAS_INTEGRATED_BUTTON,
461
		.tp = tp + TYPE4,
453
		.tp_type = TYPE4,
462
		.p = { SN_PRESSURE, 0, 300 },
454
		.tp_button = BUTTON_TYPE4,
463
		.w = { SN_WIDTH, 0, 2048 },
455
		.tp_offset = FINGER_TYPE4,
464
		.x = { SN_COORD, -4828, 5345 },
456
		.tp_fsize = FSIZE_TYPE4,
465
		.y = { SN_COORD, -203, 6803 },
457
		.tp_delta = 2,
466
		.o = { SN_ORIENT,
458
		.iface_index = 2,
467
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION },
459
		.um_size = 2,
460
		.um_req_val = 0x03,
461
		.um_req_idx = 0x02,
462
		.um_switch_idx = 1,
463
		.um_switch_on = 0x01,
464
		.um_switch_off = 0x00,
465
	},
468
	},
466
};
469
};
467
#define	WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
470
#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
553
551
	const struct wsp_dev_params *sc_params;	/* device configuration */
554
	const struct wsp_dev_params *sc_params;	/* device configuration */
552
555
556
#ifdef EVDEV_SUPPORT
557
	struct evdev_dev *sc_evdev;
558
#endif
553
	mousehw_t sc_hw;
559
	mousehw_t sc_hw;
554
	mousemode_t sc_mode;
560
	mousemode_t sc_mode;
555
	u_int	sc_pollrate;
561
	u_int	sc_pollrate;
556
	mousestatus_t sc_status;
562
	mousestatus_t sc_status;
563
	int	sc_fflags;
557
	u_int	sc_state;
564
	u_int	sc_state;
558
#define	WSP_ENABLED	       0x01
565
#define	WSP_ENABLED		0x01
566
#define	WSP_EVDEV_OPENED	0x02
559
567
560
	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
568
	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
561
	int16_t	pos_x[MAX_FINGERS];	/* position array */
569
	int16_t	pos_x[MAX_FINGERS];	/* position array */
Lines 596-603 struct wsp_softc { Link Here
596
/*
604
/*
597
 * function prototypes
605
 * function prototypes
598
 */
606
 */
599
static usb_fifo_cmd_t wsp_start_read;
607
static usb_fifo_cmd_t wsp_fifo_start_read;
600
static usb_fifo_cmd_t wsp_stop_read;
608
static usb_fifo_cmd_t wsp_fifo_stop_read;
601
static usb_fifo_open_t wsp_open;
609
static usb_fifo_open_t wsp_open;
602
static usb_fifo_close_t wsp_close;
610
static usb_fifo_close_t wsp_close;
603
static usb_fifo_ioctl_t wsp_ioctl;
611
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,
614
	.f_open = &wsp_open,
607
	.f_close = &wsp_close,
615
	.f_close = &wsp_close,
608
	.f_ioctl = &wsp_ioctl,
616
	.f_ioctl = &wsp_ioctl,
609
	.f_start_read = &wsp_start_read,
617
	.f_start_read = &wsp_fifo_start_read,
610
	.f_stop_read = &wsp_stop_read,
618
	.f_stop_read = &wsp_fifo_stop_read,
611
	.basename[0] = WSP_DRIVER_NAME,
619
	.basename[0] = WSP_DRIVER_NAME,
612
};
620
};
613
621
622
#ifdef EVDEV_SUPPORT
623
static evdev_open_t wsp_ev_open;
624
static evdev_close_t wsp_ev_close;
625
static const struct evdev_methods wsp_evdev_methods = {
626
	.ev_open = &wsp_ev_open,
627
	.ev_close = &wsp_ev_close,
628
};
629
#endif
630
614
/* device initialization and shutdown */
631
/* device initialization and shutdown */
615
static int wsp_enable(struct wsp_softc *sc);
632
static int wsp_enable(struct wsp_softc *sc);
616
static void wsp_disable(struct wsp_softc *sc);
633
static void wsp_disable(struct wsp_softc *sc);
Lines 647-658 wsp_set_device_mode(struct wsp_softc *sc, uint8_t on) Link Here
647
	usb_error_t err;
664
	usb_error_t err;
648
665
649
	/* Type 3 does not require a mode switch */
666
	/* Type 3 does not require a mode switch */
650
	if (params->tp_type == TYPE3)
667
	if (params->tp == tp + TYPE3)
651
		return 0;
668
		return 0;
652
669
653
	err = usbd_req_get_report(sc->sc_usb_device, NULL,
670
	err = usbd_req_get_report(sc->sc_usb_device, NULL,
654
	    mode_bytes, params->um_size, params->iface_index,
671
	    mode_bytes, params->tp->um_size, params->tp->iface_index,
655
	    params->um_req_val, params->um_req_idx);
672
	    UHID_FEATURE_REPORT, params->tp->um_req_idx);
656
673
657
	if (err != USB_ERR_NORMAL_COMPLETION) {
674
	if (err != USB_ERR_NORMAL_COMPLETION) {
658
		DPRINTF("Failed to read device mode (%d)\n", err);
675
		DPRINTF("Failed to read device mode (%d)\n", err);
Lines 667-678 wsp_set_device_mode(struct wsp_softc *sc, uint8_t on) Link Here
667
	 */
684
	 */
668
	pause("WHW", hz / 4);
685
	pause("WHW", hz / 4);
669
686
670
	mode_bytes[params->um_switch_idx] = 
687
	mode_bytes[params->tp->um_switch_idx] =
671
	    on ? params->um_switch_on : params->um_switch_off;
688
	    on ? params->tp->um_switch_on : params->tp->um_switch_off;
672
689
673
	return (usbd_req_set_report(sc->sc_usb_device, NULL,
690
	return (usbd_req_set_report(sc->sc_usb_device, NULL,
674
	    mode_bytes, params->um_size, params->iface_index, 
691
	    mode_bytes, params->tp->um_size, params->tp->iface_index,
675
	    params->um_req_val, params->um_req_idx));
692
	    UHID_FEATURE_REPORT, params->tp->um_req_idx));
676
}
693
}
677
694
678
static int
695
static int
Lines 720-726 wsp_probe(device_t self) Link Here
720
	/* check if we are attaching to the first match */
737
	/* check if we are attaching to the first match */
721
	if (uaa->info.bIfaceIndex != i)
738
	if (uaa->info.bIfaceIndex != i)
722
		return (ENXIO);
739
		return (ENXIO);
723
	return (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa));
740
	if (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa) != 0)
741
		return (ENXIO);
742
743
	return (BUS_PROBE_DEFAULT);
724
}
744
}
725
745
726
static int
746
static int
Lines 816-821 wsp_attach(device_t dev) Link Here
816
	sc->sc_touch = WSP_UNTOUCH;
836
	sc->sc_touch = WSP_UNTOUCH;
817
	sc->scr_mode = WSP_SCR_NONE;
837
	sc->scr_mode = WSP_SCR_NONE;
818
838
839
#ifdef EVDEV_SUPPORT
840
	sc->sc_evdev = evdev_alloc();
841
	evdev_set_name(sc->sc_evdev, device_get_desc(dev));
842
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
843
	evdev_set_id(sc->sc_evdev, BUS_USB, uaa->info.idVendor,
844
	    uaa->info.idProduct, 0);
845
	evdev_set_serial(sc->sc_evdev, usb_get_serial(uaa->device));
846
	evdev_set_methods(sc->sc_evdev, sc, &wsp_evdev_methods);
847
	evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
848
	evdev_support_event(sc->sc_evdev, EV_SYN);
849
	evdev_support_event(sc->sc_evdev, EV_ABS);
850
	evdev_support_event(sc->sc_evdev, EV_KEY);
851
852
#define WSP_SUPPORT_ABS(evdev, code, param)				\
853
	evdev_support_abs((evdev), (code), (param).min, (param).max,	\
854
	((param).max - (param).min) / (param).snratio, 0, 0);
855
856
	/* finger position */
857
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
858
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
859
	/* finger pressure */
860
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
861
	/* finger touch area */
862
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
863
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
864
	/* finger approach area */
865
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
866
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
867
	/* finger orientation */
868
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
869
	/* button properties */
870
	evdev_support_key(sc->sc_evdev, BTN_LEFT);
871
	if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
872
		evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
873
	/* Enable automatic touch assignment for type B MT protocol */
874
	evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
875
	    0, MAX_FINGERS - 1, 0, 0, 0);
876
	evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
877
	    -1, MAX_FINGERS - 1, 0, 0, 0);
878
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
879
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
880
	/* Synaptics compatibility events */
881
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
882
883
	err = evdev_register(sc->sc_evdev);
884
	if (err)
885
		goto detach;
886
#endif
887
819
	return (0);
888
	return (0);
820
889
821
detach:
890
detach:
Lines 837-842 wsp_detach(device_t dev) Link Here
837
906
838
	usb_fifo_detach(&sc->sc_fifo);
907
	usb_fifo_detach(&sc->sc_fifo);
839
908
909
#ifdef EVDEV_SUPPORT
910
	evdev_free(sc->sc_evdev);
911
#endif
912
840
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
913
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
841
914
842
	mtx_destroy(&sc->sc_mutex);
915
	mtx_destroy(&sc->sc_mutex);
Lines 863-868 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
863
	int rdz = 0;
936
	int rdz = 0;
864
	int len;
937
	int len;
865
	int i;
938
	int i;
939
#ifdef EVDEV_SUPPORT
940
	int slot = 0;
941
#endif
866
942
867
	wsp_runing_rangecheck(&tun);
943
	wsp_runing_rangecheck(&tun);
868
944
Lines 878-885 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
878
		pc = usbd_xfer_get_frame(xfer, 0);
954
		pc = usbd_xfer_get_frame(xfer, 0);
879
		usbd_copy_out(pc, 0, sc->tp_data, len);
955
		usbd_copy_out(pc, 0, sc->tp_data, len);
880
956
881
		if ((len < params->tp_offset + params->tp_fsize) ||
957
		if ((len < params->tp->offset + params->tp->fsize) ||
882
		    ((len - params->tp_offset) % params->tp_fsize) != 0) {
958
		    ((len - params->tp->offset) % params->tp->fsize) != 0) {
883
			DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
959
			DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
884
			    len, sc->tp_data[0], sc->tp_data[1]);
960
			    len, sc->tp_data[0], sc->tp_data[1]);
885
			goto tr_setup;
961
			goto tr_setup;
Lines 892-901 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
892
968
893
		h = (struct tp_header *)(sc->tp_data);
969
		h = (struct tp_header *)(sc->tp_data);
894
970
895
		if (params->tp_type >= TYPE2) {
971
		if (params->tp != tp + TYPE1) {
896
			ibt = sc->tp_data[params->tp_button];
972
			ibt = sc->tp_data[params->tp->button];
897
			ntouch = sc->tp_data[params->tp_button - 1];
973
			ntouch = sc->tp_data[params->tp->button - 1];
898
		}
974
		} else
975
			ntouch = (len - params->tp->offset) / params->tp->fsize;
976
899
		/* range check */
977
		/* range check */
900
		if (ntouch < 0)
978
		if (ntouch < 0)
901
			ntouch = 0;
979
			ntouch = 0;
Lines 903-909 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
903
			ntouch = MAX_FINGERS;
981
			ntouch = MAX_FINGERS;
904
982
905
		for (i = 0; i != ntouch; i++) {
983
		for (i = 0; i != ntouch; i++) {
906
			f = (struct tp_finger *)(sc->tp_data + params->tp_offset + params->tp_delta + i * params->tp_fsize);
984
			f = (struct tp_finger *)(sc->tp_data + params->tp->offset + params->tp->delta + i * params->tp->fsize);
907
			/* swap endianness, if any */
985
			/* swap endianness, if any */
908
			if (le16toh(0x1234) != 0x1234) {
986
			if (le16toh(0x1234) != 0x1234) {
909
				f->origin = le16toh((uint16_t)f->origin);
987
				f->origin = le16toh((uint16_t)f->origin);
Lines 929-945 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
929
			sc->pos_x[i] = f->abs_x;
1007
			sc->pos_x[i] = f->abs_x;
930
			sc->pos_y[i] = -f->abs_y;
1008
			sc->pos_y[i] = -f->abs_y;
931
			sc->index[i] = f;
1009
			sc->index[i] = f;
1010
#ifdef EVDEV_SUPPORT
1011
			if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE && f->touch_major != 0) {
1012
				union evdev_mt_slot slot_data = {
1013
					.id = slot,
1014
					.x = f->abs_x,
1015
					.y = params->y.min + params->y.max - f->abs_y,
1016
					.p = f->pressure,
1017
					.maj = f->touch_major << 1,
1018
					.min = f->touch_minor << 1,
1019
					.w_maj = f->tool_major << 1,
1020
					.w_min = f->tool_minor << 1,
1021
					.ori = params->o.max - f->orientation,
1022
				};
1023
				evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
1024
				slot++;
1025
			}
1026
#endif
932
		}
1027
		}
933
1028
1029
#ifdef EVDEV_SUPPORT
1030
		if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1031
			evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
1032
			evdev_sync(sc->sc_evdev);
1033
		}
1034
#endif
934
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
1035
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
935
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
1036
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
936
		sc->sc_status.obutton = sc->sc_status.button;
1037
		sc->sc_status.obutton = sc->sc_status.button;
937
		sc->sc_status.button = 0;
1038
		sc->sc_status.button = 0;
938
1039
939
		if (ibt != 0) {
1040
		if (ibt != 0) {
940
			if ((params->caps & HAS_INTEGRATED_BUTTON) && ntouch == 2)
1041
			if ((params->tp->caps & HAS_INTEGRATED_BUTTON) && ntouch == 2)
941
				sc->sc_status.button |= MOUSE_BUTTON3DOWN;
1042
				sc->sc_status.button |= MOUSE_BUTTON3DOWN;
942
			else if ((params->caps & HAS_INTEGRATED_BUTTON) && ntouch == 3)
1043
			else if ((params->tp->caps & HAS_INTEGRATED_BUTTON) && ntouch == 3)
943
				sc->sc_status.button |= MOUSE_BUTTON2DOWN;
1044
				sc->sc_status.button |= MOUSE_BUTTON2DOWN;
944
			else 
1045
			else 
945
				sc->sc_status.button |= MOUSE_BUTTON1DOWN;
1046
				sc->sc_status.button |= MOUSE_BUTTON1DOWN;
Lines 986-992 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
986
				 */
1087
				 */
987
				switch (sc->ntaps) {
1088
				switch (sc->ntaps) {
988
				case 1:
1089
				case 1:
989
					if (!(params->caps & HAS_INTEGRATED_BUTTON) || tun.enable_single_tap_clicks) {
1090
					if (!(params->tp->caps & HAS_INTEGRATED_BUTTON) || tun.enable_single_tap_clicks) {
990
						wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
1091
						wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
991
						DPRINTFN(WSP_LLEVEL_INFO, "LEFT CLICK!\n");
1092
						DPRINTFN(WSP_LLEVEL_INFO, "LEFT CLICK!\n");
992
					}
1093
					}
Lines 1235-1243 wsp_reset_buf(struct wsp_softc *sc) Link Here
1235
}
1336
}
1236
1337
1237
static void
1338
static void
1238
wsp_start_read(struct usb_fifo *fifo)
1339
wsp_start_read(struct wsp_softc *sc)
1239
{
1340
{
1240
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1241
	int rate;
1341
	int rate;
1242
1342
1243
	/* Check if we should override the default polling interval */
1343
	/* Check if we should override the default polling interval */
Lines 1258-1306 wsp_start_read(struct usb_fifo *fifo) Link Here
1258
}
1358
}
1259
1359
1260
static void
1360
static void
1261
wsp_stop_read(struct usb_fifo *fifo)
1361
wsp_stop_read(struct wsp_softc *sc)
1262
{
1362
{
1263
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1264
1265
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1363
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1266
}
1364
}
1267
1365
1268
static int
1366
static int
1269
wsp_open(struct usb_fifo *fifo, int fflags)
1367
wsp_open(struct usb_fifo *fifo, int fflags)
1270
{
1368
{
1271
	DPRINTFN(WSP_LLEVEL_INFO, "\n");
1369
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1370
	int rc = 0;
1272
1371
1273
	if (fflags & FREAD) {
1372
	DPRINTFN(WSP_LLEVEL_INFO, "\n");
1274
		struct wsp_softc *sc = usb_fifo_softc(fifo);
1275
		int rc;
1276
1373
1277
		if (sc->sc_state & WSP_ENABLED)
1374
	if (sc->sc_fflags & fflags)
1278
			return (EBUSY);
1375
		return (EBUSY);
1279
1376
1377
	if (fflags & FREAD) {
1280
		if (usb_fifo_alloc_buffer(fifo,
1378
		if (usb_fifo_alloc_buffer(fifo,
1281
		    WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
1379
		    WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
1282
			return (ENOMEM);
1380
			return (ENOMEM);
1283
		}
1381
		}
1284
		rc = wsp_enable(sc);
1382
#ifdef EVDEV_SUPPORT
1383
		if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1384
#endif
1385
			rc = wsp_enable(sc);
1285
		if (rc != 0) {
1386
		if (rc != 0) {
1286
			usb_fifo_free_buffer(fifo);
1387
			usb_fifo_free_buffer(fifo);
1287
			return (rc);
1388
			return (rc);
1288
		}
1389
		}
1289
	}
1390
	}
1391
	sc->sc_fflags |= fflags & (FREAD | FWRITE);
1290
	return (0);
1392
	return (0);
1291
}
1393
}
1292
1394
1293
static void
1395
static void
1294
wsp_close(struct usb_fifo *fifo, int fflags)
1396
wsp_close(struct usb_fifo *fifo, int fflags)
1295
{
1397
{
1296
	if (fflags & FREAD) {
1398
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1297
		struct wsp_softc *sc = usb_fifo_softc(fifo);
1298
1399
1299
		wsp_disable(sc);
1400
	if (fflags & FREAD) {
1401
#ifdef EVDEV_SUPPORT
1402
		if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1403
#endif
1404
			wsp_disable(sc);
1300
		usb_fifo_free_buffer(fifo);
1405
		usb_fifo_free_buffer(fifo);
1301
	}
1406
	}
1407
1408
	sc->sc_fflags &= ~(fflags & (FREAD | FWRITE));
1302
}
1409
}
1303
1410
1411
static void
1412
wsp_fifo_start_read(struct usb_fifo *fifo)
1413
{
1414
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1415
1416
	wsp_start_read(sc);
1417
}
1418
1419
static void
1420
wsp_fifo_stop_read(struct usb_fifo *fifo)
1421
{
1422
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1423
1424
#ifdef EVDEV_SUPPORT
1425
	if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1426
#endif
1427
		wsp_stop_read(sc);
1428
}
1429
1430
#ifdef EVDEV_SUPPORT
1431
static int
1432
wsp_ev_open(struct evdev_dev *evdev)
1433
{
1434
	struct wsp_softc *sc = evdev_get_softc(evdev);
1435
	int rc = 0;
1436
1437
	mtx_lock(&sc->sc_mutex);
1438
	if (sc->sc_fflags == 0)
1439
		rc = wsp_enable(sc);
1440
	if (rc == 0) {
1441
		wsp_start_read(sc);
1442
		sc->sc_state |= WSP_EVDEV_OPENED;
1443
	}
1444
	mtx_unlock(&sc->sc_mutex);
1445
1446
	return (rc);
1447
}
1448
1449
static int
1450
wsp_ev_close(struct evdev_dev *evdev)
1451
{
1452
	struct wsp_softc *sc = evdev_get_softc(evdev);
1453
1454
	mtx_lock(&sc->sc_mutex);
1455
	sc->sc_state &= ~WSP_EVDEV_OPENED;
1456
	if (sc->sc_fflags == 0)
1457
		wsp_stop_read(sc);
1458
	mtx_unlock(&sc->sc_mutex);
1459
1460
	return (0);
1461
}
1462
#endif
1463
1304
int
1464
int
1305
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1465
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1306
{
1466
{
Lines 1412-1416 static devclass_t wsp_devclass; Link Here
1412
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1572
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1413
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1573
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1414
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1574
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1575
#ifdef EVDEV_SUPPORT
1576
MODULE_DEPEND(wsp, evdev, 1, 1, 1);
1577
#endif
1415
MODULE_VERSION(wsp, 1);
1578
MODULE_VERSION(wsp, 1);
1416
USB_PNP_HOST_INFO(wsp_devs);
1579
USB_PNP_HOST_INFO(wsp_devs);
(-)b/sys/modules/hid/Makefile (+1 lines)
Lines 8-13 SUBDIR = \ Link Here
8
	hidraw
8
	hidraw
9
9
10
SUBDIR += \
10
SUBDIR += \
11
	bcm5974 \
11
	hconf \
12
	hconf \
12
	hcons \
13
	hcons \
13
	hgame \
14
	hgame \
(-)b/sys/modules/hid/bcm5974/Makefile (+10 lines)
Added Link Here
1
# $FreeBSD$
2
3
.PATH: ${SRCTOP}/sys/dev/hid
4
5
KMOD=	bcm5974
6
SRCS=	bcm5974.c
7
SRCS+=	opt_hid.h
8
SRCS+=	bus_if.h device_if.h usbdevs.h
9
10
.include <bsd.kmod.mk>
(-)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