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 (+816 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
#include <dev/usb/input/usbhid.h>
59
#endif
60
61
#include "usbdevs.h"
62
63
#define	BCM5974_BUFFER_MAX	(248 * 4)	/* 4 Type4 SPI frames */
64
#define	BCM5974_TLC_PAGE	HUP_GENERIC_DESKTOP
65
#define	BCM5974_TLC_USAGE	HUG_MOUSE
66
67
/* magic to switch device from HID (default) mode into raw */
68
/* Type1 & Type2 trackpads */
69
#define	BCM5974_USB_IFACE_INDEX	0
70
#define	BCM5974_USB_REPORT_LEN	8
71
#define	BCM5974_USB_REPORT_ID	0
72
#define	BCM5974_USB_MODE_RAW	0x01
73
#define	BCM5974_USB_MODE_HID	0x08
74
/* Type4 trackpads */
75
#define	BCM5974_HID_REPORT_LEN	2
76
#define	BCM5974_HID_REPORT_ID	2
77
#define	BCM5974_HID_MODE_RAW	0x01
78
#define	BCM5974_HID_MODE_HID	0x00
79
80
/* Tunables */
81
static	SYSCTL_NODE(_hw_hid, OID_AUTO, bcm5974, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
82
    "HID wellspring touchpad");
83
84
#ifdef HID_DEBUG
85
enum wsp_log_level {
86
	BCM5974_LLEVEL_DISABLED = 0,
87
	BCM5974_LLEVEL_ERROR,
88
	BCM5974_LLEVEL_DEBUG,		/* for troubleshooting */
89
	BCM5974_LLEVEL_INFO,		/* for diagnostics */
90
};
91
/* the default is to only log errors */
92
static int bcm5974_debug = BCM5974_LLEVEL_ERROR;
93
94
SYSCTL_INT(_hw_hid_bcm5974, OID_AUTO, debug, CTLFLAG_RWTUN,
95
    &bcm5974_debug, BCM5974_LLEVEL_ERROR, "BCM5974 debug level");
96
#endif					/* HID_DEBUG */
97
98
/*
99
 * Some tables, structures, definitions and constant values for the
100
 * touchpad protocol has been copied from Linux's
101
 * "drivers/input/mouse/bcm5974.c" which has the following copyright
102
 * holders under GPLv2. All device specific code in this driver has
103
 * been written from scratch. The decoding algorithm is based on
104
 * output from FreeBSD's usbdump.
105
 *
106
 * Copyright (C) 2008      Henrik Rydberg (rydberg@euromail.se)
107
 * Copyright (C) 2008      Scott Shawcroft (scott.shawcroft@gmail.com)
108
 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
109
 * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
110
 * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
111
 * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
112
 * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
113
 * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
114
 * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
115
 */
116
117
/* trackpad header types */
118
enum tp_type {
119
#ifdef BCM5974_USB
120
	TYPE1,			/* plain trackpad */
121
	TYPE2,			/* button integrated in trackpad */
122
#endif
123
	TYPE3,			/* additional header fields since June 2013 */
124
	TYPE4,                  /* additional header field for pressure data */
125
	TYPE_CNT
126
};
127
128
/* list of device capability bits */
129
#define	HAS_INTEGRATED_BUTTON	1
130
131
struct tp_type_params {
132
	uint8_t	caps;		/* device capability bitmask */
133
	uint8_t	button;		/* offset to button data */
134
	uint8_t	offset;		/* offset to trackpad finger data */
135
	uint8_t delta;		/* offset from header to finger struct */
136
} const static tp[TYPE_CNT] = {
137
#ifdef BCM5974_USB
138
	[TYPE1] = {
139
		.caps = 0,
140
		.button = 0,
141
		.offset = 13 * 2,
142
		.delta = 0,
143
	},
144
	[TYPE2] = {
145
		.caps = HAS_INTEGRATED_BUTTON,
146
		.button = 15,
147
		.offset = 15 * 2,
148
		.delta = 0,
149
	},
150
#endif
151
	[TYPE3] = {
152
		.caps = HAS_INTEGRATED_BUTTON,
153
		.button = 23,
154
		.offset = 19 * 2,
155
		.delta = 0,
156
	},
157
	[TYPE4] = {
158
		.caps = HAS_INTEGRATED_BUTTON,
159
		.button = 31,
160
		.offset = 23 * 2,
161
		.delta = 2,
162
	},
163
};
164
165
/* trackpad finger structure - little endian */
166
struct tp_finger {
167
	int16_t	origin;			/* zero when switching track finger */
168
	int16_t	abs_x;			/* absolute x coodinate */
169
	int16_t	abs_y;			/* absolute y coodinate */
170
	int16_t	rel_x;			/* relative x coodinate */
171
	int16_t	rel_y;			/* relative y coodinate */
172
	int16_t	tool_major;		/* tool area, major axis */
173
	int16_t	tool_minor;		/* tool area, minor axis */
174
	int16_t	orientation;		/* 16384 when point, else 15 bit angle */
175
	int16_t	touch_major;		/* touch area, major axis */
176
	int16_t	touch_minor;		/* touch area, minor axis */
177
	int16_t	unused[2];		/* zeros */
178
	int16_t pressure;		/* pressure on forcetouch touchpad */
179
	int16_t	multi;			/* one finger: varies, more fingers:
180
				 	 * constant */
181
} __packed;
182
183
/* trackpad finger data size, empirically at least ten fingers */
184
#define	MAX_FINGERS		MAX_MT_SLOTS
185
186
#define	MAX_FINGER_ORIENTATION	16384
187
188
enum {
189
#ifdef BCM5974_USB
190
	BCM5974_FLAG_WELLSPRING1,
191
	BCM5974_FLAG_WELLSPRING2,
192
	BCM5974_FLAG_WELLSPRING3,
193
	BCM5974_FLAG_WELLSPRING4,
194
	BCM5974_FLAG_WELLSPRING4A,
195
	BCM5974_FLAG_WELLSPRING5,
196
	BCM5974_FLAG_WELLSPRING6A,
197
	BCM5974_FLAG_WELLSPRING6,
198
	BCM5974_FLAG_WELLSPRING5A,
199
	BCM5974_FLAG_WELLSPRING7,
200
	BCM5974_FLAG_WELLSPRING7A,
201
#endif
202
	BCM5974_FLAG_WELLSPRING8,
203
	BCM5974_FLAG_WELLSPRING9,
204
	BCM5974_FLAG_MAX,
205
};
206
207
/* device-specific parameters */
208
struct bcm5974_axis {
209
	int snratio;			/* signal-to-noise ratio */
210
	int min;			/* device minimum reading */
211
	int max;			/* device maximum reading */
212
	int size;			/* physical size, mm */
213
};
214
215
/* device-specific configuration */
216
struct bcm5974_dev_params {
217
	const struct tp_type_params* tp;
218
	struct bcm5974_axis p;		/* finger pressure limits */
219
	struct bcm5974_axis w;		/* finger width limits */
220
	struct bcm5974_axis x;		/* horizontal limits */
221
	struct bcm5974_axis y;		/* vertical limits */
222
	struct bcm5974_axis o;		/* orientation limits */
223
};
224
225
/* logical signal quality */
226
#define	SN_PRESSURE	45		/* pressure signal-to-noise ratio */
227
#define	SN_WIDTH	25		/* width signal-to-noise ratio */
228
#define	SN_COORD	250		/* coordinate signal-to-noise ratio */
229
#define	SN_ORIENT	10		/* orientation signal-to-noise ratio */
230
231
static const struct bcm5974_dev_params bcm5974_dev_params[BCM5974_FLAG_MAX] = {
232
#ifdef BCM5974_USB
233
	[BCM5974_FLAG_WELLSPRING1] = {
234
		.tp = tp + TYPE1,
235
		.p = { SN_PRESSURE, 0, 256, 0 },
236
		.w = { SN_WIDTH, 0, 2048, 0 },
237
		.x = { SN_COORD, -4824, 5342, 105 },
238
		.y = { SN_COORD, -172, 5820, 75 },
239
		.o = { SN_ORIENT,
240
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
241
	},
242
	[BCM5974_FLAG_WELLSPRING2] = {
243
		.tp = tp + TYPE1,
244
		.p = { SN_PRESSURE, 0, 256, 0 },
245
		.w = { SN_WIDTH, 0, 2048, 0 },
246
		.x = { SN_COORD, -4824, 4824, 105 },
247
		.y = { SN_COORD, -172, 4290, 75 },
248
		.o = { SN_ORIENT,
249
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
250
	},
251
	[BCM5974_FLAG_WELLSPRING3] = {
252
		.tp = tp + TYPE2,
253
		.p = { SN_PRESSURE, 0, 300, 0 },
254
		.w = { SN_WIDTH, 0, 2048, 0 },
255
		.x = { SN_COORD, -4460, 5166, 105 },
256
		.y = { SN_COORD, -75, 6700, 75 },
257
		.o = { SN_ORIENT,
258
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
259
	},
260
	[BCM5974_FLAG_WELLSPRING4] = {
261
		.tp = tp + TYPE2,
262
		.p = { SN_PRESSURE, 0, 300, 0 },
263
		.w = { SN_WIDTH, 0, 2048, 0 },
264
		.x = { SN_COORD, -4620, 5140, 105 },
265
		.y = { SN_COORD, -150, 6600, 75 },
266
		.o = { SN_ORIENT,
267
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
268
	},
269
	[BCM5974_FLAG_WELLSPRING4A] = {
270
		.tp = tp + TYPE2,
271
		.p = { SN_PRESSURE, 0, 300, 0 },
272
		.w = { SN_WIDTH, 0, 2048, 0 },
273
		.x = { SN_COORD, -4616, 5112, 105 },
274
		.y = { SN_COORD, -142, 5234, 75 },
275
		.o = { SN_ORIENT,
276
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
277
	},
278
	[BCM5974_FLAG_WELLSPRING5] = {
279
		.tp = tp + TYPE2,
280
		.p = { SN_PRESSURE, 0, 300, 0 },
281
		.w = { SN_WIDTH, 0, 2048, 0 },
282
		.x = { SN_COORD, -4415, 5050, 105 },
283
		.y = { SN_COORD, -55, 6680, 75 },
284
		.o = { SN_ORIENT,
285
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
286
	},
287
	[BCM5974_FLAG_WELLSPRING6] = {
288
		.tp = tp + TYPE2,
289
		.p = { SN_PRESSURE, 0, 300, 0 },
290
		.w = { SN_WIDTH, 0, 2048, 0 },
291
		.x = { SN_COORD, -4620, 5140, 105 },
292
		.y = { SN_COORD, -150, 6600, 75 },
293
		.o = { SN_ORIENT,
294
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
295
	},
296
	[BCM5974_FLAG_WELLSPRING5A] = {
297
		.tp = tp + TYPE2,
298
		.p = { SN_PRESSURE, 0, 300, 0 },
299
		.w = { SN_WIDTH, 0, 2048, 0 },
300
		.x = { SN_COORD, -4750, 5280, 105 },
301
		.y = { SN_COORD, -150, 6730, 75 },
302
		.o = { SN_ORIENT,
303
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
304
	},
305
	[BCM5974_FLAG_WELLSPRING6A] = {
306
		.tp = tp + TYPE2,
307
		.p = { SN_PRESSURE, 0, 300, 0 },
308
		.w = { SN_WIDTH, 0, 2048, 0 },
309
		.x = { SN_COORD, -4620, 5140, 105 },
310
		.y = { SN_COORD, -150, 6600, 75 },
311
		.o = { SN_ORIENT,
312
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
313
	},
314
	[BCM5974_FLAG_WELLSPRING7] = {
315
		.tp = tp + TYPE2,
316
		.p = { SN_PRESSURE, 0, 300, 0 },
317
		.w = { SN_WIDTH, 0, 2048, 0 },
318
		.x = { SN_COORD, -4750, 5280, 105 },
319
		.y = { SN_COORD, -150, 6730, 75 },
320
		.o = { SN_ORIENT,
321
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
322
	},
323
	[BCM5974_FLAG_WELLSPRING7A] = {
324
		.tp = tp + TYPE2,
325
		.p = { SN_PRESSURE, 0, 300, 0 },
326
		.w = { SN_WIDTH, 0, 2048, 0 },
327
		.x = { SN_COORD, -4750, 5280, 105 },
328
		.y = { SN_COORD, -150, 6730, 75 },
329
		.o = { SN_ORIENT,
330
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
331
	},
332
#endif
333
	[BCM5974_FLAG_WELLSPRING8] = {
334
		.tp = tp + TYPE3,
335
		.p = { SN_PRESSURE, 0, 300, 0 },
336
		.w = { SN_WIDTH, 0, 2048, 0 },
337
		.x = { SN_COORD, -4620, 5140, 105 },
338
		.y = { SN_COORD, -150, 6600, 75 },
339
		.o = { SN_ORIENT,
340
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
341
	},
342
	[BCM5974_FLAG_WELLSPRING9] = {
343
		.tp = tp + TYPE4,
344
		.p = { SN_PRESSURE, 0, 300, 0 },
345
		.w = { SN_WIDTH, 0, 2048, 0 },
346
		.x = { SN_COORD, -4828, 5345, 105 },
347
		.y = { SN_COORD, -203, 6803, 75 },
348
		.o = { SN_ORIENT,
349
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
350
	},
351
};
352
353
#define	BCM5974_DEV(v,p,i)	{					\
354
	HID_BVPI(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i),	\
355
	HID_TLC(BCM5974_TLC_PAGE, BCM5974_TLC_USAGE),			\
356
}
357
358
static const struct hid_device_id bcm5974_devs[] = {
359
#ifdef BCM5974_USB
360
	/* MacbookAir1.1 */
361
	BCM5974_DEV(APPLE, WELLSPRING_ANSI, BCM5974_FLAG_WELLSPRING1),
362
	BCM5974_DEV(APPLE, WELLSPRING_ISO, BCM5974_FLAG_WELLSPRING1),
363
	BCM5974_DEV(APPLE, WELLSPRING_JIS, BCM5974_FLAG_WELLSPRING1),
364
365
	/* MacbookProPenryn, aka wellspring2 */
366
	BCM5974_DEV(APPLE, WELLSPRING2_ANSI, BCM5974_FLAG_WELLSPRING2),
367
	BCM5974_DEV(APPLE, WELLSPRING2_ISO, BCM5974_FLAG_WELLSPRING2),
368
	BCM5974_DEV(APPLE, WELLSPRING2_JIS, BCM5974_FLAG_WELLSPRING2),
369
370
	/* Macbook5,1 (unibody), aka wellspring3 */
371
	BCM5974_DEV(APPLE, WELLSPRING3_ANSI, BCM5974_FLAG_WELLSPRING3),
372
        BCM5974_DEV(APPLE, WELLSPRING3_ISO, BCM5974_FLAG_WELLSPRING3),
373
	BCM5974_DEV(APPLE, WELLSPRING3_JIS, BCM5974_FLAG_WELLSPRING3),
374
375
	/* MacbookAir3,2 (unibody), aka wellspring4 */
376
	BCM5974_DEV(APPLE, WELLSPRING4_ANSI, BCM5974_FLAG_WELLSPRING4),
377
	BCM5974_DEV(APPLE, WELLSPRING4_ISO, BCM5974_FLAG_WELLSPRING4),
378
	BCM5974_DEV(APPLE, WELLSPRING4_JIS, BCM5974_FLAG_WELLSPRING4),
379
380
	/* MacbookAir3,1 (unibody), aka wellspring4 */
381
	BCM5974_DEV(APPLE, WELLSPRING4A_ANSI, BCM5974_FLAG_WELLSPRING4A),
382
	BCM5974_DEV(APPLE, WELLSPRING4A_ISO, BCM5974_FLAG_WELLSPRING4A),
383
	BCM5974_DEV(APPLE, WELLSPRING4A_JIS, BCM5974_FLAG_WELLSPRING4A),
384
385
	/* Macbook8 (unibody, March 2011) */
386
	BCM5974_DEV(APPLE, WELLSPRING5_ANSI, BCM5974_FLAG_WELLSPRING5),
387
	BCM5974_DEV(APPLE, WELLSPRING5_ISO, BCM5974_FLAG_WELLSPRING5),
388
	BCM5974_DEV(APPLE, WELLSPRING5_JIS, BCM5974_FLAG_WELLSPRING5),
389
390
	/* MacbookAir4,1 (unibody, July 2011) */
391
	BCM5974_DEV(APPLE, WELLSPRING6A_ANSI, BCM5974_FLAG_WELLSPRING6A),
392
	BCM5974_DEV(APPLE, WELLSPRING6A_ISO, BCM5974_FLAG_WELLSPRING6A),
393
	BCM5974_DEV(APPLE, WELLSPRING6A_JIS, BCM5974_FLAG_WELLSPRING6A),
394
395
	/* MacbookAir4,2 (unibody, July 2011) */
396
	BCM5974_DEV(APPLE, WELLSPRING6_ANSI, BCM5974_FLAG_WELLSPRING6),
397
	BCM5974_DEV(APPLE, WELLSPRING6_ISO, BCM5974_FLAG_WELLSPRING6),
398
	BCM5974_DEV(APPLE, WELLSPRING6_JIS, BCM5974_FLAG_WELLSPRING6),
399
400
	/* Macbook8,2 (unibody) */
401
	BCM5974_DEV(APPLE, WELLSPRING5A_ANSI, BCM5974_FLAG_WELLSPRING5A),
402
	BCM5974_DEV(APPLE, WELLSPRING5A_ISO, BCM5974_FLAG_WELLSPRING5A),
403
	BCM5974_DEV(APPLE, WELLSPRING5A_JIS, BCM5974_FLAG_WELLSPRING5A),
404
405
	/* MacbookPro10,1 (unibody, June 2012) */
406
	/* MacbookPro11,1-3 (unibody, June 2013) */
407
	BCM5974_DEV(APPLE, WELLSPRING7_ANSI, BCM5974_FLAG_WELLSPRING7),
408
	BCM5974_DEV(APPLE, WELLSPRING7_ISO, BCM5974_FLAG_WELLSPRING7),
409
        BCM5974_DEV(APPLE, WELLSPRING7_JIS, BCM5974_FLAG_WELLSPRING7),
410
411
        /* MacbookPro10,2 (unibody, October 2012) */
412
        BCM5974_DEV(APPLE, WELLSPRING7A_ANSI, BCM5974_FLAG_WELLSPRING7A),
413
        BCM5974_DEV(APPLE, WELLSPRING7A_ISO, BCM5974_FLAG_WELLSPRING7A),
414
        BCM5974_DEV(APPLE, WELLSPRING7A_JIS, BCM5974_FLAG_WELLSPRING7A),
415
#endif
416
	/* MacbookAir6,2 (unibody, June 2013) */
417
	BCM5974_DEV(APPLE, WELLSPRING8_ANSI, BCM5974_FLAG_WELLSPRING8),
418
	BCM5974_DEV(APPLE, WELLSPRING8_ISO, BCM5974_FLAG_WELLSPRING8),
419
	BCM5974_DEV(APPLE, WELLSPRING8_JIS, BCM5974_FLAG_WELLSPRING8),
420
421
	/* MacbookPro12,1 MacbookPro11,4 */
422
	BCM5974_DEV(APPLE, WELLSPRING9_ANSI, BCM5974_FLAG_WELLSPRING9),
423
	BCM5974_DEV(APPLE, WELLSPRING9_ISO, BCM5974_FLAG_WELLSPRING9),
424
	BCM5974_DEV(APPLE, WELLSPRING9_JIS, BCM5974_FLAG_WELLSPRING9),
425
};
426
427
struct bcm5974_softc {
428
	device_t sc_dev;
429
	struct evdev_dev *sc_evdev;
430
	/* device configuration */
431
	const struct bcm5974_dev_params *sc_params;
432
};
433
434
static const uint8_t bcm5974_rdesc[] = {
435
	0x05, BCM5974_TLC_PAGE,	/* Usage Page (BCM5974_TLC_PAGE)	*/
436
	0x09, BCM5974_TLC_USAGE,/* Usage (BCM5974_TLC_USAGE)		*/
437
	0xA1, 0x01,		/* Collection (Application)		*/
438
	0x06, 0x00, 0xFF,	/*   Usage Page (Vendor Defined 0xFF00)	*/
439
	0x09, 0x01,		/*   Usage (0x01)			*/
440
	0x15, 0x00,		/*   Logical Minimum (0)		*/
441
	0x26, 0xFF, 0x00,	/*   Logical Maximum (255)		*/
442
	0x75, 0x08,		/*   Report Size (8)			*/
443
	0x96,			/*   Report Count (BCM5974_BUFFER_MAX)	*/
444
	BCM5974_BUFFER_MAX & 0xFF,
445
	BCM5974_BUFFER_MAX >> 8 & 0xFF,
446
	0x81, 0x02,		/*   Input (Data,Var,Abs)		*/
447
	0xC0,			/* End Collection			*/
448
};
449
450
/*
451
 * function prototypes
452
 */
453
static evdev_open_t	bcm5974_ev_open;
454
static evdev_close_t	bcm5974_ev_close;
455
static const struct evdev_methods bcm5974_evdev_methods = {
456
	.ev_open =	&bcm5974_ev_open,
457
	.ev_close =	&bcm5974_ev_close,
458
};
459
static hid_intr_t	bcm5974_intr;
460
461
/* Device methods. */
462
static device_identify_t bcm5974_identify;
463
static device_probe_t	bcm5974_probe;
464
static device_attach_t	bcm5974_attach;
465
static device_detach_t	bcm5974_detach;
466
467
#ifdef BCM5974_USB
468
/*
469
 * Type1 and Type2 touchpads use keyboard USB interface to switch from HID to
470
 * RAW mode. Although it is possible to extend hkbd driver to support such a
471
 * mode change requests, it's not wanted due to cross device tree dependencies.
472
 * So, find lowest common denominator (struct usb_device of grandparent usbhid
473
 * driver) of touchpad and keyboard drivers and issue direct USB requests.
474
 */
475
static int
476
bcm5974_set_device_mode_usb(struct bcm5974_softc *sc, bool on)
477
{
478
	uint8_t mode_bytes[BCM5974_USB_REPORT_LEN];
479
	struct usb_device *udev;
480
	device_t usbhid;
481
	usb_error_t err;
482
483
	usbhid = device_get_parent(device_get_parent(sc->sc_dev));
484
	if (device_get_devclass(usbhid) != devclass_find("usbhid"))
485
		return (ENXIO);
486
	udev = usbhid_get_usb_device(usbhid);
487
488
	err = usbd_req_get_report(udev, NULL, mode_bytes,
489
	    BCM5974_USB_REPORT_LEN, BCM5974_USB_IFACE_INDEX,
490
	    UHID_FEATURE_REPORT, BCM5974_USB_REPORT_ID);
491
	if (err != USB_ERR_NORMAL_COMPLETION) {
492
		DPRINTF("Failed to read device mode (%d)\n", err);
493
		return (EIO);
494
	}
495
#if 0
496
	/*
497
	 * XXX Need to wait at least 250ms for hardware to get
498
	 * ready. The device mode handling appears to be handled
499
	 * asynchronously and we should not issue these commands too
500
	 * quickly.
501
	 */
502
	pause("WHW", hz / 4);
503
#endif
504
	mode_bytes[0] = on ? BCM5974_USB_MODE_RAW : BCM5974_USB_MODE_HID;
505
506
	err = usbd_req_set_report(udev, NULL, mode_bytes,
507
	    BCM5974_USB_REPORT_LEN, BCM5974_USB_IFACE_INDEX,
508
	    UHID_FEATURE_REPORT, BCM5974_USB_REPORT_ID);
509
	if (err != USB_ERR_NORMAL_COMPLETION) {
510
		DPRINTF("Failed to write device mode (%d)\n", err);
511
		return (EIO);
512
	}
513
514
	return (0);
515
}
516
#endif
517
518
static int
519
bcm5974_set_device_mode_hid(struct bcm5974_softc *sc, bool on)
520
{
521
	uint8_t	mode_bytes[BCM5974_HID_REPORT_LEN] = {
522
		BCM5974_HID_REPORT_ID,
523
		on ? BCM5974_HID_MODE_RAW : BCM5974_HID_MODE_HID,
524
	};
525
#if 0
526
	int err;
527
528
	err = hid_get_report(sc->sc_dev, mode_bytes, BCM5974_HID_REPORT_LEN,
529
	    NULL, HID_FEATURE_REPORT, BCM5974_HID_REPORT_ID);
530
	if (err != 0) {
531
		DPRINTF("Failed to read device mode (%d)\n", err);
532
		return (err);
533
	}
534
	/*
535
	 * XXX Need to wait at least 250ms for hardware to get
536
	 * ready. The device mode handling appears to be handled
537
	 * asynchronously and we should not issue these commands too
538
	 * quickly.
539
	 */
540
	pause("WHW", hz / 4);
541
	mode_bytes[1] = on ? BCM5974_HID_MODE_RAW : BCM5974_HID_MODE_HID;
542
#endif
543
	return (hid_set_report(sc->sc_dev, mode_bytes, BCM5974_HID_REPORT_LEN,
544
	    HID_FEATURE_REPORT, BCM5974_HID_REPORT_ID));
545
}
546
547
static int
548
bcm5974_set_device_mode(struct bcm5974_softc *sc, bool on)
549
{
550
	int err = 0;
551
552
	switch (sc->sc_params->tp - tp) {
553
#ifdef BCM5974_USB
554
	case TYPE1:
555
	case TYPE2:
556
		err = bcm5974_set_device_mode_usb(sc, on);
557
		break;
558
#endif
559
	case TYPE3:	/* Type 3 does not require a mode switch */
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 (HIDBUS_LOOKUP_ID(parent, bcm5974_devs) != NULL &&
584
	    hid_get_report_descr(parent, &d_ptr, &d_len) == 0 &&
585
	    hid_is_mouse(d_ptr, d_len))
586
		hid_set_report_descr(parent, bcm5974_rdesc,
587
		    sizeof(bcm5974_rdesc));
588
}
589
590
static int
591
bcm5974_probe(device_t dev)
592
{
593
	int err;
594
595
	err = HIDBUS_LOOKUP_DRIVER_INFO(dev, bcm5974_devs);
596
	if (err != 0)
597
		return (err);
598
599
	hidbus_set_desc(dev, "Touchpad");
600
601
	return (BUS_PROBE_DEFAULT);
602
}
603
604
static int
605
bcm5974_attach(device_t dev)
606
{
607
	struct bcm5974_softc *sc = device_get_softc(dev);
608
	const struct hid_device_info *hw = hid_get_device_info(dev);
609
	int err;
610
611
	DPRINTFN(BCM5974_LLEVEL_INFO, "sc=%p\n", sc);
612
613
	sc->sc_dev = dev;
614
615
	/* get device specific configuration */
616
	sc->sc_params = bcm5974_dev_params + hidbus_get_driver_info(dev);
617
618
	sc->sc_evdev = evdev_alloc();
619
	evdev_set_name(sc->sc_evdev, device_get_desc(dev));
620
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
621
	evdev_set_id(sc->sc_evdev, hw->idBus, hw->idVendor, hw->idProduct,
622
	    hw->idVersion);
623
	evdev_set_serial(sc->sc_evdev, hw->serial);
624
	evdev_set_methods(sc->sc_evdev, sc, &bcm5974_evdev_methods);
625
	evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
626
	evdev_support_event(sc->sc_evdev, EV_SYN);
627
	evdev_support_event(sc->sc_evdev, EV_ABS);
628
	evdev_support_event(sc->sc_evdev, EV_KEY);
629
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_EXT_EPOCH); /* hidbus child */
630
631
#define BCM5974_ABS(evdev, code, param)					\
632
	evdev_support_abs((evdev), (code), (param).min, (param).max,	\
633
	((param).max - (param).min) / (param).snratio, 0,		\
634
	(param).size != 0 ? ((param).max - (param).min) / (param).size : 0);
635
636
	/* finger position */
637
	BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
638
	BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
639
	/* finger pressure */
640
	BCM5974_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
641
	/* finger touch area */
642
	BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
643
	BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
644
	/* finger approach area */
645
	BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
646
	BCM5974_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
647
	/* finger orientation */
648
	BCM5974_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
649
	/* button properties */
650
	evdev_support_key(sc->sc_evdev, BTN_LEFT);
651
	if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
652
		evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
653
	/* Enable automatic touch assignment for type B MT protocol */
654
	evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
655
	    0, MAX_FINGERS - 1, 0, 0, 0);
656
	evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
657
	    -1, MAX_FINGERS - 1, 0, 0, 0);
658
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
659
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
660
	/* Synaptics compatibility events */
661
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
662
663
	err = evdev_register(sc->sc_evdev);
664
	if (err)
665
		goto detach;
666
667
	hidbus_set_intr(dev, bcm5974_intr, sc);
668
669
	return (0);
670
671
detach:
672
	bcm5974_detach(dev);
673
	return (ENOMEM);
674
}
675
676
static int
677
bcm5974_detach(device_t dev)
678
{
679
	struct bcm5974_softc *sc = device_get_softc(dev);
680
681
	evdev_free(sc->sc_evdev);
682
683
	return (0);
684
}
685
686
static void
687
bcm5974_intr(void *context, void *data, hid_size_t len)
688
{
689
	struct bcm5974_softc *sc = context;
690
	const struct bcm5974_dev_params *params = sc->sc_params;
691
	union evdev_mt_slot slot_data;
692
	struct tp_finger *f;
693
	int ntouch;			/* the finger number in touch */
694
	int ibt;			/* button status */
695
	int i;
696
	int slot;
697
	uint8_t fsize = sizeof(struct tp_finger) + params->tp->delta;
698
699
	if ((len < params->tp->offset + fsize) ||
700
	    ((len - params->tp->offset) % fsize) != 0) {
701
		DPRINTFN(BCM5974_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
702
		    len, sc->tp_data[0], sc->tp_data[1]);
703
		return;
704
	}
705
706
	ibt = ((uint8_t *)data)[params->tp->button];
707
	ntouch = (len - params->tp->offset) / fsize;
708
709
	for (i = 0, slot = 0; i != ntouch; i++) {
710
		f = (struct tp_finger *)(((uint8_t *)data) +
711
		    params->tp->offset + params->tp->delta + i * fsize);
712
		DPRINTFN(BCM5974_LLEVEL_INFO,
713
		    "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
714
		    "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
715
		    "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
716
		    i, ibt, ntouch, le16toh(f->origin), le16toh(f->abs_x),
717
		    le16toh(f->abs_y), le16toh(f->rel_x), le16toh(f->rel_y),
718
		    le16toh(f->tool_major), le16toh(f->tool_minor),
719
		    le16toh(f->orientation), le16toh(f->touch_major),
720
		    le16toh(f->touch_minor), le16toh(f->pressure),
721
		    le16toh(f->multi));
722
723
		if (f->touch_major == 0)
724
			continue;
725
		slot_data = (union evdev_mt_slot) {
726
			.id = slot,
727
			.x = le16toh(f->abs_x),
728
			.y = params->y.min + params->y.max - le16toh(f->abs_y),
729
			.p = le16toh(f->pressure),
730
			.maj = le16toh(f->touch_major) << 1,
731
			.min = le16toh(f->touch_minor) << 1,
732
			.w_maj = le16toh(f->tool_major) << 1,
733
			.w_min = le16toh(f->tool_minor) << 1,
734
			.ori = params->o.max - le16toh(f->orientation),
735
		};
736
		evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
737
		slot++;
738
	}
739
740
	evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
741
	evdev_sync(sc->sc_evdev);
742
}
743
744
static int
745
bcm5974_ev_open(struct evdev_dev *evdev)
746
{
747
	struct bcm5974_softc *sc = evdev_get_softc(evdev);
748
	int err;
749
750
	/*
751
	 * By default the touchpad behaves like a HID device, sending
752
	 * packets with reportID = 8. Such reports contain only
753
	 * limited information. They encode movement deltas and button
754
	 * events, but do not include data from the pressure
755
	 * sensors. The device input mode can be switched from HID
756
	 * reports to raw sensor data using vendor-specific USB
757
	 * control commands:
758
	 */
759
	err = bcm5974_set_device_mode(sc, true);
760
	if (err != 0) {
761
		DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
762
		return (err);
763
	}
764
765
	return (hidbus_intr_start(sc->sc_dev));
766
}
767
768
static int
769
bcm5974_ev_close(struct evdev_dev *evdev)
770
{
771
	struct bcm5974_softc *sc = evdev_get_softc(evdev);
772
	int err;
773
774
	err = hidbus_intr_stop(sc->sc_dev);
775
	if (err != 0)
776
		return (err);
777
778
	/*
779
	 * During re-enumeration of the device we need to force the
780
	 * device back into HID mode before switching it to RAW
781
	 * mode. Else the device does not work like expected.
782
	 */
783
	err = bcm5974_set_device_mode(sc, false);
784
	if (err != 0)
785
		DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
786
787
	return (err);
788
}
789
790
static device_method_t bcm5974_methods[] = {
791
	/* Device interface */
792
	DEVMETHOD(device_identify,	bcm5974_identify),
793
	DEVMETHOD(device_probe,		bcm5974_probe),
794
	DEVMETHOD(device_attach,	bcm5974_attach),
795
	DEVMETHOD(device_detach,	bcm5974_detach),
796
	DEVMETHOD_END
797
};
798
799
static driver_t bcm5974_driver = {
800
	.name = "bcm5974",
801
	.methods = bcm5974_methods,
802
	.size = sizeof(struct bcm5974_softc)
803
};
804
805
static devclass_t bcm5974_devclass;
806
807
DRIVER_MODULE(bcm5974, hidbus, bcm5974_driver, bcm5974_devclass, NULL, 0);
808
MODULE_DEPEND(bcm5974, hidbus, 1, 1, 1);
809
MODULE_DEPEND(bcm5974, hid, 1, 1, 1);
810
#ifdef BCM5974_USB
811
MODULE_DEPEND(bcm5974, usb, 1, 1, 1);
812
MODULE_DEPEND(bcm5974, usbhid, 1, 1, 1);
813
#endif
814
MODULE_DEPEND(bcm5974, evdev, 1, 1, 1);
815
MODULE_VERSION(bcm5974, 1);
816
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/usbhid.c (-39 / +91 lines)
Lines 67-72 __FBSDID("$FreeBSD$"); Link Here
67
#include <dev/usb/usbdi.h>
67
#include <dev/usb/usbdi.h>
68
#include <dev/usb/usbdi_util.h>
68
#include <dev/usb/usbdi_util.h>
69
#include <dev/usb/usbhid.h>
69
#include <dev/usb/usbhid.h>
70
#include <dev/usb/input/usbhid.h>
70
71
71
#define	USB_DEBUG_VAR usbhid_debug
72
#define	USB_DEBUG_VAR usbhid_debug
72
#include <dev/usb/usb_debug.h>
73
#include <dev/usb/usb_debug.h>
Lines 85-108 SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, debug, CTLFLAG_RWTUN, Link Here
85
    &usbhid_debug, 0, "Debug level");
86
    &usbhid_debug, 0, "Debug level");
86
#endif
87
#endif
87
88
88
enum {
89
/* Second set of USB transfers for polling mode */
89
	USBHID_INTR_OUT_DT,
90
#define	POLL_XFER(xfer)	((xfer) + USBHID_N_TRANSFER)
90
	USBHID_INTR_IN_DT,
91
	USBHID_CTRL_DT,
92
	USBHID_N_TRANSFER,
93
};
94
91
95
struct usbhid_xfer_ctx;
92
struct usbhid_xfer_ctx;
96
typedef int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx);
93
typedef int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx);
97
94
98
union usbhid_device_request {
99
	struct {			/* INTR xfers */
100
		uint16_t maxlen;
101
		uint16_t actlen;
102
	} intr;
103
	struct usb_device_request ctrl;	/* CTRL xfers */
104
};
105
106
/* Syncronous USB transfer context */
95
/* Syncronous USB transfer context */
107
struct usbhid_xfer_ctx {
96
struct usbhid_xfer_ctx {
108
	union usbhid_device_request req;
97
	union usbhid_device_request req;
Lines 123-130 struct usbhid_softc { Link Here
123
112
124
	struct mtx sc_mtx;
113
	struct mtx sc_mtx;
125
	struct usb_config sc_config[USBHID_N_TRANSFER];
114
	struct usb_config sc_config[USBHID_N_TRANSFER];
126
	struct usb_xfer *sc_xfer[USBHID_N_TRANSFER];
115
	struct usb_xfer *sc_xfer[POLL_XFER(USBHID_N_TRANSFER)];
127
	struct usbhid_xfer_ctx sc_xfer_ctx[USBHID_N_TRANSFER];
116
	struct usbhid_xfer_ctx sc_xfer_ctx[POLL_XFER(USBHID_N_TRANSFER)];
128
117
129
	struct usb_device *sc_udev;
118
	struct usb_device *sc_udev;
130
	uint8_t	sc_iface_no;
119
	uint8_t	sc_iface_no;
Lines 144-149 static usb_callback_t usbhid_ctrl_callback; Link Here
144
static usbhid_callback_t usbhid_intr_handler_cb;
133
static usbhid_callback_t usbhid_intr_handler_cb;
145
static usbhid_callback_t usbhid_sync_wakeup_cb;
134
static usbhid_callback_t usbhid_sync_wakeup_cb;
146
135
136
struct usb_device *
137
usbhid_get_usb_device(device_t dev)
138
{
139
	struct usbhid_softc *sc = device_get_softc(dev);
140
141
	return (sc->sc_udev);
142
}
143
147
static void
144
static void
148
usbhid_intr_out_callback(struct usb_xfer *xfer, usb_error_t error)
145
usbhid_intr_out_callback(struct usb_xfer *xfer, usb_error_t error)
149
{
146
{
Lines 308-313 static const struct usb_config usbhid_config[USBHID_N_TRANSFER] = { Link Here
308
	},
305
	},
309
};
306
};
310
307
308
static inline usb_frlength_t
309
usbhid_xfer_max_len(struct usb_xfer *xfer)
310
{
311
	return (xfer == NULL ? 0 : usbd_xfer_max_len(xfer));
312
}
313
314
static inline int
315
usbhid_xfer_check_len(struct usb_xfer *xfer, hid_size_t len)
316
{
317
	if (xfer == NULL)
318
		return (ENODEV);
319
	if (len > usbd_xfer_max_len(xfer))
320
		return (ENOBUFS);
321
	return (0);
322
}
323
311
static void
324
static void
312
usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context,
325
usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context,
313
    struct hid_rdesc_info *rdesc)
326
    struct hid_rdesc_info *rdesc)
Lines 335-358 usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context, Link Here
335
	 * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
348
	 * itself, typically by hkbd via CTRL+ALT+ESC sequences. Or if the HID
336
	 * keyboard driver was processing a key at the moment of panic.
349
	 * keyboard driver was processing a key at the moment of panic.
337
	 */
350
	 */
338
	for (n = 0; n != USBHID_N_TRANSFER; n++) {
351
	for (n = 0; n != POLL_XFER(USBHID_N_TRANSFER); n++) {
352
		sc->sc_xfer[n] = NULL;
339
		if (nowrite && n == USBHID_INTR_OUT_DT)
353
		if (nowrite && n == USBHID_INTR_OUT_DT)
340
			continue;
354
			continue;
341
		error = usbd_transfer_setup(sc->sc_udev, &sc->sc_iface_index,
355
		error = usbd_transfer_setup(sc->sc_udev, &sc->sc_iface_index,
342
		    sc->sc_xfer + n, sc->sc_config + n, 1,
356
		    sc->sc_xfer + n, sc->sc_config + n % USBHID_N_TRANSFER, 1,
343
		    (void *)(sc->sc_xfer_ctx + n), &sc->sc_mtx);
357
		    (void *)(sc->sc_xfer_ctx + n), &sc->sc_mtx);
344
		if (error)
358
		if (error)
345
			break;
359
			DPRINTF("xfer %d setup error=%s\n", n,
360
			    usbd_errstr(error));
346
	}
361
	}
347
362
348
	if (error)
363
	rdesc->rdsize = usbhid_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]);
349
		DPRINTF("error=%s\n", usbd_errstr(error));
364
	rdesc->grsize = usbhid_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]);
350
351
	rdesc->rdsize = usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]);
352
	rdesc->grsize = usbd_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]);
353
	rdesc->srsize = rdesc->grsize;
365
	rdesc->srsize = rdesc->grsize;
354
	rdesc->wrsize = nowrite ? rdesc->srsize :
366
	rdesc->wrsize = nowrite ? rdesc->srsize :
355
	    usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]);
367
	    usbhid_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]);
356
368
357
	sc->sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
369
	sc->sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
358
}
370
}
Lines 363-368 usbhid_intr_unsetup(device_t dev) Link Here
363
	struct usbhid_softc* sc = device_get_softc(dev);
375
	struct usbhid_softc* sc = device_get_softc(dev);
364
376
365
	usbd_transfer_unsetup(sc->sc_xfer, USBHID_N_TRANSFER);
377
	usbd_transfer_unsetup(sc->sc_xfer, USBHID_N_TRANSFER);
378
	usbd_transfer_unsetup(
379
	    sc->sc_xfer, POLL_XFER(USBHID_N_TRANSFER));
366
	free(sc->sc_intr_buf, M_USBDEV);
380
	free(sc->sc_intr_buf, M_USBDEV);
367
}
381
}
368
382
Lines 371-376 usbhid_intr_start(device_t dev) Link Here
371
{
385
{
372
	struct usbhid_softc* sc = device_get_softc(dev);
386
	struct usbhid_softc* sc = device_get_softc(dev);
373
387
388
	if (sc->sc_xfer[USBHID_INTR_IN_DT] == NULL)
389
		return (ENODEV);
390
374
	mtx_lock(&sc->sc_mtx);
391
	mtx_lock(&sc->sc_mtx);
375
	sc->sc_xfer_ctx[USBHID_INTR_IN_DT] = (struct usbhid_xfer_ctx) {
392
	sc->sc_xfer_ctx[USBHID_INTR_IN_DT] = (struct usbhid_xfer_ctx) {
376
		.req.intr.maxlen =
393
		.req.intr.maxlen =
Lines 379-385 usbhid_intr_start(device_t dev) Link Here
379
		.cb_ctx = sc,
396
		.cb_ctx = sc,
380
		.buf = sc->sc_intr_buf,
397
		.buf = sc->sc_intr_buf,
381
	};
398
	};
399
	sc->sc_xfer_ctx[POLL_XFER(USBHID_INTR_IN_DT)] = (struct usbhid_xfer_ctx) {
400
		.req.intr.maxlen =
401
		    usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]),
402
		.cb = usbhid_intr_handler_cb,
403
		.cb_ctx = sc,
404
		.buf = sc->sc_intr_buf,
405
	};
382
	usbd_transfer_start(sc->sc_xfer[USBHID_INTR_IN_DT]);
406
	usbd_transfer_start(sc->sc_xfer[USBHID_INTR_IN_DT]);
407
	usbd_transfer_start(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
383
	mtx_unlock(&sc->sc_mtx);
408
	mtx_unlock(&sc->sc_mtx);
384
409
385
	return (0);
410
	return (0);
Lines 392-397 usbhid_intr_stop(device_t dev) Link Here
392
417
393
	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_IN_DT]);
418
	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_IN_DT]);
394
	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_OUT_DT]);
419
	usbd_transfer_drain(sc->sc_xfer[USBHID_INTR_OUT_DT]);
420
	usbd_transfer_drain(sc->sc_xfer[POLL_XFER(USBHID_INTR_IN_DT)]);
395
421
396
	return (0);
422
	return (0);
397
}
423
}
Lines 402-423 usbhid_intr_poll(device_t dev) Link Here
402
	struct usbhid_softc* sc = device_get_softc(dev);
428
	struct usbhid_softc* sc = device_get_softc(dev);
403
429
404
	usbd_transfer_poll(sc->sc_xfer + USBHID_INTR_IN_DT, 1);
430
	usbd_transfer_poll(sc->sc_xfer + USBHID_INTR_IN_DT, 1);
431
	usbd_transfer_poll(sc->sc_xfer + POLL_XFER(USBHID_INTR_IN_DT), 1);
405
}
432
}
406
433
407
/*
434
/*
408
 * HID interface
435
 * HID interface
409
 */
436
 */
410
static int
437
static int
411
usbhid_sync_xfer(struct usbhid_softc* sc, int xfer_idx,
438
usbhid_sync_xfer(struct usbhid_softc* sc, enum usbhid_xfer xfer_idx,
412
    union usbhid_device_request *req, void *buf)
439
    union usbhid_device_request *req, void *buf)
413
{
440
{
414
	int error, timeout;
441
	int error, timeout;
415
	struct usbhid_xfer_ctx *xfer_ctx, save;
442
	struct usbhid_xfer_ctx *xfer_ctx;
416
443
417
	xfer_ctx = sc->sc_xfer_ctx + xfer_idx;
444
	xfer_ctx = sc->sc_xfer_ctx + xfer_idx;
418
445
419
	if (USB_IN_POLLING_MODE_FUNC()) {
446
	if (USB_IN_POLLING_MODE_FUNC()) {
420
		save = *xfer_ctx;
447
		xfer_ctx = POLL_XFER(xfer_ctx);
448
		xfer_idx = POLL_XFER(xfer_idx);
421
	} else {
449
	} else {
422
		mtx_lock(&sc->sc_mtx);
450
		mtx_lock(&sc->sc_mtx);
423
		++xfer_ctx->waiters;
451
		++xfer_ctx->waiters;
Lines 455-463 usbhid_sync_xfer(struct usbhid_softc* sc, int xfer_idx, Link Here
455
	if (error == 0)
483
	if (error == 0)
456
		*req = xfer_ctx->req;
484
		*req = xfer_ctx->req;
457
485
458
	if (USB_IN_POLLING_MODE_FUNC()) {
486
	if (!USB_IN_POLLING_MODE_FUNC()) {
459
		*xfer_ctx = save;
460
	} else {
461
		xfer_ctx->influx = false;
487
		xfer_ctx->influx = false;
462
		if (xfer_ctx->waiters != 0)
488
		if (xfer_ctx->waiters != 0)
463
			wakeup_one(&xfer_ctx->waiters);
489
			wakeup_one(&xfer_ctx->waiters);
Lines 470-475 usbhid_sync_xfer(struct usbhid_softc* sc, int xfer_idx, Link Here
470
	return (error);
496
	return (error);
471
}
497
}
472
498
499
int
500
usbhid_do_request(device_t dev, enum usbhid_xfer xfer_idx,
501
    union usbhid_device_request *req, void *buf)
502
{
503
	struct usbhid_softc* sc = device_get_softc(dev);
504
	int error;
505
506
	error = usbhid_xfer_check_len(sc->sc_xfer[USBHID_CTRL_DT], 0);
507
	if (error)
508
		return (error);
509
510
	return (usbhid_sync_xfer(sc, xfer_idx, req, buf));
511
}
512
473
static int
513
static int
474
usbhid_get_rdesc(device_t dev, void *buf, hid_size_t len)
514
usbhid_get_rdesc(device_t dev, void *buf, hid_size_t len)
475
{
515
{
Lines 493-500 usbhid_get_report(device_t dev, void *buf, hid_size_t maxlen, Link Here
493
	union usbhid_device_request req;
533
	union usbhid_device_request req;
494
	int error;
534
	int error;
495
535
496
	if (maxlen > usbd_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]))
536
	error = usbhid_xfer_check_len(sc->sc_xfer[USBHID_CTRL_DT], maxlen);
497
		return (ENOBUFS);
537
	if (error)
538
		return (error);
498
539
499
	req.ctrl.bmRequestType = UT_READ_CLASS_INTERFACE;
540
	req.ctrl.bmRequestType = UT_READ_CLASS_INTERFACE;
500
	req.ctrl.bRequest = UR_GET_REPORT;
541
	req.ctrl.bRequest = UR_GET_REPORT;
Lines 516-524 usbhid_set_report(device_t dev, const void *buf, hid_size_t len, uint8_t type, Link Here
516
{
557
{
517
	struct usbhid_softc* sc = device_get_softc(dev);
558
	struct usbhid_softc* sc = device_get_softc(dev);
518
	union usbhid_device_request req;
559
	union usbhid_device_request req;
560
	int error;
519
561
520
	if (len > usbd_xfer_max_len(sc->sc_xfer[USBHID_CTRL_DT]))
562
	error = usbhid_xfer_check_len(sc->sc_xfer[USBHID_CTRL_DT], len);
521
		return (ENOBUFS);
563
	if (error)
564
		return (error);
522
565
523
	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
566
	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
524
	req.ctrl.bRequest = UR_SET_REPORT;
567
	req.ctrl.bRequest = UR_SET_REPORT;
Lines 538-545 usbhid_read(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen) Link Here
538
	union usbhid_device_request req;
581
	union usbhid_device_request req;
539
	int error;
582
	int error;
540
583
541
	if (maxlen > usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_IN_DT]))
584
	error = usbhid_xfer_check_len(sc->sc_xfer[USBHID_INTR_IN_DT], maxlen);
542
		return (ENOBUFS);
585
	if (error)
586
		return (error);
543
587
544
	req.intr.maxlen = maxlen;
588
	req.intr.maxlen = maxlen;
545
	error = usbhid_sync_xfer(sc, USBHID_INTR_IN_DT, &req, buf);
589
	error = usbhid_sync_xfer(sc, USBHID_INTR_IN_DT, &req, buf);
Lines 554-562 usbhid_write(device_t dev, const void *buf, hid_size_t len) Link Here
554
{
598
{
555
	struct usbhid_softc* sc = device_get_softc(dev);
599
	struct usbhid_softc* sc = device_get_softc(dev);
556
	union usbhid_device_request req;
600
	union usbhid_device_request req;
601
	int error;
557
602
558
	if (len > usbd_xfer_max_len(sc->sc_xfer[USBHID_INTR_OUT_DT]))
603
	error = usbhid_xfer_check_len(sc->sc_xfer[USBHID_INTR_OUT_DT], len);
559
		return (ENOBUFS);
604
	if (error)
605
		return (error);
560
606
561
	req.intr.maxlen = len;
607
	req.intr.maxlen = len;
562
	return (usbhid_sync_xfer(sc, USBHID_INTR_OUT_DT, &req,
608
	return (usbhid_sync_xfer(sc, USBHID_INTR_OUT_DT, &req,
Lines 569-574 usbhid_set_idle(device_t dev, uint16_t duration, uint8_t id) Link Here
569
	struct usbhid_softc* sc = device_get_softc(dev);
615
	struct usbhid_softc* sc = device_get_softc(dev);
570
	union usbhid_device_request req;
616
	union usbhid_device_request req;
571
617
618
	if (sc->sc_xfer[USBHID_CTRL_DT] == NULL)
619
		return (ENODEV);
620
572
	/* Duration is measured in 4 milliseconds per unit. */
621
	/* Duration is measured in 4 milliseconds per unit. */
573
	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
622
	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
574
	req.ctrl.bRequest = UR_SET_IDLE;
623
	req.ctrl.bRequest = UR_SET_IDLE;
Lines 586-591 usbhid_set_protocol(device_t dev, uint16_t protocol) Link Here
586
	struct usbhid_softc* sc = device_get_softc(dev);
635
	struct usbhid_softc* sc = device_get_softc(dev);
587
	union usbhid_device_request req;
636
	union usbhid_device_request req;
588
637
638
	if (sc->sc_xfer[USBHID_CTRL_DT] == NULL)
639
		return (ENODEV);
640
589
	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
641
	req.ctrl.bmRequestType = UT_WRITE_CLASS_INTERFACE;
590
	req.ctrl.bRequest = UR_SET_PROTOCOL;
642
	req.ctrl.bRequest = UR_SET_PROTOCOL;
591
	USETW(req.ctrl.wValue, protocol);
643
	USETW(req.ctrl.wValue, protocol);
(-)b/sys/dev/usb/input/usbhid.h (+54 lines)
Added Link Here
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-NetBSD
3
 *
4
 * Copyright (c) 2021 Vladimir Kondratyev <wulf@FreeBSD.org>
5
 *
6
 * This code is derived from software contributed to The NetBSD Foundation
7
 * by Lennart Augustsson (lennart@augustsson.net) at
8
 * Carlstedt Research & Technology.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#ifndef _USB_INPUT_USBHID_H_
33
#define _USB_INPUT_USBHID_H_
34
35
enum usbhid_xfer {
36
	USBHID_INTR_OUT_DT,
37
	USBHID_INTR_IN_DT,
38
	USBHID_CTRL_DT,
39
	USBHID_N_TRANSFER,
40
};
41
42
union usbhid_device_request {
43
	struct {                        /* INTR xfers */
44
		uint16_t maxlen;
45
		uint16_t actlen;
46
	} intr;
47
	struct usb_device_request ctrl; /* CTRL xfers */
48
};
49
50
struct usb_device *usbhid_get_usb_device(device_t);
51
int usbhid_do_request(device_t, enum usbhid_xfer,
52
    union usbhid_device_request *, void *);
53
54
#endif	/* _USB_INPUT_USBHID_H_ */
(-)b/sys/dev/usb/input/wsp.c (-220 / +385 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
	int size;			/* physical size, mm */
334
};
335
254
/* device-specific configuration */
336
/* device-specific configuration */
255
struct wsp_dev_params {
337
struct wsp_dev_params {
256
	uint8_t	caps;			/* device capability bitmask */
338
	const struct tp* tp;
257
	uint8_t	tp_type;		/* type of trackpad interface */
339
	struct wsp_param p;		/* finger pressure limits */
258
	uint8_t	tp_button;		/* offset to button data */
340
	struct wsp_param w;		/* finger width limits */
259
	uint8_t	tp_offset;		/* offset to trackpad finger data */
341
	struct wsp_param x;		/* horizontal limits */
260
	uint8_t tp_fsize;		/* bytes in single finger block */
342
	struct wsp_param y;		/* vertical limits */
261
	uint8_t tp_delta;		/* offset from header to finger struct */
343
	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
};
344
};
270
345
346
/* logical signal quality */
347
#define	SN_PRESSURE	45		/* pressure signal-to-noise ratio */
348
#define	SN_WIDTH	25		/* width signal-to-noise ratio */
349
#define	SN_COORD	250		/* coordinate signal-to-noise ratio */
350
#define	SN_ORIENT	10		/* orientation signal-to-noise ratio */
351
271
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
352
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
272
	[WSP_FLAG_WELLSPRING1] = {
353
	[WSP_FLAG_WELLSPRING1] = {
273
		.caps = 0,
354
		.tp = tp + TYPE1,
274
		.tp_type = TYPE1,
355
		.p = { SN_PRESSURE, 0, 256, 0 },
275
		.tp_button = 0,
356
		.w = { SN_WIDTH, 0, 2048, 0 },
276
		.tp_offset = FINGER_TYPE1,
357
		.x = { SN_COORD, -4824, 5342, 105 },
277
		.tp_fsize = FSIZE_TYPE1,
358
		.y = { SN_COORD, -172, 5820, 75 },
278
		.tp_delta = 0,
359
		.o = { SN_ORIENT,
279
		.iface_index = 0,
360
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
361
	},
287
	[WSP_FLAG_WELLSPRING2] = {
362
	[WSP_FLAG_WELLSPRING2] = {
288
		.caps = 0,
363
		.tp = tp + TYPE1,
289
		.tp_type = TYPE1,
364
		.p = { SN_PRESSURE, 0, 256, 0 },
290
		.tp_button = 0,
365
		.w = { SN_WIDTH, 0, 2048, 0 },
291
		.tp_offset = FINGER_TYPE1,
366
		.x = { SN_COORD, -4824, 4824, 105 },
292
		.tp_fsize = FSIZE_TYPE1,
367
		.y = { SN_COORD, -172, 4290, 75 },
293
		.tp_delta = 0,
368
		.o = { SN_ORIENT,
294
		.iface_index = 0,
369
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
370
	},
302
	[WSP_FLAG_WELLSPRING3] = {
371
	[WSP_FLAG_WELLSPRING3] = {
303
		.caps = HAS_INTEGRATED_BUTTON,
372
		.tp = tp + TYPE2,
304
		.tp_type = TYPE2,
373
		.p = { SN_PRESSURE, 0, 300, 0 },
305
		.tp_button = BUTTON_TYPE2,
374
		.w = { SN_WIDTH, 0, 2048, 0 },
306
		.tp_offset = FINGER_TYPE2,
375
		.x = { SN_COORD, -4460, 5166, 105 },
307
		.tp_fsize = FSIZE_TYPE2,
376
		.y = { SN_COORD, -75, 6700, 75 },
308
		.tp_delta = 0,
377
		.o = { SN_ORIENT,
309
		.iface_index = 0,
378
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
379
	},
317
	[WSP_FLAG_WELLSPRING4] = {
380
	[WSP_FLAG_WELLSPRING4] = {
318
		.caps = HAS_INTEGRATED_BUTTON,
381
		.tp = tp + TYPE2,
319
		.tp_type = TYPE2,
382
		.p = { SN_PRESSURE, 0, 300, 0 },
320
		.tp_button = BUTTON_TYPE2,
383
		.w = { SN_WIDTH, 0, 2048, 0 },
321
		.tp_offset = FINGER_TYPE2,
384
		.x = { SN_COORD, -4620, 5140, 105 },
322
		.tp_fsize = FSIZE_TYPE2,
385
		.y = { SN_COORD, -150, 6600, 75 },
323
		.tp_delta = 0,
386
		.o = { SN_ORIENT,
324
		.iface_index = 0,
387
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
388
	},
332
	[WSP_FLAG_WELLSPRING4A] = {
389
	[WSP_FLAG_WELLSPRING4A] = {
333
		.caps = HAS_INTEGRATED_BUTTON,
390
		.tp = tp + TYPE2,
334
		.tp_type = TYPE2,
391
		.p = { SN_PRESSURE, 0, 300, 0 },
335
		.tp_button = BUTTON_TYPE2,
392
		.w = { SN_WIDTH, 0, 2048, 0 },
336
		.tp_offset = FINGER_TYPE2,
393
		.x = { SN_COORD, -4616, 5112, 105 },
337
		.tp_fsize = FSIZE_TYPE2,
394
		.y = { SN_COORD, -142, 5234, 75 },
338
		.tp_delta = 0,
395
		.o = { SN_ORIENT,
339
		.iface_index = 0,
396
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
397
	},
347
	[WSP_FLAG_WELLSPRING5] = {
398
	[WSP_FLAG_WELLSPRING5] = {
348
		.caps = HAS_INTEGRATED_BUTTON,
399
		.tp = tp + TYPE2,
349
		.tp_type = TYPE2,
400
		.p = { SN_PRESSURE, 0, 300, 0 },
350
		.tp_button = BUTTON_TYPE2,
401
		.w = { SN_WIDTH, 0, 2048, 0 },
351
		.tp_offset = FINGER_TYPE2,
402
		.x = { SN_COORD, -4415, 5050, 105 },
352
		.tp_fsize = FSIZE_TYPE2,
403
		.y = { SN_COORD, -55, 6680, 75 },
353
		.tp_delta = 0,
404
		.o = { SN_ORIENT,
354
		.iface_index = 0,
405
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
406
	},
362
	[WSP_FLAG_WELLSPRING6] = {
407
	[WSP_FLAG_WELLSPRING6] = {
363
		.caps = HAS_INTEGRATED_BUTTON,
408
		.tp = tp + TYPE2,
364
		.tp_type = TYPE2,
409
		.p = { SN_PRESSURE, 0, 300, 0 },
365
		.tp_button = BUTTON_TYPE2,
410
		.w = { SN_WIDTH, 0, 2048, 0 },
366
		.tp_offset = FINGER_TYPE2,
411
		.x = { SN_COORD, -4620, 5140, 105 },
367
		.tp_fsize = FSIZE_TYPE2,
412
		.y = { SN_COORD, -150, 6600, 75 },
368
		.tp_delta = 0,
413
		.o = { SN_ORIENT,
369
		.iface_index = 0,
414
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
415
	},
377
	[WSP_FLAG_WELLSPRING5A] = {
416
	[WSP_FLAG_WELLSPRING5A] = {
378
		.caps = HAS_INTEGRATED_BUTTON,
417
		.tp = tp + TYPE2,
379
		.tp_type = TYPE2,
418
		.p = { SN_PRESSURE, 0, 300, 0 },
380
		.tp_button = BUTTON_TYPE2,
419
		.w = { SN_WIDTH, 0, 2048, 0 },
381
		.tp_offset = FINGER_TYPE2,
420
		.x = { SN_COORD, -4750, 5280, 105 },
382
		.tp_fsize = FSIZE_TYPE2,
421
		.y = { SN_COORD, -150, 6730, 75 },
383
		.tp_delta = 0,
422
		.o = { SN_ORIENT,
384
		.iface_index = 0,
423
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
424
	},
392
	[WSP_FLAG_WELLSPRING6A] = {
425
	[WSP_FLAG_WELLSPRING6A] = {
393
		.caps = HAS_INTEGRATED_BUTTON,
426
		.tp = tp + TYPE2,
394
		.tp_type = TYPE2,
427
		.p = { SN_PRESSURE, 0, 300, 0 },
395
		.tp_button = BUTTON_TYPE2,
428
		.w = { SN_WIDTH, 0, 2048, 0 },
396
		.tp_offset = FINGER_TYPE2,
429
		.x = { SN_COORD, -4620, 5140, 105 },
397
		.tp_fsize = FSIZE_TYPE2,
430
		.y = { SN_COORD, -150, 6600, 75 },
398
		.tp_delta = 0,
431
		.o = { SN_ORIENT,
399
		.um_size = 8,
432
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
433
	},
406
	[WSP_FLAG_WELLSPRING7] = {
434
	[WSP_FLAG_WELLSPRING7] = {
407
		.caps = HAS_INTEGRATED_BUTTON,
435
		.tp = tp + TYPE2,
408
		.tp_type = TYPE2,
436
		.p = { SN_PRESSURE, 0, 300, 0 },
409
		.tp_button = BUTTON_TYPE2,
437
		.w = { SN_WIDTH, 0, 2048, 0 },
410
		.tp_offset = FINGER_TYPE2,
438
		.x = { SN_COORD, -4750, 5280, 105 },
411
		.tp_fsize = FSIZE_TYPE2,
439
		.y = { SN_COORD, -150, 6730, 75 },
412
		.tp_delta = 0,
440
		.o = { SN_ORIENT,
413
		.iface_index = 0,
441
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
442
	},
421
	[WSP_FLAG_WELLSPRING7A] = {
443
	[WSP_FLAG_WELLSPRING7A] = {
422
		.caps = HAS_INTEGRATED_BUTTON,
444
		.tp = tp + TYPE2,
423
		.tp_type = TYPE2,
445
		.p = { SN_PRESSURE, 0, 300, 0 },
424
		.tp_button = BUTTON_TYPE2,
446
		.w = { SN_WIDTH, 0, 2048, 0 },
425
		.tp_offset = FINGER_TYPE2,
447
		.x = { SN_COORD, -4750, 5280, 105 },
426
		.tp_fsize = FSIZE_TYPE2,
448
		.y = { SN_COORD, -150, 6730, 75 },
427
		.tp_delta = 0,
449
		.o = { SN_ORIENT,
428
		.iface_index = 0,
450
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
451
	},
436
	[WSP_FLAG_WELLSPRING8] = {
452
	[WSP_FLAG_WELLSPRING8] = {
437
		.caps = HAS_INTEGRATED_BUTTON,
453
		.tp = tp + TYPE3,
438
		.tp_type = TYPE3,
454
		.p = { SN_PRESSURE, 0, 300, 0 },
439
		.tp_button = BUTTON_TYPE3,
455
		.w = { SN_WIDTH, 0, 2048, 0 },
440
		.tp_offset = FINGER_TYPE3,
456
		.x = { SN_COORD, -4620, 5140, 105 },
441
		.tp_fsize = FSIZE_TYPE3,
457
		.y = { SN_COORD, -150, 6600, 75 },
442
		.tp_delta = 0,
458
		.o = { SN_ORIENT,
443
		.iface_index = 0,
459
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
460
	},
451
	[WSP_FLAG_WELLSPRING9] = {
461
	[WSP_FLAG_WELLSPRING9] = {
452
		.caps = HAS_INTEGRATED_BUTTON,
462
		.tp = tp + TYPE4,
453
		.tp_type = TYPE4,
463
		.p = { SN_PRESSURE, 0, 300, 0 },
454
		.tp_button = BUTTON_TYPE4,
464
		.w = { SN_WIDTH, 0, 2048, 0 },
455
		.tp_offset = FINGER_TYPE4,
465
		.x = { SN_COORD, -4828, 5345, 105 },
456
		.tp_fsize = FSIZE_TYPE4,
466
		.y = { SN_COORD, -203, 6803, 75 },
457
		.tp_delta = 2,
467
		.o = { SN_ORIENT,
458
		.iface_index = 2,
468
		    -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION, 0 },
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
	},
469
	},
466
};
470
};
467
#define	WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
471
#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
554
551
	const struct wsp_dev_params *sc_params;	/* device configuration */
555
	const struct wsp_dev_params *sc_params;	/* device configuration */
552
556
557
#ifdef EVDEV_SUPPORT
558
	struct evdev_dev *sc_evdev;
559
#endif
553
	mousehw_t sc_hw;
560
	mousehw_t sc_hw;
554
	mousemode_t sc_mode;
561
	mousemode_t sc_mode;
555
	u_int	sc_pollrate;
562
	u_int	sc_pollrate;
556
	mousestatus_t sc_status;
563
	mousestatus_t sc_status;
564
	int	sc_fflags;
557
	u_int	sc_state;
565
	u_int	sc_state;
558
#define	WSP_ENABLED	       0x01
566
#define	WSP_ENABLED		0x01
567
#define	WSP_EVDEV_OPENED	0x02
559
568
560
	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
569
	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
561
	int16_t	pos_x[MAX_FINGERS];	/* position array */
570
	int16_t	pos_x[MAX_FINGERS];	/* position array */
Lines 596-603 struct wsp_softc { Link Here
596
/*
605
/*
597
 * function prototypes
606
 * function prototypes
598
 */
607
 */
599
static usb_fifo_cmd_t wsp_start_read;
608
static usb_fifo_cmd_t wsp_fifo_start_read;
600
static usb_fifo_cmd_t wsp_stop_read;
609
static usb_fifo_cmd_t wsp_fifo_stop_read;
601
static usb_fifo_open_t wsp_open;
610
static usb_fifo_open_t wsp_open;
602
static usb_fifo_close_t wsp_close;
611
static usb_fifo_close_t wsp_close;
603
static usb_fifo_ioctl_t wsp_ioctl;
612
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,
615
	.f_open = &wsp_open,
607
	.f_close = &wsp_close,
616
	.f_close = &wsp_close,
608
	.f_ioctl = &wsp_ioctl,
617
	.f_ioctl = &wsp_ioctl,
609
	.f_start_read = &wsp_start_read,
618
	.f_start_read = &wsp_fifo_start_read,
610
	.f_stop_read = &wsp_stop_read,
619
	.f_stop_read = &wsp_fifo_stop_read,
611
	.basename[0] = WSP_DRIVER_NAME,
620
	.basename[0] = WSP_DRIVER_NAME,
612
};
621
};
613
622
623
#ifdef EVDEV_SUPPORT
624
static evdev_open_t wsp_ev_open;
625
static evdev_close_t wsp_ev_close;
626
static const struct evdev_methods wsp_evdev_methods = {
627
	.ev_open = &wsp_ev_open,
628
	.ev_close = &wsp_ev_close,
629
};
630
#endif
631
614
/* device initialization and shutdown */
632
/* device initialization and shutdown */
615
static int wsp_enable(struct wsp_softc *sc);
633
static int wsp_enable(struct wsp_softc *sc);
616
static void wsp_disable(struct wsp_softc *sc);
634
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;
665
	usb_error_t err;
648
666
649
	/* Type 3 does not require a mode switch */
667
	/* Type 3 does not require a mode switch */
650
	if (params->tp_type == TYPE3)
668
	if (params->tp == tp + TYPE3)
651
		return 0;
669
		return 0;
652
670
653
	err = usbd_req_get_report(sc->sc_usb_device, NULL,
671
	err = usbd_req_get_report(sc->sc_usb_device, NULL,
654
	    mode_bytes, params->um_size, params->iface_index,
672
	    mode_bytes, params->tp->um_size, params->tp->iface_index,
655
	    params->um_req_val, params->um_req_idx);
673
	    UHID_FEATURE_REPORT, params->tp->um_req_idx);
656
674
657
	if (err != USB_ERR_NORMAL_COMPLETION) {
675
	if (err != USB_ERR_NORMAL_COMPLETION) {
658
		DPRINTF("Failed to read device mode (%d)\n", err);
676
		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
	 */
685
	 */
668
	pause("WHW", hz / 4);
686
	pause("WHW", hz / 4);
669
687
670
	mode_bytes[params->um_switch_idx] = 
688
	mode_bytes[params->tp->um_switch_idx] =
671
	    on ? params->um_switch_on : params->um_switch_off;
689
	    on ? params->tp->um_switch_on : params->tp->um_switch_off;
672
690
673
	return (usbd_req_set_report(sc->sc_usb_device, NULL,
691
	return (usbd_req_set_report(sc->sc_usb_device, NULL,
674
	    mode_bytes, params->um_size, params->iface_index, 
692
	    mode_bytes, params->tp->um_size, params->tp->iface_index,
675
	    params->um_req_val, params->um_req_idx));
693
	    UHID_FEATURE_REPORT, params->tp->um_req_idx));
676
}
694
}
677
695
678
static int
696
static int
Lines 720-726 wsp_probe(device_t self) Link Here
720
	/* check if we are attaching to the first match */
738
	/* check if we are attaching to the first match */
721
	if (uaa->info.bIfaceIndex != i)
739
	if (uaa->info.bIfaceIndex != i)
722
		return (ENXIO);
740
		return (ENXIO);
723
	return (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa));
741
	if (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa) != 0)
742
		return (ENXIO);
743
744
	return (BUS_PROBE_DEFAULT);
724
}
745
}
725
746
726
static int
747
static int
Lines 816-821 wsp_attach(device_t dev) Link Here
816
	sc->sc_touch = WSP_UNTOUCH;
837
	sc->sc_touch = WSP_UNTOUCH;
817
	sc->scr_mode = WSP_SCR_NONE;
838
	sc->scr_mode = WSP_SCR_NONE;
818
839
840
#ifdef EVDEV_SUPPORT
841
	sc->sc_evdev = evdev_alloc();
842
	evdev_set_name(sc->sc_evdev, device_get_desc(dev));
843
	evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
844
	evdev_set_id(sc->sc_evdev, BUS_USB, uaa->info.idVendor,
845
	    uaa->info.idProduct, 0);
846
	evdev_set_serial(sc->sc_evdev, usb_get_serial(uaa->device));
847
	evdev_set_methods(sc->sc_evdev, sc, &wsp_evdev_methods);
848
	evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
849
	evdev_support_event(sc->sc_evdev, EV_SYN);
850
	evdev_support_event(sc->sc_evdev, EV_ABS);
851
	evdev_support_event(sc->sc_evdev, EV_KEY);
852
853
#define WSP_SUPPORT_ABS(evdev, code, param)				\
854
	evdev_support_abs((evdev), (code), (param).min, (param).max,	\
855
	((param).max - (param).min) / (param).snratio, 0,		\
856
	(param).size != 0 ? ((param).max - (param).min) / (param).size : 0);
857
858
	/* finger position */
859
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x);
860
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y);
861
	/* finger pressure */
862
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p);
863
	/* finger touch area */
864
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w);
865
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w);
866
	/* finger approach area */
867
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->sc_params->w);
868
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->sc_params->w);
869
	/* finger orientation */
870
	WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->sc_params->o);
871
	/* button properties */
872
	evdev_support_key(sc->sc_evdev, BTN_LEFT);
873
	if ((sc->sc_params->tp->caps & HAS_INTEGRATED_BUTTON) != 0)
874
		evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
875
	/* Enable automatic touch assignment for type B MT protocol */
876
	evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
877
	    0, MAX_FINGERS - 1, 0, 0, 0);
878
	evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
879
	    -1, MAX_FINGERS - 1, 0, 0, 0);
880
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
881
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
882
	/* Synaptics compatibility events */
883
	evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
884
885
	err = evdev_register(sc->sc_evdev);
886
	if (err)
887
		goto detach;
888
#endif
889
819
	return (0);
890
	return (0);
820
891
821
detach:
892
detach:
Lines 837-842 wsp_detach(device_t dev) Link Here
837
908
838
	usb_fifo_detach(&sc->sc_fifo);
909
	usb_fifo_detach(&sc->sc_fifo);
839
910
911
#ifdef EVDEV_SUPPORT
912
	evdev_free(sc->sc_evdev);
913
#endif
914
840
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
915
	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
841
916
842
	mtx_destroy(&sc->sc_mutex);
917
	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;
938
	int rdz = 0;
864
	int len;
939
	int len;
865
	int i;
940
	int i;
941
#ifdef EVDEV_SUPPORT
942
	int slot = 0;
943
#endif
866
944
867
	wsp_runing_rangecheck(&tun);
945
	wsp_runing_rangecheck(&tun);
868
946
Lines 878-885 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
878
		pc = usbd_xfer_get_frame(xfer, 0);
956
		pc = usbd_xfer_get_frame(xfer, 0);
879
		usbd_copy_out(pc, 0, sc->tp_data, len);
957
		usbd_copy_out(pc, 0, sc->tp_data, len);
880
958
881
		if ((len < params->tp_offset + params->tp_fsize) ||
959
		if ((len < params->tp->offset + params->tp->fsize) ||
882
		    ((len - params->tp_offset) % params->tp_fsize) != 0) {
960
		    ((len - params->tp->offset) % params->tp->fsize) != 0) {
883
			DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
961
			DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
884
			    len, sc->tp_data[0], sc->tp_data[1]);
962
			    len, sc->tp_data[0], sc->tp_data[1]);
885
			goto tr_setup;
963
			goto tr_setup;
Lines 892-901 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
892
970
893
		h = (struct tp_header *)(sc->tp_data);
971
		h = (struct tp_header *)(sc->tp_data);
894
972
895
		if (params->tp_type >= TYPE2) {
973
		if (params->tp != tp + TYPE1) {
896
			ibt = sc->tp_data[params->tp_button];
974
			ibt = sc->tp_data[params->tp->button];
897
			ntouch = sc->tp_data[params->tp_button - 1];
975
			ntouch = sc->tp_data[params->tp->button - 1];
898
		}
976
		} else
977
			ntouch = (len - params->tp->offset) / params->tp->fsize;
978
899
		/* range check */
979
		/* range check */
900
		if (ntouch < 0)
980
		if (ntouch < 0)
901
			ntouch = 0;
981
			ntouch = 0;
Lines 903-909 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
903
			ntouch = MAX_FINGERS;
983
			ntouch = MAX_FINGERS;
904
984
905
		for (i = 0; i != ntouch; i++) {
985
		for (i = 0; i != ntouch; i++) {
906
			f = (struct tp_finger *)(sc->tp_data + params->tp_offset + params->tp_delta + i * params->tp_fsize);
986
			f = (struct tp_finger *)(sc->tp_data + params->tp->offset + params->tp->delta + i * params->tp->fsize);
907
			/* swap endianness, if any */
987
			/* swap endianness, if any */
908
			if (le16toh(0x1234) != 0x1234) {
988
			if (le16toh(0x1234) != 0x1234) {
909
				f->origin = le16toh((uint16_t)f->origin);
989
				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;
1009
			sc->pos_x[i] = f->abs_x;
930
			sc->pos_y[i] = -f->abs_y;
1010
			sc->pos_y[i] = -f->abs_y;
931
			sc->index[i] = f;
1011
			sc->index[i] = f;
1012
#ifdef EVDEV_SUPPORT
1013
			if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE && f->touch_major != 0) {
1014
				union evdev_mt_slot slot_data = {
1015
					.id = slot,
1016
					.x = f->abs_x,
1017
					.y = params->y.min + params->y.max - f->abs_y,
1018
					.p = f->pressure,
1019
					.maj = f->touch_major << 1,
1020
					.min = f->touch_minor << 1,
1021
					.w_maj = f->tool_major << 1,
1022
					.w_min = f->tool_minor << 1,
1023
					.ori = params->o.max - f->orientation,
1024
				};
1025
				evdev_mt_push_slot(sc->sc_evdev, slot, &slot_data);
1026
				slot++;
1027
			}
1028
#endif
932
		}
1029
		}
933
1030
1031
#ifdef EVDEV_SUPPORT
1032
		if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1033
			evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
1034
			evdev_sync(sc->sc_evdev);
1035
		}
1036
#endif
934
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
1037
		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
935
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
1038
		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
936
		sc->sc_status.obutton = sc->sc_status.button;
1039
		sc->sc_status.obutton = sc->sc_status.button;
937
		sc->sc_status.button = 0;
1040
		sc->sc_status.button = 0;
938
1041
939
		if (ibt != 0) {
1042
		if (ibt != 0) {
940
			if ((params->caps & HAS_INTEGRATED_BUTTON) && ntouch == 2)
1043
			if ((params->tp->caps & HAS_INTEGRATED_BUTTON) && ntouch == 2)
941
				sc->sc_status.button |= MOUSE_BUTTON3DOWN;
1044
				sc->sc_status.button |= MOUSE_BUTTON3DOWN;
942
			else if ((params->caps & HAS_INTEGRATED_BUTTON) && ntouch == 3)
1045
			else if ((params->tp->caps & HAS_INTEGRATED_BUTTON) && ntouch == 3)
943
				sc->sc_status.button |= MOUSE_BUTTON2DOWN;
1046
				sc->sc_status.button |= MOUSE_BUTTON2DOWN;
944
			else 
1047
			else 
945
				sc->sc_status.button |= MOUSE_BUTTON1DOWN;
1048
				sc->sc_status.button |= MOUSE_BUTTON1DOWN;
Lines 986-992 wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) Link Here
986
				 */
1089
				 */
987
				switch (sc->ntaps) {
1090
				switch (sc->ntaps) {
988
				case 1:
1091
				case 1:
989
					if (!(params->caps & HAS_INTEGRATED_BUTTON) || tun.enable_single_tap_clicks) {
1092
					if (!(params->tp->caps & HAS_INTEGRATED_BUTTON) || tun.enable_single_tap_clicks) {
990
						wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
1093
						wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
991
						DPRINTFN(WSP_LLEVEL_INFO, "LEFT CLICK!\n");
1094
						DPRINTFN(WSP_LLEVEL_INFO, "LEFT CLICK!\n");
992
					}
1095
					}
Lines 1235-1243 wsp_reset_buf(struct wsp_softc *sc) Link Here
1235
}
1338
}
1236
1339
1237
static void
1340
static void
1238
wsp_start_read(struct usb_fifo *fifo)
1341
wsp_start_read(struct wsp_softc *sc)
1239
{
1342
{
1240
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1241
	int rate;
1343
	int rate;
1242
1344
1243
	/* Check if we should override the default polling interval */
1345
	/* Check if we should override the default polling interval */
Lines 1258-1306 wsp_start_read(struct usb_fifo *fifo) Link Here
1258
}
1360
}
1259
1361
1260
static void
1362
static void
1261
wsp_stop_read(struct usb_fifo *fifo)
1363
wsp_stop_read(struct wsp_softc *sc)
1262
{
1364
{
1263
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1264
1265
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1365
	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
1266
}
1366
}
1267
1367
1268
static int
1368
static int
1269
wsp_open(struct usb_fifo *fifo, int fflags)
1369
wsp_open(struct usb_fifo *fifo, int fflags)
1270
{
1370
{
1271
	DPRINTFN(WSP_LLEVEL_INFO, "\n");
1371
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1372
	int rc = 0;
1272
1373
1273
	if (fflags & FREAD) {
1374
	DPRINTFN(WSP_LLEVEL_INFO, "\n");
1274
		struct wsp_softc *sc = usb_fifo_softc(fifo);
1275
		int rc;
1276
1375
1277
		if (sc->sc_state & WSP_ENABLED)
1376
	if (sc->sc_fflags & fflags)
1278
			return (EBUSY);
1377
		return (EBUSY);
1279
1378
1379
	if (fflags & FREAD) {
1280
		if (usb_fifo_alloc_buffer(fifo,
1380
		if (usb_fifo_alloc_buffer(fifo,
1281
		    WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
1381
		    WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
1282
			return (ENOMEM);
1382
			return (ENOMEM);
1283
		}
1383
		}
1284
		rc = wsp_enable(sc);
1384
#ifdef EVDEV_SUPPORT
1385
		if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1386
#endif
1387
			rc = wsp_enable(sc);
1285
		if (rc != 0) {
1388
		if (rc != 0) {
1286
			usb_fifo_free_buffer(fifo);
1389
			usb_fifo_free_buffer(fifo);
1287
			return (rc);
1390
			return (rc);
1288
		}
1391
		}
1289
	}
1392
	}
1393
	sc->sc_fflags |= fflags & (FREAD | FWRITE);
1290
	return (0);
1394
	return (0);
1291
}
1395
}
1292
1396
1293
static void
1397
static void
1294
wsp_close(struct usb_fifo *fifo, int fflags)
1398
wsp_close(struct usb_fifo *fifo, int fflags)
1295
{
1399
{
1296
	if (fflags & FREAD) {
1400
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1297
		struct wsp_softc *sc = usb_fifo_softc(fifo);
1298
1401
1299
		wsp_disable(sc);
1402
	if (fflags & FREAD) {
1403
#ifdef EVDEV_SUPPORT
1404
		if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1405
#endif
1406
			wsp_disable(sc);
1300
		usb_fifo_free_buffer(fifo);
1407
		usb_fifo_free_buffer(fifo);
1301
	}
1408
	}
1409
1410
	sc->sc_fflags &= ~(fflags & (FREAD | FWRITE));
1302
}
1411
}
1303
1412
1413
static void
1414
wsp_fifo_start_read(struct usb_fifo *fifo)
1415
{
1416
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1417
1418
	wsp_start_read(sc);
1419
}
1420
1421
static void
1422
wsp_fifo_stop_read(struct usb_fifo *fifo)
1423
{
1424
	struct wsp_softc *sc = usb_fifo_softc(fifo);
1425
1426
#ifdef EVDEV_SUPPORT
1427
	if ((sc->sc_state & WSP_EVDEV_OPENED) == 0)
1428
#endif
1429
		wsp_stop_read(sc);
1430
}
1431
1432
#ifdef EVDEV_SUPPORT
1433
static int
1434
wsp_ev_open(struct evdev_dev *evdev)
1435
{
1436
	struct wsp_softc *sc = evdev_get_softc(evdev);
1437
	int rc = 0;
1438
1439
	mtx_lock(&sc->sc_mutex);
1440
	if (sc->sc_fflags == 0)
1441
		rc = wsp_enable(sc);
1442
	if (rc == 0) {
1443
		wsp_start_read(sc);
1444
		sc->sc_state |= WSP_EVDEV_OPENED;
1445
	}
1446
	mtx_unlock(&sc->sc_mutex);
1447
1448
	return (rc);
1449
}
1450
1451
static int
1452
wsp_ev_close(struct evdev_dev *evdev)
1453
{
1454
	struct wsp_softc *sc = evdev_get_softc(evdev);
1455
1456
	mtx_lock(&sc->sc_mutex);
1457
	sc->sc_state &= ~WSP_EVDEV_OPENED;
1458
	if (sc->sc_fflags == 0)
1459
		wsp_stop_read(sc);
1460
	mtx_unlock(&sc->sc_mutex);
1461
1462
	return (0);
1463
}
1464
#endif
1465
1304
int
1466
int
1305
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1467
wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
1306
{
1468
{
Lines 1412-1416 static devclass_t wsp_devclass; Link Here
1412
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1574
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
1413
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1575
MODULE_DEPEND(wsp, usb, 1, 1, 1);
1414
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1576
MODULE_DEPEND(wsp, hid, 1, 1, 1);
1577
#ifdef EVDEV_SUPPORT
1578
MODULE_DEPEND(wsp, evdev, 1, 1, 1);
1579
#endif
1415
MODULE_VERSION(wsp, 1);
1580
MODULE_VERSION(wsp, 1);
1416
USB_PNP_HOST_INFO(wsp_devs);
1581
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