This source file includes following definitions.
- btms_match
- btms_attach
- btms_detach
- btms_enable
- btms_ioctl
- btms_disable
- btms_input
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include <sys/param.h>
40 #include <sys/conf.h>
41 #include <sys/device.h>
42 #include <sys/proc.h>
43 #include <sys/systm.h>
44
45 #include <netbt/bluetooth.h>
46
47 #include <dev/bluetooth/bthid.h>
48 #include <dev/bluetooth/bthidev.h>
49
50 #include <dev/usb/hid.h>
51 #include <dev/usb/usb.h>
52 #include <dev/usb/usbhid.h>
53
54 #include <dev/wscons/wsconsio.h>
55 #include <dev/wscons/wsmousevar.h>
56
57 #define MAX_BUTTONS 31
58 #define BUTTON(n) (1 << (((n) == 1 || (n) == 2) ? 3 - (n) : (n)))
59 #define NOTMOUSE(f) (((f) & (HIO_CONST | HIO_RELATIVE)) != HIO_RELATIVE)
60
61 struct btms_softc {
62 struct bthidev sc_hidev;
63
64 struct device *sc_wsmouse;
65 int sc_enabled;
66 uint16_t sc_flags;
67
68
69 struct hid_location sc_loc_x;
70 struct hid_location sc_loc_y;
71 struct hid_location sc_loc_z;
72 struct hid_location sc_loc_w;
73 struct hid_location sc_loc_button[MAX_BUTTONS];
74
75 int sc_num_buttons;
76 uint32_t sc_buttons;
77 };
78
79
80 #define BTMS_REVZ (1 << 0)
81 #define BTMS_HASZ (1 << 1)
82 #define BTMS_HASW (1 << 2)
83
84 int btms_match(struct device *, struct cfdata *, void *);
85 void btms_attach(struct device *, struct device *, void *);
86 int btms_detach(struct device *, int);
87
88 struct cfdriver btms_cd = {
89 NULL, "btms", DV_DULL
90 };
91
92 const struct cfattach btms_ca = {
93 sizeof(struct btms_softc),
94 btms_match,
95 btms_attach,
96 btms_detach,
97 };
98
99
100 int btms_enable(void *);
101 int btms_ioctl(void *, unsigned long, void *, int, struct lwp *);
102 void btms_disable(void *);
103
104 const struct wsmouse_accessops btms_accessops = {
105 btms_enable,
106 btms_ioctl,
107 btms_disable,
108 };
109
110
111 void btms_input(struct bthidev *, uint8_t *, int);
112
113
114 int
115 btms_match(struct device *parent, struct cfdata *match, void *aux)
116 {
117 struct bthidev_attach_args *ba = aux;
118
119 if (hid_is_collection(ba->ba_desc, ba->ba_dlen, ba->ba_id,
120 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
121 return 1;
122
123 return 0;
124 }
125
126 void
127 btms_attach(struct device *parent, struct device *self, void *aux)
128 {
129 struct btms_softc *sc = (struct btms_softc *)self;
130 struct bthidev_attach_args *ba = aux;
131 struct wsmousedev_attach_args wsma;
132 struct hid_location *zloc;
133 uint32_t flags;
134 int i, hl;
135
136 ba->ba_input = btms_input;
137
138
139 hl = hid_locate(ba->ba_desc, ba->ba_dlen,
140 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), ba->ba_id, hid_input,
141 &sc->sc_loc_x, &flags);
142
143 if (hl == 0 || NOTMOUSE(flags)) {
144 printf("\n%s: X report 0x%04x not supported\n",
145 sc->sc_hidev.sc_dev.dv_xname, flags);
146
147 return;
148 }
149
150
151 hl = hid_locate(ba->ba_desc, ba->ba_dlen,
152 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), ba->ba_id, hid_input,
153 &sc->sc_loc_y, &flags);
154
155 if (hl == 0 || NOTMOUSE(flags)) {
156 printf("\n%s: Y report 0x%04x not supported\n",
157 sc->sc_hidev.sc_dev.dv_xname, flags);
158
159 return;
160 }
161
162
163 hl = hid_locate(ba->ba_desc, ba->ba_dlen,
164 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), ba->ba_id, hid_input,
165 &sc->sc_loc_z, &flags);
166
167 zloc = &sc->sc_loc_z;
168 if (hl) {
169 if (NOTMOUSE(flags)) {
170 printf("\n%s: Wheel report 0x%04x not supported\n",
171 sc->sc_hidev.sc_dev.dv_xname, flags);
172
173
174 sc->sc_loc_z.size = 0;
175 } else {
176 sc->sc_flags |= BTMS_HASZ;
177
178 sc->sc_flags ^= BTMS_REVZ;
179
180 zloc = &sc->sc_loc_w;
181 }
182 }
183
184 hl = hid_locate(ba->ba_desc, ba->ba_dlen,
185 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), ba->ba_id, hid_input,
186 zloc, &flags);
187
188
189
190
191
192
193 if (!hl) {
194 hl = hid_locate(ba->ba_desc, ba->ba_dlen,
195 HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN), ba->ba_id, hid_input,
196 zloc, &flags);
197 }
198
199 if (hl) {
200 if (NOTMOUSE(flags))
201 zloc->size = 0;
202 else {
203 if (sc->sc_flags & BTMS_HASZ)
204 sc->sc_flags |= BTMS_HASW;
205 else
206 sc->sc_flags |= BTMS_HASZ;
207 }
208 }
209
210 for (i = 1 ; i <= MAX_BUTTONS ; i++) {
211 hl = hid_locate(ba->ba_desc, ba->ba_dlen,
212 HID_USAGE2(HUP_BUTTON, i), ba->ba_id, hid_input,
213 &sc->sc_loc_button[i - 1], NULL);
214
215 if (hl == 0)
216 break;
217 }
218 sc->sc_num_buttons = i - 1;
219
220 printf(": %d button%s%s%s%s.\n", sc->sc_num_buttons,
221 sc->sc_num_buttons == 1 ? "" : "s",
222 sc->sc_flags & BTMS_HASW ? ", W" : "",
223 sc->sc_flags & BTMS_HASZ ? " and Z dir" : "",
224 sc->sc_flags & BTMS_HASW ? "s" : "");
225
226 wsma.accessops = &btms_accessops;
227 wsma.accesscookie = sc;
228
229 sc->sc_wsmouse = config_found((struct device *)sc,
230 &wsma, wsmousedevprint);
231 }
232
233 int
234 btms_detach(struct device *self, int flags)
235 {
236 struct btms_softc *sc = (struct btms_softc *)self;
237 int err = 0;
238
239 if (sc->sc_wsmouse != NULL) {
240 err = config_detach(sc->sc_wsmouse, flags);
241 sc->sc_wsmouse = NULL;
242 }
243
244 return err;
245 }
246
247 int
248 btms_enable(void *self)
249 {
250 struct btms_softc *sc = (struct btms_softc *)self;
251
252 if (sc->sc_enabled)
253 return EBUSY;
254
255 sc->sc_enabled = 1;
256 return 0;
257 }
258
259 int
260 btms_ioctl(void *self, unsigned long cmd, void *data, int flag, struct lwp *l)
261 {
262
263
264 switch (cmd) {
265 case WSMOUSEIO_GTYPE:
266 *(uint *)data = WSMOUSE_TYPE_BLUETOOTH;
267 break;
268
269 default:
270 return EPASSTHROUGH;
271 }
272
273 return 0;
274 }
275
276 void
277 btms_disable(void *self)
278 {
279 struct btms_softc *sc = (struct btms_softc *)self;
280
281 sc->sc_enabled = 0;
282 }
283
284 void
285 btms_input(struct bthidev *self, uint8_t *data, int len)
286 {
287 struct btms_softc *sc = (struct btms_softc *)self;
288 int dx, dy, dz, dw;
289 uint32_t buttons;
290 int i, s;
291
292 if (sc->sc_wsmouse == NULL || sc->sc_enabled == 0)
293 return;
294
295 dx = hid_get_data(data, &sc->sc_loc_x);
296 dy = -hid_get_data(data, &sc->sc_loc_y);
297 dz = hid_get_data(data, &sc->sc_loc_z);
298 dw = hid_get_data(data, &sc->sc_loc_w);
299
300 if (sc->sc_flags & BTMS_REVZ)
301 dz = -dz;
302
303 buttons = 0;
304 for (i = 0 ; i < sc->sc_num_buttons ; i++)
305 if (hid_get_data(data, &sc->sc_loc_button[i]))
306 buttons |= BUTTON(i);
307
308 if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
309 buttons != sc->sc_buttons) {
310 sc->sc_buttons = buttons;
311
312 s = spltty();
313 wsmouse_input(sc->sc_wsmouse, buttons, dx, dy, dz, dw,
314 WSMOUSE_INPUT_DELTA);
315 splx(s);
316 }
317 }