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 / +532 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
 * Set tracking id to -1 for unassigned (new) points.
313
 */
111
void
314
void
112
evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
315
evdev_mt_match_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt,
316
    int size)
113
{
317
{
318
	struct evdev_mt *mt = evdev->ev_mt;
319
	int i, j, m, n, dx, dy, slot, num_touches;
320
	int *p, *r2c, *c2r;
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
	num_touches = bitcount(mt->touches);
331
	if (num_touches >= size) {
332
		FOREACHBIT(mt->touches, slot)
333
			for (i = 0; i < size; i++) {
334
				dx = pt[i].x - mt->slots[slot].x;
335
				dy = pt[i].y - mt->slots[slot].y;
336
				*p++ = dx * dx + dy * dy;
337
			}
338
		m = num_touches;
339
		n = size;
340
	} else {
341
		for (i = 0; i < size; i++)
342
			FOREACHBIT(mt->touches, slot) {
343
				dx = pt[i].x - mt->slots[slot].x;
344
				dy = pt[i].y - mt->slots[slot].y;
345
				*p++ = dx * dx + dy * dy;
346
			}
347
		m = size;
348
		n = num_touches;
349
	}
350
	evdev_mt_matching(mt->matrix, m, n, p);
351
352
	r2c = p;
353
	c2r = p + m;
354
	for (i = 0; i < m; i++)
355
		if ((j = r2c[i]) >= 0)
356
			c2r[j] = i;
357
358
	p = (n == size ? c2r : r2c);
359
	for (i = 0; i < size; i++)
360
		if (*p++ < 0)
361
			pt[i].id = -1;
362
363
	p = (n == size ? r2c : c2r);
364
	FOREACHBIT(mt->touches, slot)
365
		if ((i = *p++) >= 0)
366
			pt[i].id = mt->tracking_ids[slot];
117
}
367
}
118
368
119
inline int32_t
369
static void
120
evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
370
evdev_mt_send_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
121
{
371
{
372
	struct evdev_mt *mt = evdev->ev_mt;
373
	union evdev_mt_slot *slot;
122
374
123
	return (evdev->ev_mt->
375
	EVDEV_LOCK_ASSERT(evdev);
124
	    ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
376
	MPASS(size >= 0 && size <= MAXIMAL_MT_SLOT(evdev) + 1);
377
378
	/*
379
	 * While MT-matching assign tracking IDs of new contacts to be equal
380
	 * to a slot number to make things simpler.
381
	 */
382
	for (slot = pt; slot < pt + size; slot++) {
383
		if (slot->id < 0)
384
			slot->id = ffc_slot(evdev, mt->touches | mt->frame);
385
		if (slot->id >= 0)
386
			evdev_mt_send_slot(evdev, slot->id, slot);
387
	}
125
}
388
}
126
389
127
inline void
390
int
128
evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
391
evdev_mt_push_frame(struct evdev_dev *evdev, union evdev_mt_slot *pt, int size)
392
{
393
	if (size < 0 || size > MAXIMAL_MT_SLOT(evdev) + 1)
394
		return (EINVAL);
395
396
	EVDEV_ENTER(evdev);
397
	evdev_mt_send_frame(evdev, pt, size);
398
	EVDEV_EXIT(evdev);
399
400
	return (0);
401
}
402
403
bool
404
evdev_mt_record_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
129
    int32_t value)
405
    int32_t value)
130
{
406
{
407
	struct evdev_mt *mt = evdev->ev_mt;
408
409
	EVDEV_LOCK_ASSERT(evdev);
410
411
	switch (type) {
412
	case EV_SYN:
413
		if (code == SYN_MT_REPORT) {
414
			/* MT protocol type A support */
415
			KASSERT(mt->type_a, ("Not a MT type A protocol"));
416
			mt->match_frame |= 1U << mt->match_slot;
417
			mt->match_slot++;
418
			return (true);
419
		}
420
		break;
421
	case EV_ABS:
422
		if (code == ABS_MT_SLOT) {
423
			/* MT protocol type B support */
424
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
425
			KASSERT(value >= 0, ("Negative slot number"));
426
			mt->match_slot = value;
427
			mt->match_frame |= 1U << mt->match_slot;
428
			return (true);
429
		} else if (code == ABS_MT_TRACKING_ID) {
430
			KASSERT(!mt->type_a, ("Not a MT type B protocol"));
431
			if (value == -1)
432
				mt->match_frame &= ~(1U << mt->match_slot);
433
			return (true);
434
		} else if (ABS_IS_MT(code)) {
435
			KASSERT(mt->match_slot >= 0, ("Negative slot"));
436
			KASSERT(mt->match_slot <= MAXIMAL_MT_SLOT(evdev),
437
			    ("Slot number too big"));
438
			mt->match_slots[mt->match_slot].
439
			    val[ABS_MT_INDEX(code)] = value;
440
			return (true);
441
		}
442
		break;
443
	default:
444
		break;
445
	}
131
446
132
	evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
447
	return (false);
133
	    value;
134
}
448
}
135
449
136
int32_t
450
static void
137
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
451
evdev_mt_replay_events(struct evdev_dev *evdev)
138
{
452
{
139
	int32_t tr_id, slot, free_slot = -1;
453
	struct evdev_mt *mt = evdev->ev_mt;
454
	int slot, size = 0;
140
455
141
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
456
	EVDEV_LOCK_ASSERT(evdev);
142
		tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
457
143
		if (tr_id == tracking_id)
458
	FOREACHBIT(mt->match_frame, slot) {
144
			return (slot);
459
		if (slot != size)
145
		/*
460
			mt->match_slots[size] = mt->match_slots[slot];
146
		 * Its possible that slot will be reassigned in a place of just
461
		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
	}
462
	}
463
	evdev_mt_match_frame(evdev, mt->match_slots, size);
464
	evdev_mt_send_frame(evdev, mt->match_slots, size);
465
	mt->match_slot = 0;
466
	mt->match_frame = 0;
467
}
468
469
union evdev_mt_slot *
470
evdev_mt_get_match_slots(struct evdev_dev *evdev)
471
{
472
	return (evdev->ev_mt->match_slots);
473
}
156
474
157
	return (free_slot);
475
int
476
evdev_mt_get_last_slot(struct evdev_dev *evdev)
477
{
478
	return (evdev->ev_mt->last_reported_slot);
158
}
479
}
159
480
160
void
481
void
161
evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
482
evdev_mt_set_last_slot(struct evdev_dev *evdev, int slot)
162
{
483
{
163
	int32_t i;
484
	struct evdev_mt *mt = evdev->ev_mt;
485
486
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
164
487
165
	for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
488
	mt->frame |= 1U << slot;
166
		evdev_support_key(evdev, evdev_fngmap[i]);
489
	mt->last_reported_slot = slot;
167
}
490
}
168
491
169
void
492
int32_t
170
evdev_support_mt_compat(struct evdev_dev *evdev)
493
evdev_mt_get_value(struct evdev_dev *evdev, int slot, int16_t code)
171
{
494
{
172
	int32_t i;
495
	struct evdev_mt *mt = evdev->ev_mt;
173
496
174
	if (evdev->ev_absinfo == NULL)
497
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
175
		return;
176
498
177
	evdev_support_event(evdev, EV_KEY);
499
	return (mt->slots[slot].val[ABS_MT_INDEX(code)]);
178
	evdev_support_key(evdev, BTN_TOUCH);
500
}
179
501
180
	/* Touchscreens should not advertise tap tool capabilities */
502
void
181
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
503
evdev_mt_set_value(struct evdev_dev *evdev, int slot, int16_t code,
182
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
504
    int32_t value)
505
{
506
	struct evdev_mt *mt = evdev->ev_mt;
183
507
184
	/* Echo 0-th MT-slot as ST-slot */
508
	MPASS(slot >= 0 && slot <= MAXIMAL_MT_SLOT(evdev));
185
	for (i = 0; i < nitems(evdev_mtstmap); i++)
509
186
		if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
510
	if (code == ABS_MT_TRACKING_ID) {
187
			evdev_support_abs(evdev, evdev_mtstmap[i][1],
511
		if (value != -1)
188
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
512
			mt->touches |= 1U << slot;
189
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
513
		else
190
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
514
			mt->touches &= ~(1U << slot);
191
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
515
	}
192
			    evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
516
	mt->slots[slot].val[ABS_MT_INDEX(code)] = value;
193
}
517
}
194
518
195
static int32_t
519
int
196
evdev_count_fingers(struct evdev_dev *evdev)
520
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
197
{
521
{
198
	int32_t nfingers = 0, i;
522
	struct evdev_mt *mt = evdev->ev_mt;
523
	int slot;
524
525
	KASSERT(!mt->type_a, ("Not a MT type B protocol"));
199
526
200
	for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
527
	/*
201
		if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
528
	 * Ignore tracking_id if slot assignment is performed by evdev.
202
			nfingers++;
529
	 * Events are written sequentially to temporary matching buffer.
530
	 */
531
	if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_TRACK))
532
		return (ffc_slot(evdev, mt->match_frame));
203
533
204
	return (nfingers);
534
	FOREACHBIT(mt->touches, slot)
535
		if (mt->tracking_ids[slot] == tracking_id)
536
			return (slot);
537
	/*
538
	 * Do not allow allocation of new slot in a place of just
539
	 * released one within the same report.
540
	 */
541
	return (ffc_slot(evdev, mt->touches | mt->frame));
205
}
542
}
206
543
207
static void
544
int32_t
208
evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
545
evdev_mt_reassign_id(struct evdev_dev *evdev, int slot, int32_t id)
209
{
546
{
210
	int32_t i;
547
	struct evdev_mt *mt = evdev->ev_mt;
548
	int32_t nid;
211
549
212
	EVDEV_LOCK_ASSERT(evdev);
550
	if (id == -1 || bit_test(evdev->ev_flags, EVDEV_FLAG_MT_KEEPID)) {
551
		mt->tracking_ids[slot] = id;
552
		return (id);
553
	}
554
555
	nid = evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID);
556
	if (nid != -1) {
557
		KASSERT(id == mt->tracking_ids[slot],
558
		    ("MT-slot tracking id has changed"));
559
		return (nid);
560
	}
213
561
214
	if (nfingers > nitems(evdev_fngmap))
562
	mt->tracking_ids[slot] = id;
215
		nfingers = nitems(evdev_fngmap);
563
again:
564
	nid = mt->tracking_id++;
565
	FOREACHBIT(mt->touches, slot)
566
		if (evdev_mt_get_value(evdev, slot, ABS_MT_TRACKING_ID) == nid)
567
			goto again;
216
568
217
	for (i = 0; i < nitems(evdev_fngmap); i++)
569
	return (nid);
218
		evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
570
}
219
		    nfingers == i + 1);
571
572
static inline int32_t
573
evdev_mt_normalize(int32_t value, int32_t mtmin, int32_t mtmax, int32_t stmax)
574
{
575
	if (stmax != 0 && mtmax != mtmin) {
576
		value = (value - mtmin) * stmax / (mtmax - mtmin);
577
		value = MAX(MIN(value, stmax), 0);
578
	}
579
	return (value);
220
}
580
}
221
581
222
void
582
void
223
evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
583
evdev_support_mt_compat(struct evdev_dev *evdev)
224
{
584
{
585
	struct input_absinfo *ai;
586
	int i;
225
587
226
	EVDEV_ENTER(evdev);
588
	if (evdev->ev_absinfo == NULL)
227
	evdev_send_nfingers(evdev, nfingers);
589
		return;
228
	EVDEV_EXIT(evdev);
590
591
	evdev_support_event(evdev, EV_KEY);
592
	evdev_support_key(evdev, BTN_TOUCH);
593
594
	/* Touchscreens should not advertise tap tool capabilities */
595
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
596
		evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
597
598
	/* Echo 0-th MT-slot as ST-slot */
599
	for (i = 0; i < nitems(evdev_mtstmap); i++) {
600
		if (!bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].mt) ||
601
		     bit_test(evdev->ev_abs_flags, evdev_mtstmap[i].st))
602
			continue;
603
		ai = evdev->ev_absinfo + evdev_mtstmap[i].mt;
604
		evdev->ev_mt->mtst_events |= 1U << i;
605
		if (evdev_mtstmap[i].max != 0)
606
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
607
			    0,
608
			    evdev_mtstmap[i].max,
609
			    0,
610
			    evdev_mt_normalize(
611
			      ai->flat, 0, ai->maximum, evdev_mtstmap[i].max),
612
			    0);
613
		else
614
			evdev_support_abs(evdev, evdev_mtstmap[i].st,
615
			    ai->minimum,
616
			    ai->maximum,
617
			    0,
618
			    ai->flat,
619
			    ai->resolution);
620
	}
229
}
621
}
230
622
231
void
623
static void
232
evdev_send_mt_compat(struct evdev_dev *evdev)
624
evdev_mt_send_st_compat(struct evdev_dev *evdev)
233
{
625
{
234
	int32_t nfingers, i;
626
	struct evdev_mt *mt = evdev->ev_mt;
627
	int nfingers, i, st_slot;
235
628
236
	EVDEV_LOCK_ASSERT(evdev);
629
	EVDEV_LOCK_ASSERT(evdev);
237
630
238
	nfingers = evdev_count_fingers(evdev);
631
	nfingers = bitcount(mt->touches);
239
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
632
	evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
240
633
241
	if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
634
	/* Send first active MT-slot state as single touch report */
242
		/* Echo 0-th MT-slot as ST-slot */
635
	st_slot = ffs(mt->touches) - 1;
243
		for (i = 0; i < nitems(evdev_mtstmap); i++)
636
	if (st_slot != -1)
244
			if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
637
		FOREACHBIT(mt->mtst_events, i)
245
				evdev_send_event(evdev, EV_ABS,
638
			evdev_send_event(evdev, EV_ABS, evdev_mtstmap[i].st,
246
				    evdev_mtstmap[i][1],
639
			    evdev_mt_normalize(evdev_mt_get_value(evdev,
247
				    evdev_get_mt_value(evdev, 0,
640
			      st_slot, evdev_mtstmap[i].mt),
248
				    evdev_mtstmap[i][0]));
641
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].minimum,
642
			      evdev->ev_absinfo[evdev_mtstmap[i].mt].maximum,
643
			      evdev_mtstmap[i].max));
249
644
250
	/* Touchscreens should not report tool taps */
645
	/* Touchscreens should not report tool taps */
251
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
646
	if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
Lines 260-283 evdev_push_mt_compat(struct evdev_dev *evdev) Link Here
260
{
655
{
261
656
262
	EVDEV_ENTER(evdev);
657
	EVDEV_ENTER(evdev);
263
	evdev_send_mt_compat(evdev);
658
	evdev_mt_send_st_compat(evdev);
264
	EVDEV_EXIT(evdev);
659
	EVDEV_EXIT(evdev);
265
}
660
}
266
661
267
void
662
static void
268
evdev_send_mt_autorel(struct evdev_dev *evdev)
663
evdev_mt_send_autorel(struct evdev_dev *evdev)
269
{
664
{
270
	int32_t slot;
665
	struct evdev_mt *mt = evdev->ev_mt;
666
	int slot;
271
667
272
	EVDEV_LOCK_ASSERT(evdev);
668
	EVDEV_LOCK_ASSERT(evdev);
669
	KASSERT(mt->match_frame == 0, ("Unmatched events exist"));
273
670
274
	for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
671
	FOREACHBIT(mt->touches & ~mt->frame, slot)
275
		if (evdev->ev_mt->ev_mt_slots[slot].ev_report !=
672
		evdev_mt_send_slot(evdev, slot, NULL);
276
		    evdev->ev_report_count &&
673
}
277
		    evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID) != -1){
674
278
			evdev_send_event(evdev, EV_ABS, ABS_MT_SLOT, slot);
675
void
279
			evdev_send_event(evdev, EV_ABS, ABS_MT_TRACKING_ID,
676
evdev_mt_push_autorel(struct evdev_dev *evdev)
280
			    -1);
677
{
281
		}
678
	EVDEV_ENTER(evdev);
282
	}
679
	evdev_mt_send_autorel(evdev);
680
	EVDEV_EXIT(evdev);
283
}
681
}
(-)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 (+814 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
/* Enable support for Type1 & Type2 trackpads */
51
#define	BCM5974_USB	1
52
53
#ifdef BCM5974_USB
54
#include <dev/usb/usb.h>
55
#include <dev/usb/usbdi.h>
56
#include <dev/usb/usbdi_util.h>
57
#include <dev/usb/usbhid.h>
58
#endif
59
60
#include "usbdevs.h"
61
62
#define	BCM5974_BUFFER_MAX	1024
63
#define	BCM5974_TLC_PAGE	HUP_DIGITIZERS
64
#define	BCM5974_TLC_USAGE	HUD_TOUCHPAD
65
66
/* magic to switch device from HID (default) mode into raw */
67
/* Type1 & Type2 trackpads */
68
#define	BCM5974_USB_IFACE_INDEX	0
69
#define	BCM5974_USB_REPORT_LEN	8
70
#define	BCM5974_USB_REPORT_ID	0
71
#define	BCM5974_USB_MODE_RAW	0x01
72
#define	BCM5974_USB_MODE_HID	0x08
73
/* Type4 trackpads */
74
#define	BCM5974_HID_REPORT_LEN	2
75
#define	BCM5974_HID_REPORT_ID	2
76
#define	BCM5974_HID_MODE_RAW	0x01
77
#define	BCM5974_HID_MODE_HID	0x00
78
79
/* Tunables */
80
static	SYSCTL_NODE(_hw_hid, OID_AUTO, bcm5974, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
81
    "HID wellspring touchpad");
82
83
#ifdef HID_DEBUG
84
enum wsp_log_level {
85
	BCM5974_LLEVEL_DISABLED = 0,
86
	BCM5974_LLEVEL_ERROR,
87
	BCM5974_LLEVEL_DEBUG,		/* for troubleshooting */
88
	BCM5974_LLEVEL_INFO,		/* for diagnostics */
89
};
90
/* the default is to only log errors */
91
static int bcm5974_debug = BCM5974_LLEVEL_ERROR;
92
93
SYSCTL_INT(_hw_hid_bcm5974, OID_AUTO, debug, CTLFLAG_RWTUN,
94
    &bcm5974_debug, BCM5974_LLEVEL_ERROR, "BCM5974 debug level");
95
#endif					/* HID_DEBUG */
96
97
/*
98
 * Some tables, structures, definitions and constant values for the
99
 * touchpad protocol has been copied from Linux's
100
 * "drivers/input/mouse/bcm5974.c" which has the following copyright
101
 * holders under GPLv2. All device specific code in this driver has
102
 * been written from scratch. The decoding algorithm is based on
103
 * output from FreeBSD's usbdump.
104
 *
105
 * Copyright (C) 2008      Henrik Rydberg (rydberg@euromail.se)
106
 * Copyright (C) 2008      Scott Shawcroft (scott.shawcroft@gmail.com)
107
 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
108
 * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
109
 * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
110
 * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
111
 * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
112
 * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
113
 * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
114
 */
115
116
/* trackpad header types */
117
enum tp_type {
118
#ifdef BCM5974_USB
119
	TYPE1,			/* plain trackpad */
120
	TYPE2,			/* button integrated in trackpad */
121
#endif
122
	TYPE3,			/* additional header fields since June 2013 */
123
	TYPE4,                  /* additional header field for pressure data */
124
	TYPE_CNT
125
};
126
127
/* list of device capability bits */
128
#define	HAS_INTEGRATED_BUTTON	1
129
130
struct tp_type_params {
131
	uint8_t	caps;		/* device capability bitmask */
132
	uint8_t	button;		/* offset to button data */
133
	uint8_t	offset;		/* offset to trackpad finger data */
134
	uint8_t delta;		/* offset from header to finger struct */
135
} const static tp[TYPE_CNT] = {
136
#ifdef BCM5974_USB
137
	[TYPE1] = {
138
		.caps = 0,
139
		.button = 0,
140
		.offset = 13 * 2,
141
		.delta = 0,
142
	},
143
	[TYPE2] = {
144
		.caps = HAS_INTEGRATED_BUTTON,
145
		.button = 15,
146
		.offset = 15 * 2,
147
		.delta = 0,
148
	},
149
#endif
150
	[TYPE3] = {
151
		.caps = HAS_INTEGRATED_BUTTON,
152
		.button = 23,
153
		.offset = 19 * 2,
154
		.delta = 0,
155
	},
156
	[TYPE4] = {
157
		.caps = HAS_INTEGRATED_BUTTON,
158
		.button = 31,
159
		.offset = 23 * 2,
160
		.delta = 2,
161
	},
162
};
163
164
/* trackpad finger structure - little endian */
165
struct tp_finger {
166
	int16_t	origin;			/* zero when switching track finger */
167
	int16_t	abs_x;			/* absolute x coodinate */
168
	int16_t	abs_y;			/* absolute y coodinate */
169
	int16_t	rel_x;			/* relative x coodinate */
170
	int16_t	rel_y;			/* relative y coodinate */
171
	int16_t	tool_major;		/* tool area, major axis */
172
	int16_t	tool_minor;		/* tool area, minor axis */
173
	int16_t	orientation;		/* 16384 when point, else 15 bit angle */
174
	int16_t	touch_major;		/* touch area, major axis */
175
	int16_t	touch_minor;		/* touch area, minor axis */
176
	int16_t	unused[2];		/* zeros */
177
	int16_t pressure;		/* pressure on forcetouch touchpad */
178
	int16_t	multi;			/* one finger: varies, more fingers:
179
				 	 * constant */
180
} __packed;
181
182
/* trackpad finger data size, empirically at least ten fingers */
183
#define	MAX_FINGERS		MAX_MT_SLOTS
184
185
#define	MAX_FINGER_ORIENTATION	16384
186
187
enum {
188
#ifdef BCM5974_USB
189
	BCM5974_FLAG_WELLSPRING1,
190
	BCM5974_FLAG_WELLSPRING2,
191
	BCM5974_FLAG_WELLSPRING3,
192
	BCM5974_FLAG_WELLSPRING4,
193
	BCM5974_FLAG_WELLSPRING4A,
194
	BCM5974_FLAG_WELLSPRING5,
195
	BCM5974_FLAG_WELLSPRING6A,
196
	BCM5974_FLAG_WELLSPRING6,
197
	BCM5974_FLAG_WELLSPRING5A,
198
	BCM5974_FLAG_WELLSPRING7,
199
	BCM5974_FLAG_WELLSPRING7A,
200
#endif
201
	BCM5974_FLAG_WELLSPRING8,
202
	BCM5974_FLAG_WELLSPRING9,
203
	BCM5974_FLAG_MAX,
204
};
205
206
/* device-specific parameters */
207
struct bcm5974_axis {
208
	int snratio;			/* signal-to-noise ratio */
209
	int min;			/* device minimum reading */
210
	int max;			/* device maximum reading */
211
	int size;			/* physical size, mm */
212
};
213
214
/* device-specific configuration */
215
struct bcm5974_dev_params {
216
	const struct tp_type_params* tp;
217
	struct bcm5974_axis p;		/* finger pressure limits */
218
	struct bcm5974_axis w;		/* finger width limits */
219
	struct bcm5974_axis x;		/* horizontal limits */
220
	struct bcm5974_axis y;		/* vertical limits */
221
	struct bcm5974_axis o;		/* orientation limits */
222
};
223
224
/* logical signal quality */
225
#define	SN_PRESSURE	45		/* pressure signal-to-noise ratio */
226
#define	SN_WIDTH	25		/* width signal-to-noise ratio */
227
#define	SN_COORD	250		/* coordinate signal-to-noise ratio */
228
#define	SN_ORIENT	10		/* orientation signal-to-noise ratio */
229
230
static const struct bcm5974_dev_params bcm5974_dev_params[BCM5974_FLAG_MAX] = {
231
#ifdef BCM5974_USB
232
	[BCM5974_FLAG_WELLSPRING1] = {
233
		.tp = tp + TYPE1,
234
		.p = { SN_PRESSURE, 0, 256, 0 },
235
		.w = { SN_WIDTH, 0, 2048, 0 },
236
		.x = { SN_COORD, -4824, 5342, 0 },
237
		.y = { SN_COORD, -172, 5820, 0 },
238
		.o = { SN_ORIENT,
239
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
240
	},
241
	[BCM5974_FLAG_WELLSPRING2] = {
242
		.tp = tp + TYPE1,
243
		.p = { SN_PRESSURE, 0, 256, 0 },
244
		.w = { SN_WIDTH, 0, 2048, 0 },
245
		.x = { SN_COORD, -4824, 4824, 0 },
246
		.y = { SN_COORD, -172, 4290, 0 },
247
		.o = { SN_ORIENT,
248
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
249
	},
250
	[BCM5974_FLAG_WELLSPRING3] = {
251
		.tp = tp + TYPE2,
252
		.p = { SN_PRESSURE, 0, 300, 0 },
253
		.w = { SN_WIDTH, 0, 2048, 0 },
254
		.x = { SN_COORD, -4460, 5166, 0 },
255
		.y = { SN_COORD, -75, 6700, 0 },
256
		.o = { SN_ORIENT,
257
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
258
	},
259
	[BCM5974_FLAG_WELLSPRING4] = {
260
		.tp = tp + TYPE2,
261
		.p = { SN_PRESSURE, 0, 300, 0 },
262
		.w = { SN_WIDTH, 0, 2048, 0 },
263
		.x = { SN_COORD, -4620, 5140, 0 },
264
		.y = { SN_COORD, -150, 6600, 0 },
265
		.o = { SN_ORIENT,
266
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
267
	},
268
	[BCM5974_FLAG_WELLSPRING4A] = {
269
		.tp = tp + TYPE2,
270
		.p = { SN_PRESSURE, 0, 300, 0 },
271
		.w = { SN_WIDTH, 0, 2048, 0 },
272
		.x = { SN_COORD, -4616, 5112, 0 },
273
		.y = { SN_COORD, -142, 5234, 0 },
274
		.o = { SN_ORIENT,
275
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
276
	},
277
	[BCM5974_FLAG_WELLSPRING5] = {
278
		.tp = tp + TYPE2,
279
		.p = { SN_PRESSURE, 0, 300, 0 },
280
		.w = { SN_WIDTH, 0, 2048, 0 },
281
		.x = { SN_COORD, -4415, 5050, 0 },
282
		.y = { SN_COORD, -55, 6680, 0 },
283
		.o = { SN_ORIENT,
284
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
285
	},
286
	[BCM5974_FLAG_WELLSPRING6] = {
287
		.tp = tp + TYPE2,
288
		.p = { SN_PRESSURE, 0, 300, 0 },
289
		.w = { SN_WIDTH, 0, 2048, 0 },
290
		.x = { SN_COORD, -4620, 5140, 0 },
291
		.y = { SN_COORD, -150, 6600, 0 },
292
		.o = { SN_ORIENT,
293
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
294
	},
295
	[BCM5974_FLAG_WELLSPRING5A] = {
296
		.tp = tp + TYPE2,
297
		.p = { SN_PRESSURE, 0, 300, 0 },
298
		.w = { SN_WIDTH, 0, 2048, 0 },
299
		.x = { SN_COORD, -4750, 5280, 0 },
300
		.y = { SN_COORD, -150, 6730, 0 },
301
		.o = { SN_ORIENT,
302
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
303
	},
304
	[BCM5974_FLAG_WELLSPRING6A] = {
305
		.tp = tp + TYPE2,
306
		.p = { SN_PRESSURE, 0, 300, 0 },
307
		.w = { SN_WIDTH, 0, 2048, 0 },
308
		.x = { SN_COORD, -4620, 5140, 0 },
309
		.y = { SN_COORD, -150, 6600, 0 },
310
		.o = { SN_ORIENT,
311
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
312
	},
313
	[BCM5974_FLAG_WELLSPRING7] = {
314
		.tp = tp + TYPE2,
315
		.p = { SN_PRESSURE, 0, 300, 0 },
316
		.w = { SN_WIDTH, 0, 2048, 0 },
317
		.x = { SN_COORD, -4750, 5280, 0 },
318
		.y = { SN_COORD, -150, 6730, 0 },
319
		.o = { SN_ORIENT,
320
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
321
	},
322
	[BCM5974_FLAG_WELLSPRING7A] = {
323
		.tp = tp + TYPE2,
324
		.p = { SN_PRESSURE, 0, 300 },
325
		.w = { SN_WIDTH, 0, 2048 },
326
		.x = { SN_COORD, -4750, 5280 },
327
		.y = { SN_COORD, -150, 6730 },
328
		.o = { SN_ORIENT,
329
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
330
	},
331
#endif
332
	[BCM5974_FLAG_WELLSPRING8] = {
333
		.tp = tp + TYPE3,
334
		.p = { SN_PRESSURE, 0, 300, 0 },
335
		.w = { SN_WIDTH, 0, 2048, 0 },
336
		.x = { SN_COORD, -4620, 5140, 0 },
337
		.y = { SN_COORD, -150, 6600, 0 },
338
		.o = { SN_ORIENT,
339
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
340
	},
341
	[BCM5974_FLAG_WELLSPRING9] = {
342
		.tp = tp + TYPE4,
343
		.p = { SN_PRESSURE, 0, 300, 0 },
344
		.w = { SN_WIDTH, 0, 2048, 0 },
345
		.x = { SN_COORD, -4828, 5345, 0 },
346
		.y = { SN_COORD, -203, 6803, 0 },
347
		.o = { SN_ORIENT,
348
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
349
	},
350
};
351
352
#define	BCM5974_DEV(v,p,i)	{					\
353
	HID_BVPI(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i),	\
354
	HID_TLC(BCM5974_TLC_PAGE, BCM5974_TLC_USAGE),			\
355
}
356
357
static const struct hid_device_id bcm5974_devs[] = {
358
#ifdef BCM5974_USB
359
	/* MacbookAir1.1 */
360
	BCM5974_DEV(APPLE, WELLSPRING_ANSI, BCM5974_FLAG_WELLSPRING1),
361
	BCM5974_DEV(APPLE, WELLSPRING_ISO, BCM5974_FLAG_WELLSPRING1),
362
	BCM5974_DEV(APPLE, WELLSPRING_JIS, BCM5974_FLAG_WELLSPRING1),
363
364
	/* MacbookProPenryn, aka wellspring2 */
365
	BCM5974_DEV(APPLE, WELLSPRING2_ANSI, BCM5974_FLAG_WELLSPRING2),
366
	BCM5974_DEV(APPLE, WELLSPRING2_ISO, BCM5974_FLAG_WELLSPRING2),
367
	BCM5974_DEV(APPLE, WELLSPRING2_JIS, BCM5974_FLAG_WELLSPRING2),
368
369
	/* Macbook5,1 (unibody), aka wellspring3 */
370
	BCM5974_DEV(APPLE, WELLSPRING3_ANSI, BCM5974_FLAG_WELLSPRING3),
371
        BCM5974_DEV(APPLE, WELLSPRING3_ISO, BCM5974_FLAG_WELLSPRING3),
372
	BCM5974_DEV(APPLE, WELLSPRING3_JIS, BCM5974_FLAG_WELLSPRING3),
373
374
	/* MacbookAir3,2 (unibody), aka wellspring4 */
375
	BCM5974_DEV(APPLE, WELLSPRING4_ANSI, BCM5974_FLAG_WELLSPRING4),
376
	BCM5974_DEV(APPLE, WELLSPRING4_ISO, BCM5974_FLAG_WELLSPRING4),
377
	BCM5974_DEV(APPLE, WELLSPRING4_JIS, BCM5974_FLAG_WELLSPRING4),
378
379
	/* MacbookAir3,1 (unibody), aka wellspring4 */
380
	BCM5974_DEV(APPLE, WELLSPRING4A_ANSI, BCM5974_FLAG_WELLSPRING4A),
381
	BCM5974_DEV(APPLE, WELLSPRING4A_ISO, BCM5974_FLAG_WELLSPRING4A),
382
	BCM5974_DEV(APPLE, WELLSPRING4A_JIS, BCM5974_FLAG_WELLSPRING4A),
383
384
	/* Macbook8 (unibody, March 2011) */
385
	BCM5974_DEV(APPLE, WELLSPRING5_ANSI, BCM5974_FLAG_WELLSPRING5),
386
	BCM5974_DEV(APPLE, WELLSPRING5_ISO, BCM5974_FLAG_WELLSPRING5),
387
	BCM5974_DEV(APPLE, WELLSPRING5_JIS, BCM5974_FLAG_WELLSPRING5),
388
389
	/* MacbookAir4,1 (unibody, July 2011) */
390
	BCM5974_DEV(APPLE, WELLSPRING6A_ANSI, BCM5974_FLAG_WELLSPRING6A),
391
	BCM5974_DEV(APPLE, WELLSPRING6A_ISO, BCM5974_FLAG_WELLSPRING6A),
392
	BCM5974_DEV(APPLE, WELLSPRING6A_JIS, BCM5974_FLAG_WELLSPRING6A),
393
394
	/* MacbookAir4,2 (unibody, July 2011) */
395
	BCM5974_DEV(APPLE, WELLSPRING6_ANSI, BCM5974_FLAG_WELLSPRING6),
396
	BCM5974_DEV(APPLE, WELLSPRING6_ISO, BCM5974_FLAG_WELLSPRING6),
397
	BCM5974_DEV(APPLE, WELLSPRING6_JIS, BCM5974_FLAG_WELLSPRING6),
398
399
	/* Macbook8,2 (unibody) */
400
	BCM5974_DEV(APPLE, WELLSPRING5A_ANSI, BCM5974_FLAG_WELLSPRING5A),
401
	BCM5974_DEV(APPLE, WELLSPRING5A_ISO, BCM5974_FLAG_WELLSPRING5A),
402
	BCM5974_DEV(APPLE, WELLSPRING5A_JIS, BCM5974_FLAG_WELLSPRING5A),
403
404
	/* MacbookPro10,1 (unibody, June 2012) */
405
	/* MacbookPro11,1-3 (unibody, June 2013) */
406
	BCM5974_DEV(APPLE, WELLSPRING7_ANSI, BCM5974_FLAG_WELLSPRING7),
407
	BCM5974_DEV(APPLE, WELLSPRING7_ISO, BCM5974_FLAG_WELLSPRING7),
408
        BCM5974_DEV(APPLE, WELLSPRING7_JIS, BCM5974_FLAG_WELLSPRING7),
409
410
        /* MacbookPro10,2 (unibody, October 2012) */
411
        BCM5974_DEV(APPLE, WELLSPRING7A_ANSI, BCM5974_FLAG_WELLSPRING7A),
412
        BCM5974_DEV(APPLE, WELLSPRING7A_ISO, BCM5974_FLAG_WELLSPRING7A),
413
        BCM5974_DEV(APPLE, WELLSPRING7A_JIS, BCM5974_FLAG_WELLSPRING7A),
414
#endif
415
	/* MacbookAir6,2 (unibody, June 2013) */
416
	BCM5974_DEV(APPLE, WELLSPRING8_ANSI, BCM5974_FLAG_WELLSPRING8),
417
	BCM5974_DEV(APPLE, WELLSPRING8_ISO, BCM5974_FLAG_WELLSPRING8),
418
	BCM5974_DEV(APPLE, WELLSPRING8_JIS, BCM5974_FLAG_WELLSPRING8),
419
420
	/* MacbookPro12,1 MacbookPro11,4 */
421
	BCM5974_DEV(APPLE, WELLSPRING9_ANSI, BCM5974_FLAG_WELLSPRING9),
422
	BCM5974_DEV(APPLE, WELLSPRING9_ISO, BCM5974_FLAG_WELLSPRING9),
423
	BCM5974_DEV(APPLE, WELLSPRING9_JIS, BCM5974_FLAG_WELLSPRING9),
424
};
425
426
struct bcm5974_softc {
427
	device_t sc_dev;
428
	struct evdev_dev *sc_evdev;
429
	/* device configuration */
430
	const struct bcm5974_dev_params *sc_params;
431
};
432
433
static const uint8_t bcm5974_rdesc[] = {
434
	0x05, BCM5974_TLC_PAGE,	/* Usage Page (BCM5974_TLC_PAGE)	*/
435
	0x09, BCM5974_TLC_USAGE,/* Usage (BCM5974_TLC_USAGE)		*/
436
	0xA1, 0x01,		/* Collection (Application)		*/
437
	0x06, 0x00, 0xFF,	/*   Usage Page (Vendor Defined 0xFF00)	*/
438
	0x09, 0x01,		/*   Usage (0x01)			*/
439
	0x15, 0x00,		/*   Logical Minimum (0)		*/
440
	0x26, 0xFF, 0x00,	/*   Logical Maximum (255)		*/
441
	0x75, 0x08,		/*   Report Size (8)			*/
442
	0x96,			/*   Report Count (BCM5974_BUFFER_MAX)	*/
443
	BCM5974_BUFFER_MAX & 0xFF,
444
	BCM5974_BUFFER_MAX >> 8 & 0xFF,
445
	0x81, 0x22,		/*   Input (Data,Var,Abs)		*/
446
	0xC0,			/* End Collection			*/
447
};
448
449
/*
450
 * function prototypes
451
 */
452
static evdev_open_t	bcm5974_ev_open;
453
static evdev_close_t	bcm5974_ev_close;
454
static const struct evdev_methods bcm5974_evdev_methods = {
455
	.ev_open =	&bcm5974_ev_open,
456
	.ev_close =	&bcm5974_ev_close,
457
};
458
static hid_intr_t	bcm5974_intr;
459
460
/* Device methods. */
461
static device_identify_t bcm5974_identify;
462
static device_probe_t	bcm5974_probe;
463
static device_attach_t	bcm5974_attach;
464
static device_detach_t	bcm5974_detach;
465
466
#ifdef BCM5974_USB
467
/*
468
 * Type1 and Type2 touchpads use keyboard USB interface to switch from HID to
469
 * RAW mode. Although it is possible to extend hkbd driver to support such a
470
 * mode change requests, it's not wanted due to cross device tree dependencies.
471
 * So, find lowest common denominator (struct usb_device of grandparent usbhid
472
 * driver) of touchpad and keyboard drivers and issue direct USB requests.
473
 */
474
static int
475
bcm5974_set_device_mode_usb(struct bcm5974_softc *sc, bool on)
476
{
477
	uint8_t mode_bytes[BCM5974_USB_REPORT_LEN];
478
	struct usb_attach_arg *uaa;
479
	device_t usbhid;
480
	usb_error_t err;
481
482
	usbhid = device_get_parent(device_get_parent(sc->sc_dev));
483
	if (device_get_devclass(usbhid) != devclass_find("usbhid"))
484
		return (ENXIO);
485
	uaa = device_get_ivars(usbhid);
486
487
	err = usbd_req_get_report(uaa->device, NULL, mode_bytes,
488
	    BCM5974_USB_REPORT_LEN, BCM5974_USB_IFACE_INDEX,
489
	    UHID_FEATURE_REPORT, BCM5974_USB_REPORT_ID);
490
	if (err != USB_ERR_NORMAL_COMPLETION) {
491
		DPRINTF("Failed to read device mode (%d)\n", err);
492
		return (EIO);
493
	}
494
#if 0
495
	/*
496
	 * XXX Need to wait at least 250ms for hardware to get
497
	 * ready. The device mode handling appears to be handled
498
	 * asynchronously and we should not issue these commands too
499
	 * quickly.
500
	 */
501
	pause("WHW", hz / 4);
502
#endif
503
	mode_bytes[0] = on ? BCM5974_USB_MODE_RAW : BCM5974_USB_MODE_HID;
504
505
	err = usbd_req_set_report(uaa->device, NULL, mode_bytes,
506
	    BCM5974_USB_REPORT_LEN, BCM5974_USB_IFACE_INDEX,
507
	    UHID_FEATURE_REPORT, BCM5974_USB_REPORT_ID);
508
	if (err != USB_ERR_NORMAL_COMPLETION) {
509
		DPRINTF("Failed to write device mode (%d)\n", err);
510
		return (EIO);
511
	}
512
513
	return (0);
514
}
515
#endif
516
517
static int
518
bcm5974_set_device_mode_hid(struct bcm5974_softc *sc, bool on)
519
{
520
	uint8_t	mode_bytes[BCM5974_HID_REPORT_LEN] = {
521
		BCM5974_HID_REPORT_ID,
522
		on ? BCM5974_HID_MODE_RAW : BCM5974_HID_MODE_HID,
523
	};
524
#if 0
525
	int err;
526
527
	err = hid_get_report(sc->sc_dev, mode_bytes, BCM5974_HID_REPORT_LEN,
528
	    NULL, HID_FEATURE_REPORT, BCM5974_HID_REPORT_ID);
529
	if (err != 0) {
530
		DPRINTF("Failed to read device mode (%d)\n", err);
531
		return (err);
532
	}
533
	/*
534
	 * XXX Need to wait at least 250ms for hardware to get
535
	 * ready. The device mode handling appears to be handled
536
	 * asynchronously and we should not issue these commands too
537
	 * quickly.
538
	 */
539
	pause("WHW", hz / 4);
540
	mode_bytes[1] = on ? BCM5974_HID_MODE_RAW : BCM5974_HID_MODE_HID;
541
#endif
542
	return (hid_set_report(sc->sc_dev, mode_bytes, BCM5974_HID_REPORT_LEN,
543
	    HID_FEATURE_REPORT, BCM5974_HID_REPORT_ID));
544
}
545
546
static int
547
bcm5974_set_device_mode(struct bcm5974_softc *sc, bool on)
548
{
549
	int err;
550
551
	switch (sc->sc_params->tp - tp) {
552
#ifdef BCM5974_USB
553
	case TYPE1:
554
	case TYPE2:
555
		err = bcm5974_set_device_mode_usb(sc, on);
556
		break;
557
#endif
558
	case TYPE3:	/* Type 3 does not require a mode switch */
559
		err = 0;
560
		break;
561
	case TYPE4:
562
		err = bcm5974_set_device_mode_hid(sc, on);
563
		break;
564
	default:
565
		KASSERT(0 == 1, ("Unknown trackpad type"));
566
	}
567
568
	return (err);
569
}
570
571
static void
572
bcm5974_identify(driver_t *driver, device_t parent)
573
{
574
	void *d_ptr;
575
	hid_size_t d_len;
576
577
	/*
578
	 * The bcm5974 touchpad has no stable RAW mode TLC in its report
579
	 * descriptor.  So replace existing HID mode mouse TLC with dummy one
580
	 * to set proper transport layer buffer sizes, make driver probe
581
	 * simpler and prevent unwanted hms driver attachment.
582
	 */
583
	if (hid_get_report_descr(parent, &d_ptr, &d_len) == 0 &&
584
	    hid_is_mouse(d_ptr, d_len))
585
		hid_set_report_descr(parent, bcm5974_rdesc,
586
		    sizeof(bcm5974_rdesc));
587
}
588
589
static int
590
bcm5974_probe(device_t dev)
591
{
592
	int err;
593
594
	err = HIDBUS_LOOKUP_DRIVER_INFO(dev, bcm5974_devs);
595
	if (err != 0)
596
		return (err);
597
598
	hidbus_set_desc(dev, "Touchpad");
599
600
	return (BUS_PROBE_DEFAULT);
601
}
602
603
static int
604
bcm5974_attach(device_t dev)
605
{
606
	struct bcm5974_softc *sc = device_get_softc(dev);
607
	const struct hid_device_info *hw = hid_get_device_info(dev);
608
	int err;
609
610
	DPRINTFN(BCM5974_LLEVEL_INFO, "sc=%p\n", sc);
611
612
	sc->sc_dev = dev;
613
614
	/* get device specific configuration */
615
	sc->sc_params = bcm5974_dev_params + hidbus_get_driver_info(dev);
616
617
	sc->sc_evdev = evdev_alloc();
618
	evdev_set_name(sc->sc_evdev, device_get_desc(dev));
619
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
620
	evdev_set_id(sc->sc_evdev, hw->idBus, hw->idVendor, hw->idProduct,
621
	    hw->idVersion);
622
	evdev_set_serial(sc->sc_evdev, hw->serial);
623
	evdev_set_methods(sc->sc_evdev, sc, &bcm5974_evdev_methods);
624
	evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
625
	evdev_support_event(sc->sc_evdev, EV_SYN);
626
	evdev_support_event(sc->sc_evdev, EV_ABS);
627
	evdev_support_event(sc->sc_evdev, EV_KEY);
628
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
629
630
#define BCM5974_ABS(evdev, code, param)					\
631
	evdev_support_abs((evdev), (code), (param).min, (param).max,	\
632
	((param).max - (param).min) / (param).snratio, 0,		\
633
	(param).size != 0 ? ((param).max - (param).min) / (param).size : 0);
634
635
	/* finger position */
636
	BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
637
	BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
638
	/* finger pressure */
639
	BCM5974_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
640
	/* finger touch area */
641
	BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
642
	BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
643
	/* finger approach area */
644
	BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
645
	BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
646
	/* finger orientation */
647
	BCM5974_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
648
	/* button properties */
649
	evdev_support_key(sc->sc_evdev, BTN_LEFT);
650
	if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
651
		evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
652
	/* Enable automatic touch assignment for type B MT protocol */
653
	evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
654
	    0, MAX_FINGERS - 1, 0, 0, 0);
655
	evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
656
	    -1, MAX_FINGERS - 1, 0, 0, 0);
657
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
658
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
659
	/* Synaptics compatibility events */
660
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
661
662
	err = evdev_register(sc->sc_evdev);
663
	if (err)
664
		goto detach;
665
666
	hidbus_set_intr(dev, bcm5974_intr, sc);
667
668
	return (0);
669
670
detach:
671
	bcm5974_detach(dev);
672
	return (ENOMEM);
673
}
674
675
static int
676
bcm5974_detach(device_t dev)
677
{
678
	struct bcm5974_softc *sc = device_get_softc(dev);
679
680
	evdev_free(sc->sc_evdev);
681
682
	return (0);
683
}
684
685
static void
686
bcm5974_intr(void *context, void *data, hid_size_t len)
687
{
688
	struct bcm5974_softc *sc = context;
689
	const struct bcm5974_dev_params *params = sc->sc_params;
690
	union evdev_mt_slot slot_data;
691
	struct tp_finger *f;
692
	int ntouch;			/* the finger number in touch */
693
	int ibt;			/* button status */
694
	int i;
695
	int slot;
696
	uint8_t fsize = sizeof(struct tp_finger) + params->tp->delta;
697
698
	if ((len < params->tp->offset + fsize) ||
699
	    ((len - params->tp->offset) % fsize) != 0) {
700
		DPRINTFN(BCM5974_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
701
		    len, sc->tp_data[0], sc->tp_data[1]);
702
		return;
703
	}
704
705
	ibt = ((uint8_t *)data)[params->tp->button];
706
	ntouch = (len - params->tp->offset) / fsize;
707
708
	for (i = 0, slot = 0; i != ntouch; i++) {
709
		f = (struct tp_finger *)(((uint8_t *)data) +
710
		    params->tp->offset + params->tp->delta + i * fsize);
711
		DPRINTFN(BCM5974_LLEVEL_INFO,
712
		    "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
713
		    "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
714
		    "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
715
		    i, ibt, ntouch, le16toh(f->origin), le16toh(f->abs_x),
716
		    le16toh(f->abs_y), le16toh(f->rel_x), le16toh(f->rel_y),
717
		    le16toh(f->tool_major), le16toh(f->tool_minor),
718
		    le16toh(f->orientation), le16toh(f->touch_major),
719
		    le16toh(f->touch_minor), le16toh(f->pressure),
720
		    le16toh(f->multi));
721
722
		if (f->touch_major == 0)
723
			continue;
724
		slot_data = (union evdev_mt_slot) {
725
			.id = slot,
726
			.x = le16toh(f->abs_x),
727
			.y = params->y.min + params->y.max - le16toh(f->abs_y),
728
			.p = le16toh(f->pressure),
729
			.maj = le16toh(f->touch_major) << 1,
730
			.min = le16toh(f->touch_minor) << 1,
731
			.w_maj = le16toh(f->tool_major) << 1,
732
			.w_min = le16toh(f->tool_minor) << 1,
733
			.ori = params->o.max - le16toh(f->orientation),
734
		};
735
		evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
736
		slot++;
737
	}
738
739
	evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
740
	evdev_sync(sc->sc_evdev);
741
}
742
743
static int
744
bcm5974_ev_open(struct evdev_dev *evdev)
745
{
746
	struct bcm5974_softc *sc = evdev_get_softc(evdev);
747
	int err;
748
749
	/*
750
	 * By default the touchpad behaves like a HID device, sending
751
	 * packets with reportID = 8. Such reports contain only
752
	 * limited information. They encode movement deltas and button
753
	 * events, but do not include data from the pressure
754
	 * sensors. The device input mode can be switched from HID
755
	 * reports to raw sensor data using vendor-specific USB
756
	 * control commands:
757
	 */
758
	err = bcm5974_set_device_mode(sc, true);
759
	if (err != 0) {
760
		DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
761
		return (err);
762
	}
763
764
	return (hidbus_intr_start(sc->sc_dev));
765
}
766
767
static int
768
bcm5974_ev_close(struct evdev_dev *evdev)
769
{
770
	struct bcm5974_softc *sc = evdev_get_softc(evdev);
771
	int err;
772
773
	err = hidbus_intr_stop(sc->sc_dev);
774
	if (err != 0)
775
		return (err);
776
777
	/*
778
	 * During re-enumeration of the device we need to force the
779
	 * device back into HID mode before switching it to RAW
780
	 * mode. Else the device does not work like expected.
781
	 */
782
	err = bcm5974_set_device_mode(sc, false);
783
	if (err != 0)
784
		DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
785
786
	return (err);
787
}
788
789
static device_method_t bcm5974_methods[] = {
790
	/* Device interface */
791
	DEVMETHOD(device_identify,	bcm5974_identify),
792
	DEVMETHOD(device_probe,		bcm5974_probe),
793
	DEVMETHOD(device_attach,	bcm5974_attach),
794
	DEVMETHOD(device_detach,	bcm5974_detach),
795
	DEVMETHOD_END
796
};
797
798
static driver_t bcm5974_driver = {
799
	.name = "bcm5974",
800
	.methods = bcm5974_methods,
801
	.size = sizeof(struct bcm5974_softc)
802
};
803
804
static devclass_t bcm5974_devclass;
805
806
DRIVER_MODULE(bcm5974, hidbus, bcm5974_driver, bcm5974_devclass, NULL, 0);
807
MODULE_DEPEND(bcm5974, hidbus, 1, 1, 1);
808
MODULE_DEPEND(bcm5974, hid, 1, 1, 1);
809
#ifdef BCM5974_USB
810
MODULE_DEPEND(bcm5974, usb, 1, 1, 1);
811
#endif
812
MODULE_DEPEND(bcm5974, evdev, 1, 1, 1);
813
MODULE_VERSION(bcm5974, 1);
814
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