xref: /openbsd-src/sys/dev/usb/uhidpp.c (revision c02cd12511bd98f410ea5913f5c4488a8730ee33)
1 /*	$OpenBSD: uhidpp.c,v 1.16 2021/07/28 09:56:54 anton Exp $	*/
2 
3 /*
4  * Copyright (c) 2021 Anton Lindqvist <anton@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/kernel.h>
22 #include <sys/device.h>
23 #include <sys/mutex.h>
24 #include <sys/sensors.h>
25 
26 #include <dev/usb/usb.h>
27 #include <dev/usb/usbhid.h>
28 #include <dev/usb/usbdi.h>
29 #include <dev/usb/usbdevs.h>
30 #include <dev/usb/uhidev.h>
31 
32 /* #define UHIDPP_DEBUG */
33 #ifdef UHIDPP_DEBUG
34 
35 #define DPRINTF(x...) do {						\
36 	if (uhidpp_debug)						\
37 		printf(x);						\
38 } while (0)
39 
40 #define DREPORT(prefix, repid, buf, len) do {				\
41 	if (uhidpp_debug)						\
42 		uhidd_dump_report((prefix), (repid), (buf), (len));	\
43 } while (0)
44 
45 void uhidd_dump_report(const char *, uint8_t, const unsigned char *, u_int);
46 
47 int uhidpp_debug = 1;
48 
49 #else
50 
51 #define DPRINTF(x...)
52 #define DREPORT(prefix, repid, buf, len)
53 
54 #endif
55 
56 #define HIDPP_LINK_STATUS(x)	((x) & (1 << 7))
57 
58 #define HIDPP_REPORT_ID_SHORT			0x10
59 #define HIDPP_REPORT_ID_LONG			0x11
60 
61 /*
62  * Length of reports. Note that the effective length is always +1 as
63  * uhidev_set_report() prepends the report ID.
64  */
65 #define HIDPP_REPORT_SHORT_LENGTH		(7 - 1)
66 #define HIDPP_REPORT_LONG_LENGTH		(20 - 1)
67 
68 /*
69  * Maximum number of allowed parameters for reports. Note, the parameters always
70  * starts at offset 3 for both RAP and FAP reports.
71  */
72 #define HIDPP_REPORT_SHORT_PARAMS_MAX		(HIDPP_REPORT_SHORT_LENGTH - 3)
73 #define HIDPP_REPORT_LONG_PARAMS_MAX		(HIDPP_REPORT_LONG_LENGTH - 3)
74 
75 #define HIDPP_DEVICE_ID_RECEIVER		0xff
76 
77 #define HIDPP_FEAT_ROOT_IDX			0x00
78 #define HIDPP_FEAT_ROOT_PING_FUNC		0x01
79 #define HIDPP_FEAT_ROOT_PING_DATA		0x5a
80 
81 #define HIDPP_SET_REGISTER			0x80
82 #define HIDPP_GET_REGISTER			0x81
83 #define HIDPP_SET_LONG_REGISTER			0x82
84 #define HIDPP_GET_LONG_REGISTER			0x83
85 
86 #define HIDPP_REG_ENABLE_REPORTS		0x00
87 #define HIDPP_REG_PAIRING_INFORMATION		0xb5
88 
89 #define HIDPP_NOTIF_DEVICE_BATTERY_STATUS	(1 << 4)
90 #define HIDPP_NOTIF_RECEIVER_WIRELESS		(1 << 0)
91 #define HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT	(1 << 3)
92 
93 /* HID++ 1.0 error codes. */
94 #define HIDPP_ERROR				0x8f
95 #define HIDPP_ERROR_SUCCESS			0x00
96 #define HIDPP_ERROR_INVALID_SUBID		0x01
97 #define HIDPP_ERROR_INVALID_ADRESS		0x02
98 #define HIDPP_ERROR_INVALID_VALUE		0x03
99 #define HIDPP_ERROR_CONNECT_FAIL		0x04
100 #define HIDPP_ERROR_TOO_MANY_DEVICES		0x05
101 #define HIDPP_ERROR_ALREADY_EXISTS		0x06
102 #define HIDPP_ERROR_BUSY			0x07
103 #define HIDPP_ERROR_UNKNOWN_DEVICE		0x08
104 #define HIDPP_ERROR_RESOURCE_ERROR		0x09
105 #define HIDPP_ERROR_REQUEST_UNAVAILABLE		0x0a
106 #define HIDPP_ERROR_INVALID_PARAM_VALUE		0x0b
107 #define HIDPP_ERROR_WRONG_PIN_CODE		0x0c
108 
109 /*
110  * The software ID is added to feature access reports (FAP) and used to
111  * distinguish responses from notifications. Note, the software ID must be
112  * greater than zero which is reserved for notifications.
113  */
114 #define HIDPP_SOFTWARE_ID			0x01
115 #define HIDPP_SOFTWARE_ID_LEN			4
116 
117 #define HIDPP20_FEAT_ROOT_ID			0x0000
118 #define HIDPP20_FEAT_ROOT_GET_FEATURE_FUNC	0x0000
119 
120 #define HIDPP20_FEAT_FEATURE_ID			0x0001
121 #define HIDPP20_FEAT_FEATURE_COUNT_FUNC		0x0000
122 #define HIDPP20_FEAT_FEATURE_ID_FUNC		0x0001
123 
124 #define HIDPP20_FEAT_BATTERY_ID			0x1000
125 #define HIDPP20_FEAT_BATTERY_LEVEL_FUNC		0x0000
126 #define HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC	0x0001
127 
128 /* HID++ 2.0 error codes. */
129 #define HIDPP20_ERROR				0xff
130 #define HIDPP20_ERROR_NO_ERROR			0x00
131 #define HIDPP20_ERROR_UNKNOWN			0x01
132 #define HIDPP20_ERROR_INVALID_ARGUMENT		0x02
133 #define HIDPP20_ERROR_OUT_OF_RANGE		0x03
134 #define HIDPP20_ERROR_HARDWARE_ERROR		0x04
135 #define HIDPP20_ERROR_LOGITECH_INTERNAL		0x05
136 #define HIDPP20_ERROR_INVALID_FEATURE_INDEX	0x06
137 #define HIDPP20_ERROR_INVALID_FUNCTION_ID	0x07
138 #define HIDPP20_ERROR_BUSY			0x08
139 #define HIDPP20_ERROR_UNSUPPORTED		0x09
140 
141 /*
142  * Sentinels used for interrupt response synchronization. The values must be
143  * disjoint from existing report IDs.
144  */
145 #define UHIDPP_RESP_NONE			0
146 #define UHIDPP_RESP_WAIT			1
147 #define UHIDPP_RESP_ERROR			2
148 
149 /* Maximum number of devices associated with a single receiver. */
150 #define UHIDPP_NDEVICES				6
151 
152 /* Maximum number of pending notifications. */
153 #define UHIDPP_NNOTIFICATIONS			4
154 
155 /* Number of sensors per paired device. */
156 #define UHIDPP_NSENSORS				2
157 
158 /* Feature access report used by the HID++ 2.0 (and greater) protocol. */
159 struct fap {
160 	uint8_t feature_idx;
161 	uint8_t funcidx_swid;
162 	uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX];
163 };
164 
165 /*
166  * Register access report used by the HID++ 1.0 protocol. Receivers always uses
167  * this type of report.
168  */
169 struct rap {
170 	uint8_t sub_id;
171 	uint8_t reg_address;
172 	uint8_t params[HIDPP_REPORT_LONG_PARAMS_MAX];
173 };
174 
175 struct uhidpp_report {
176 	uint8_t device_id;
177 	union {
178 		struct fap fap;
179 		struct rap rap;
180 	};
181 } __packed;
182 
183 struct uhidpp_notification {
184 	struct uhidpp_report n_rep;
185 	unsigned int n_id;
186 };
187 
188 struct uhidpp_device {
189 	uint8_t d_id;
190 	uint8_t d_connected;
191 	uint8_t d_major;
192 	uint8_t d_minor;
193 	uint8_t d_features;
194 #define UHIDPP_DEVICE_FEATURE_ROOT		0x01
195 #define UHIDPP_DEVICE_FEATURE_BATTERY		0x02
196 
197 	struct {
198 		struct ksensor b_sens[UHIDPP_NSENSORS];
199 		uint8_t b_feature_idx;
200 		uint8_t b_level;
201 		uint8_t b_next_level;
202 		uint8_t b_status;
203 		uint8_t b_nlevels;
204 	} d_battery;
205 };
206 
207 /*
208  * Locking:
209  *	[m]	sc_mtx
210  */
211 struct uhidpp_softc {
212 	struct uhidev sc_hdev;
213 	struct usbd_device *sc_udev;
214 
215 	struct mutex sc_mtx;
216 
217 	struct uhidpp_device sc_devices[UHIDPP_NDEVICES];
218 					/* [m] connected devices */
219 
220 	struct uhidpp_notification sc_notifications[UHIDPP_NNOTIFICATIONS];
221 					/* [m] pending notifications */
222 
223 	struct usb_task sc_task;	/* [m] notification task */
224 
225 	struct ksensordev sc_sensdev;	/* [m] */
226 	struct sensor_task *sc_senstsk;	/* [m] */
227 
228 	struct uhidpp_report *sc_req;	/* [m] synchronous request buffer */
229 	struct uhidpp_report *sc_resp;	/* [m] synchronous response buffer */
230 	u_int sc_resp_state;		/* [m] synchronous response state */
231 
232 };
233 
234 int uhidpp_match(struct device *, void *, void *);
235 void uhidpp_attach(struct device *, struct device *, void *);
236 int uhidpp_detach(struct device *, int flags);
237 void uhidpp_intr(struct uhidev *addr, void *ibuf, u_int len);
238 void uhidpp_refresh(void *);
239 void uhidpp_task(void *);
240 int uhidpp_sleep(struct uhidpp_softc *, uint64_t);
241 
242 void uhidpp_device_connect(struct uhidpp_softc *, struct uhidpp_device *);
243 void uhidpp_device_refresh(struct uhidpp_softc *, struct uhidpp_device *);
244 int uhidpp_device_features(struct uhidpp_softc *, struct uhidpp_device *);
245 
246 struct uhidpp_notification *uhidpp_claim_notification(struct uhidpp_softc *);
247 int uhidpp_consume_notification(struct uhidpp_softc *, struct uhidpp_report *);
248 int uhidpp_is_notification(struct uhidpp_softc *, struct uhidpp_report *);
249 
250 static int uhidpp_has_sensors(struct uhidpp_softc *);
251 
252 int hidpp_get_protocol_version(struct uhidpp_softc  *, uint8_t, uint8_t *,
253     uint8_t *);
254 
255 int hidpp10_get_name(struct uhidpp_softc *, uint8_t, char *, size_t);
256 int hidpp10_get_serial(struct uhidpp_softc *, uint8_t, uint8_t *, size_t);
257 int hidpp10_get_type(struct uhidpp_softc *, uint8_t, const char **);
258 int hidpp10_enable_notifications(struct uhidpp_softc *, uint8_t);
259 
260 int hidpp20_root_get_feature(struct uhidpp_softc *, uint8_t, uint16_t,
261     uint8_t *, uint8_t *);
262 int hidpp20_feature_get_count(struct uhidpp_softc *, uint8_t, uint8_t,
263     uint8_t *);
264 int hidpp20_feature_get_id(struct uhidpp_softc *, uint8_t, uint8_t, uint8_t,
265     uint16_t *, uint8_t *);
266 int hidpp20_battery_get_level_status(struct uhidpp_softc *, uint8_t, uint8_t,
267     uint8_t *, uint8_t *, uint8_t *);
268 int hidpp20_battery_get_capability(struct uhidpp_softc *, uint8_t, uint8_t,
269     uint8_t *);
270 
271 int hidpp_send_validate(uint8_t, int);
272 int hidpp_send_rap_report(struct uhidpp_softc *, uint8_t, uint8_t,
273     uint8_t, uint8_t, uint8_t *, int, struct uhidpp_report *);
274 int hidpp_send_fap_report(struct uhidpp_softc *, uint8_t, uint8_t, uint8_t,
275     uint8_t, uint8_t *, int, struct uhidpp_report *);
276 int hidpp_send_report(struct uhidpp_softc *, uint8_t, struct uhidpp_report *,
277     struct uhidpp_report *);
278 
279 struct cfdriver uhidpp_cd = {
280 	NULL, "uhidpp", DV_DULL
281 };
282 
283 const struct cfattach uhidpp_ca = {
284 	sizeof(struct uhidpp_softc),
285 	uhidpp_match,
286 	uhidpp_attach,
287 	uhidpp_detach,
288 };
289 
290 static const struct usb_devno uhidpp_devs[] = {
291 	{ USB_VENDOR_LOGITECH,	USB_PRODUCT_ANY },
292 };
293 
294 int
295 uhidpp_match(struct device *parent, void *match, void *aux)
296 {
297 	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
298 	void *desc;
299 	int descsiz, siz;
300 
301 	if (uha->reportid != HIDPP_REPORT_ID_SHORT &&
302 	    uha->reportid != HIDPP_REPORT_ID_LONG)
303 		return UMATCH_NONE;
304 
305 	if (usb_lookup(uhidpp_devs,
306 		    uha->uaa->vendor, uha->uaa->product) == NULL)
307 		return UMATCH_NONE;
308 
309 	uhidev_get_report_desc(uha->parent, &desc, &descsiz);
310 	siz = hid_report_size(desc, descsiz, hid_output, HIDPP_REPORT_ID_SHORT);
311 	if (siz != HIDPP_REPORT_SHORT_LENGTH)
312 		return UMATCH_NONE;
313 	siz = hid_report_size(desc, descsiz, hid_output, HIDPP_REPORT_ID_LONG);
314 	if (siz != HIDPP_REPORT_LONG_LENGTH)
315 		return UMATCH_NONE;
316 
317 	return UMATCH_VENDOR_PRODUCT;
318 }
319 
320 void
321 uhidpp_attach(struct device *parent, struct device *self, void *aux)
322 {
323 	struct uhidpp_softc *sc = (struct uhidpp_softc *)self;
324 	struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
325 	struct usb_attach_arg *uaa = uha->uaa;
326 	int error, i;
327 	int npaired = 0;
328 
329 	sc->sc_hdev.sc_intr = uhidpp_intr;
330 	sc->sc_hdev.sc_udev = uaa->device;
331 	sc->sc_hdev.sc_parent = uha->parent;
332 	sc->sc_hdev.sc_report_id = uha->reportid;
333 	/* The largest supported report dictates the sizes. */
334 	sc->sc_hdev.sc_isize = HIDPP_REPORT_LONG_LENGTH;
335 	sc->sc_hdev.sc_osize = HIDPP_REPORT_LONG_LENGTH;
336 
337 	sc->sc_udev = uaa->device;
338 
339 	mtx_init(&sc->sc_mtx, IPL_USB);
340 
341 	sc->sc_resp = NULL;
342 	sc->sc_resp_state = UHIDPP_RESP_NONE;
343 
344 	error = uhidev_open(&sc->sc_hdev);
345 	if (error) {
346 		printf(" open error %d\n", error);
347 		return;
348 	}
349 
350 	usb_init_task(&sc->sc_task, uhidpp_task, sc, USB_TASK_TYPE_GENERIC);
351 
352 	mtx_enter(&sc->sc_mtx);
353 
354 	/*
355 	 * Wire up report device handlers before issuing commands to the device
356 	 * in order to receive responses. Necessary as uhidev by default
357 	 * performs the wiring after the attach routine has returned.
358 	 */
359 	error = uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
360 	    HIDPP_REPORT_ID_SHORT);
361 	if (error) {
362 		printf(" short report error %d\n", error);
363 		return;
364 	}
365 	error = uhidev_set_report_dev(sc->sc_hdev.sc_parent, &sc->sc_hdev,
366 	    HIDPP_REPORT_ID_LONG);
367 	if (error) {
368 		printf(" long report error %d\n", error);
369 		return;
370 	}
371 
372 	/* Probe paired devices. */
373 	for (i = 0; i < UHIDPP_NDEVICES; i++) {
374 		char name[16];
375 		uint8_t serial[4];
376 		struct uhidpp_device *dev = &sc->sc_devices[i];
377 		const char *type;
378 		uint8_t device_id = i + 1;
379 
380 		dev->d_id = device_id;
381 
382 		if (hidpp10_get_serial(sc, device_id, serial, sizeof(serial)) ||
383 		    hidpp10_get_type(sc, device_id, &type) ||
384 		    hidpp10_get_name(sc, device_id, name, sizeof(name)))
385 			continue;
386 
387 		if (npaired > 0)
388 			printf(",");
389 		printf(" device %d", device_id);
390 		printf(" %s", type);
391 		printf(" \"%s\"", name);
392 		printf(" serial %02x-%02x-%02x-%02x",
393 		    serial[0], serial[1], serial[2], serial[3]);
394 		npaired++;
395 	}
396 	if (npaired == 0)
397 		goto out;
398 
399 	/* Enable notifications for the receiver. */
400 	error = hidpp10_enable_notifications(sc, HIDPP_DEVICE_ID_RECEIVER);
401 	if (error)
402 		printf(" error %d", error);
403 
404 out:
405 	mtx_leave(&sc->sc_mtx);
406 	printf("\n");
407 }
408 
409 int
410 uhidpp_detach(struct device *self, int flags)
411 {
412 	struct uhidpp_softc *sc = (struct uhidpp_softc *)self;
413 	int i, j;
414 
415 	usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
416 
417 	if (sc->sc_senstsk != NULL)
418 		sensor_task_unregister(sc->sc_senstsk);
419 
420 	KASSERT(sc->sc_resp_state == UHIDPP_RESP_NONE);
421 
422 	if (uhidpp_has_sensors(sc))
423 		sensordev_deinstall(&sc->sc_sensdev);
424 
425 	for (i = 0; i < UHIDPP_NDEVICES; i++) {
426 		struct uhidpp_device *dev = &sc->sc_devices[i];
427 
428 		if (!dev->d_connected)
429 			continue;
430 
431 		for (j = 0; j < UHIDPP_NSENSORS; j++)
432 			sensor_detach(&sc->sc_sensdev, &dev->d_battery.b_sens[j]);
433 	}
434 
435 	uhidev_close(&sc->sc_hdev);
436 
437 	return 0;
438 }
439 
440 void
441 uhidpp_intr(struct uhidev *addr, void *buf, u_int len)
442 {
443 	struct uhidpp_softc *sc = (struct uhidpp_softc *)addr;
444 	struct uhidpp_report *rep = buf;
445 	int dowake = 0;
446 	uint8_t repid;
447 
448 	/*
449 	 * Ugliness ahead as the report ID is stripped of by uhidev_intr() but
450 	 * needed to determine if an error occurred.
451 	 * Note that an error response is always a short report even if the
452 	 * command that caused the error is a long report.
453 	 */
454 	repid = ((uint8_t *)buf)[-1];
455 
456 	DREPORT(__func__, repid, buf, len);
457 
458 	mtx_enter(&sc->sc_mtx);
459 	if (uhidpp_is_notification(sc, rep)) {
460 		struct uhidpp_notification *ntf;
461 
462 		ntf = uhidpp_claim_notification(sc);
463 		if (ntf != NULL) {
464 			memcpy(&ntf->n_rep, buf, len);
465 			usb_add_task(sc->sc_udev, &sc->sc_task);
466 		} else {
467 			DPRINTF("%s: too many notifications", __func__);
468 		}
469 	} else {
470 		KASSERT(sc->sc_resp_state == UHIDPP_RESP_WAIT);
471 		dowake = 1;
472 		sc->sc_resp_state = repid;
473 		memcpy(sc->sc_resp, buf, len);
474 	}
475 	mtx_leave(&sc->sc_mtx);
476 	if (dowake)
477 		wakeup(sc);
478 }
479 
480 void
481 uhidpp_refresh(void *arg)
482 {
483 	struct uhidpp_softc *sc = arg;
484 	int i;
485 
486 	mtx_enter(&sc->sc_mtx);
487 	for (i = 0; i < UHIDPP_NDEVICES; i++) {
488 		struct uhidpp_device *dev = &sc->sc_devices[i];
489 
490 		if (dev->d_connected)
491 			uhidpp_device_refresh(sc, dev);
492 	}
493 	mtx_leave(&sc->sc_mtx);
494 }
495 
496 void
497 uhidpp_task(void *arg)
498 {
499 	struct uhidpp_softc *sc = arg;
500 
501 	mtx_enter(&sc->sc_mtx);
502 	for (;;) {
503 		struct uhidpp_report rep;
504 		struct uhidpp_device *dev;
505 
506 		if (uhidpp_consume_notification(sc, &rep))
507 			break;
508 
509 		DPRINTF("%s: device_id=%d, sub_id=%02x\n",
510 		    __func__, rep.device_id, rep.rap.sub_id);
511 
512 		if (rep.device_id == 0 || rep.device_id > UHIDPP_NDEVICES) {
513 			DPRINTF("%s: invalid device\n", __func__);
514 			continue;
515 		}
516 		dev = &sc->sc_devices[rep.device_id - 1];
517 
518 		switch (rep.rap.sub_id) {
519 		case 0x0e:	/* leds */
520 		case 0x40:	/* disconnect */
521 		case 0x4b:	/* pairing accepted */
522 			break;
523 		case 0x41:	/* connect */
524 			/*
525 			 * Do nothing if the link is reported to be out of
526 			 * range. This happens when a device has been idle for a
527 			 * while.
528 			 */
529 			if (HIDPP_LINK_STATUS(rep.rap.params[0]))
530 				uhidpp_device_connect(sc, dev);
531 			break;
532 		}
533 	}
534 	mtx_leave(&sc->sc_mtx);
535 }
536 
537 int
538 uhidpp_sleep(struct uhidpp_softc *sc, uint64_t nsecs)
539 {
540 	return msleep_nsec(sc, &sc->sc_mtx, PZERO, "uhidpp", nsecs);
541 }
542 
543 void
544 uhidpp_device_connect(struct uhidpp_softc *sc, struct uhidpp_device *dev)
545 {
546 	struct ksensor *sens;
547 	int error;
548 	uint8_t feature_type;
549 
550 	MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
551 
552 	/* A connected device will continously send connect events. */
553 	if (dev->d_connected)
554 		return;
555 
556 	/*
557 	 * If features are already present, it must be a device lacking battery
558 	 * support.
559 	 */
560 	if (dev->d_features)
561 		return;
562 
563 	error = hidpp_get_protocol_version(sc, dev->d_id,
564 	    &dev->d_major, &dev->d_minor);
565 	if (error) {
566 		DPRINTF("%s: protocol version failure: device_id=%d, "
567 		    "error=%d\n",
568 		    __func__, dev->d_id, error);
569 		return;
570 	}
571 
572 	DPRINTF("%s: device_id=%d, version=%d.%d\n",
573 	    __func__, dev->d_id, dev->d_major, dev->d_minor);
574 
575 	if (dev->d_major >= 2) {
576 		error = uhidpp_device_features(sc, dev);
577 		if (error) {
578 			DPRINTF("%s: features failure: device_id=%d, "
579 			    "error=%d\n",
580 			    __func__, dev->d_id, error);
581 			return;
582 		}
583 
584 		error = hidpp20_root_get_feature(sc, dev->d_id,
585 		    HIDPP20_FEAT_BATTERY_ID,
586 		    &dev->d_battery.b_feature_idx, &feature_type);
587 		if (error) {
588 			DPRINTF("%s: battery feature index failure: "
589 			    "device_id=%d, error=%d\n",
590 			    __func__, dev->d_id, error);
591 			return;
592 		}
593 
594 		error = hidpp20_battery_get_capability(sc, dev->d_id,
595 		    dev->d_battery.b_feature_idx, &dev->d_battery.b_nlevels);
596 		if (error) {
597 			DPRINTF("%s: battery capability failure: device_id=%d, "
598 			    "error=%d\n", __func__, dev->d_id, error);
599 			return;
600 		}
601 
602 	} else {
603 		return;
604 	}
605 
606 	dev->d_connected = 1;
607 
608 	/*
609 	 * Delay installation of sensors until a device with battery support is
610 	 * connected. Allows sensorsd(8) to pick up hotplugged devices.
611 	 */
612 	if (!uhidpp_has_sensors(sc)) {
613 		strlcpy(sc->sc_sensdev.xname, sc->sc_hdev.sc_dev.dv_xname,
614 		    sizeof(sc->sc_sensdev.xname));
615 		sensordev_install(&sc->sc_sensdev);
616 	}
617 
618 	sens = &dev->d_battery.b_sens[0];
619 	strlcpy(sens->desc, "battery level", sizeof(sens->desc));
620 	sens->type = SENSOR_PERCENT;
621 	sens->flags = SENSOR_FUNKNOWN;
622 	sensor_attach(&sc->sc_sensdev, sens);
623 
624 	sens = &dev->d_battery.b_sens[1];
625 	strlcpy(sens->desc, "number of battery levels", sizeof(sens->desc));
626 	sens->type = SENSOR_INTEGER;
627 	sens->value = dev->d_battery.b_nlevels;
628 	sensor_attach(&sc->sc_sensdev, sens);
629 
630 	if (sc->sc_senstsk == NULL) {
631 		/*
632 		 * The mutex must be temporarily released while calling
633 		 * sensor_task_register() as it might end up sleeping.
634 		 */
635 		mtx_leave(&sc->sc_mtx);
636 		sc->sc_senstsk = sensor_task_register(sc, uhidpp_refresh, 30);
637 		mtx_enter(&sc->sc_mtx);
638 	}
639 
640 	uhidpp_device_refresh(sc, dev);
641 }
642 
643 void
644 uhidpp_device_refresh(struct uhidpp_softc *sc, struct uhidpp_device *dev)
645 {
646 	int error;
647 
648 	MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
649 
650 	if (dev->d_major >= 2) {
651 		error = hidpp20_battery_get_level_status(sc, dev->d_id,
652 		    dev->d_battery.b_feature_idx,
653 		    &dev->d_battery.b_level, &dev->d_battery.b_next_level,
654 		    &dev->d_battery.b_status);
655 		if (error) {
656 			DPRINTF("%s: battery status failure: device_id=%d, "
657 			    "error=%d\n",
658 			    __func__, dev->d_id, error);
659 			return;
660 		}
661 
662 		dev->d_battery.b_sens[0].value = dev->d_battery.b_level * 1000;
663 		dev->d_battery.b_sens[0].flags &= ~SENSOR_FUNKNOWN;
664 		if (dev->d_battery.b_nlevels < 10) {
665 			/*
666 			 * According to the HID++ 2.0 specification, less than
667 			 * 10 levels should be mapped to the following 4 levels:
668 			 *
669 			 * [0, 10]   critical
670 			 * [11, 30]  low
671 			 * [31, 80]  good
672 			 * [81, 100] full
673 			 *
674 			 * Since sensors are limited to 3 valid statuses, clamp
675 			 * it even further.
676 			 */
677 			if (dev->d_battery.b_level <= 10)
678 				dev->d_battery.b_sens[0].status = SENSOR_S_CRIT;
679 			else if (dev->d_battery.b_level <= 30)
680 				dev->d_battery.b_sens[0].status = SENSOR_S_WARN;
681 			else
682 				dev->d_battery.b_sens[0].status = SENSOR_S_OK;
683 		} else {
684 			/*
685 			 * XXX the device supports battery mileage. The current
686 			 * level must be checked against resp.fap.params[3]
687 			 * given by hidpp20_battery_get_capability().
688 			 */
689 			dev->d_battery.b_sens[0].status = SENSOR_S_UNKNOWN;
690 		}
691 	}
692 }
693 
694 /*
695  * Enumerate all supported HID++ 2.0 features for the given device.
696  */
697 int
698 uhidpp_device_features(struct uhidpp_softc *sc, struct uhidpp_device *dev)
699 {
700 	int error;
701 	uint8_t count, feature_idx, feature_type, i;
702 
703 	/* All devices support the root feature. */
704 	dev->d_features |= UHIDPP_DEVICE_FEATURE_ROOT;
705 
706 	error = hidpp20_root_get_feature(sc, dev->d_id,
707 	    HIDPP20_FEAT_FEATURE_ID,
708 	    &feature_idx, &feature_type);
709 	if (error) {
710 		DPRINTF("%s: feature index failure: device_id=%d, error=%d\n",
711 		    __func__, dev->d_id, error);
712 		return error;
713 	}
714 
715 	error = hidpp20_feature_get_count(sc, dev->d_id, feature_idx, &count);
716 	if (error) {
717 		DPRINTF("%s: feature count failure: device_id=%d, error=%d\n",
718 		    __func__, dev->d_id, error);
719 		return error;
720 	}
721 
722 	for (i = 1; i <= count; i++) {
723 		uint16_t id;
724 		uint8_t type;
725 
726 		error = hidpp20_feature_get_id(sc, dev->d_id, feature_idx, i,
727 		    &id, &type);
728 		if (error)
729 			continue;
730 
731 		if (id == HIDPP20_FEAT_BATTERY_ID)
732 			dev->d_features |= UHIDPP_DEVICE_FEATURE_BATTERY;
733 
734 		DPRINTF("%s: idx=%d, id=%x, type=%x device_id=%d\n",
735 		    __func__, i, id, type, dev->d_id);
736 	}
737 	DPRINTF("%s: device_id=%d, count=%d, features=%x\n",
738 	    __func__, dev->d_id, count, dev->d_features);
739 
740 	if ((dev->d_features & UHIDPP_DEVICE_FEATURE_BATTERY) == 0)
741 		return -ENODEV;
742 	return 0;
743 }
744 
745 /*
746  * Returns the next available notification slot, if available.
747  */
748 struct uhidpp_notification *
749 uhidpp_claim_notification(struct uhidpp_softc *sc)
750 {
751 	struct uhidpp_notification *ntf = NULL;
752 	int nclaimed = 0;
753 	int i;
754 
755 	MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
756 
757 	for (i = 0; i < UHIDPP_NNOTIFICATIONS; i++) {
758 		struct uhidpp_notification *tmp = &sc->sc_notifications[i];
759 
760 		if (tmp->n_id > 0)
761 			nclaimed++;
762 		else if (ntf == NULL)
763 			ntf = tmp;
764 	}
765 
766 	if (ntf == NULL)
767 		return NULL;
768 	ntf->n_id = nclaimed + 1;
769 	return ntf;
770 }
771 
772 /*
773  * Consume the first unhandled notification, if present.
774  */
775 int
776 uhidpp_consume_notification(struct uhidpp_softc *sc, struct uhidpp_report *rep)
777 {
778 	struct uhidpp_notification *ntf = NULL;
779 	int i;
780 
781 	MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
782 
783 	for (i = 0; i < UHIDPP_NNOTIFICATIONS; i++) {
784 		struct uhidpp_notification *tmp = &sc->sc_notifications[i];
785 
786 		if (tmp->n_id > 0 && (ntf == NULL || tmp->n_id < ntf->n_id))
787 			ntf = tmp;
788 	}
789 	if (ntf == NULL)
790 		return 1;
791 
792 	memcpy(rep, &ntf->n_rep, sizeof(*rep));
793 	ntf->n_id = 0;
794 	return 0;
795 }
796 
797 
798 /*
799  * Returns non-zero if the given report is a notification. Otherwise, it must be
800  * a response.
801  */
802 int
803 uhidpp_is_notification(struct uhidpp_softc *sc, struct uhidpp_report *rep)
804 {
805 	/* Not waiting for a response. */
806 	if (sc->sc_req == NULL)
807 		return 1;
808 
809 	/* Everything except the parameters must be repeated in a response. */
810 	if (sc->sc_req->device_id == rep->device_id &&
811 	    sc->sc_req->rap.sub_id == rep->rap.sub_id &&
812 	    sc->sc_req->rap.reg_address == rep->rap.reg_address)
813 		return 0;
814 
815 	/* An error must always be a response. */
816 	if ((rep->rap.sub_id == HIDPP_ERROR ||
817 		    rep->fap.feature_idx == HIDPP20_ERROR) &&
818 	    rep->fap.funcidx_swid == sc->sc_req->fap.feature_idx &&
819 	    rep->fap.params[0] == sc->sc_req->fap.funcidx_swid)
820 		return 0;
821 
822 	return 1;
823 }
824 
825 static int
826 uhidpp_has_sensors(struct uhidpp_softc *sc)
827 {
828 	return sc->sc_sensdev.xname[0] != '\0';
829 }
830 
831 int
832 hidpp_get_protocol_version(struct uhidpp_softc  *sc, uint8_t device_id,
833     uint8_t *major, uint8_t *minor)
834 {
835 	struct uhidpp_report resp;
836 	uint8_t params[3] = { 0, 0, HIDPP_FEAT_ROOT_PING_DATA };
837 	int error;
838 
839 	error = hidpp_send_fap_report(sc,
840 	    HIDPP_REPORT_ID_SHORT,
841 	    device_id,
842 	    HIDPP_FEAT_ROOT_IDX,
843 	    HIDPP_FEAT_ROOT_PING_FUNC,
844 	    params, sizeof(params), &resp);
845 	if (error == HIDPP_ERROR_INVALID_SUBID) {
846 		*major = 1;
847 		*minor = 0;
848 		return 0;
849 	}
850 	if (error)
851 		return error;
852 	if (resp.rap.params[2] != HIDPP_FEAT_ROOT_PING_DATA)
853 		return -EPROTO;
854 
855 	*major = resp.fap.params[0];
856 	*minor = resp.fap.params[1];
857 	return 0;
858 }
859 
860 int
861 hidpp10_get_name(struct uhidpp_softc *sc, uint8_t device_id,
862     char *buf, size_t bufsiz)
863 {
864 	struct uhidpp_report resp;
865 	int error;
866 	uint8_t params[1] = { 0x40 + (device_id - 1) };
867 	uint8_t len;
868 
869 	error = hidpp_send_rap_report(sc,
870 	    HIDPP_REPORT_ID_SHORT,
871 	    HIDPP_DEVICE_ID_RECEIVER,
872 	    HIDPP_GET_LONG_REGISTER,
873 	    HIDPP_REG_PAIRING_INFORMATION,
874 	    params, sizeof(params), &resp);
875 	if (error)
876 		return error;
877 
878 	len = resp.rap.params[1];
879 	if (len + 2 > sizeof(resp.rap.params))
880 		return -ENAMETOOLONG;
881 	if (len > bufsiz - 1)
882 		len = bufsiz - 1;
883 	memcpy(buf, &resp.rap.params[2], len);
884 	buf[len] = '\0';
885 	return 0;
886 }
887 
888 int
889 hidpp10_get_serial(struct uhidpp_softc *sc, uint8_t device_id,
890     uint8_t *buf, size_t bufsiz)
891 {
892 	struct uhidpp_report resp;
893 	int error;
894 	uint8_t params[1] = { 0x30 + (device_id - 1) };
895 	uint8_t len;
896 
897 	error = hidpp_send_rap_report(sc,
898 	    HIDPP_REPORT_ID_SHORT,
899 	    HIDPP_DEVICE_ID_RECEIVER,
900 	    HIDPP_GET_LONG_REGISTER,
901 	    HIDPP_REG_PAIRING_INFORMATION,
902 	    params, sizeof(params), &resp);
903 	if (error)
904 		return error;
905 
906 	len = 4;
907 	if (bufsiz < len)
908 		len = bufsiz;
909 	memcpy(buf, &resp.rap.params[1], len);
910 	return 0;
911 }
912 
913 int
914 hidpp10_get_type(struct uhidpp_softc *sc, uint8_t device_id, const char **type)
915 {
916 	struct uhidpp_report resp;
917 	int error;
918 	uint8_t params[1] = { 0x20 + (device_id - 1) };
919 
920 	error = hidpp_send_rap_report(sc,
921 	    HIDPP_REPORT_ID_SHORT,
922 	    HIDPP_DEVICE_ID_RECEIVER,
923 	    HIDPP_GET_LONG_REGISTER,
924 	    HIDPP_REG_PAIRING_INFORMATION,
925 	    params, sizeof(params), &resp);
926 	if (error)
927 		return error;
928 
929 	switch (resp.rap.params[7]) {
930 	case 0x00:
931 		*type = "unknown";
932 		return 0;
933 	case 0x01:
934 		*type = "keyboard";
935 		return 0;
936 	case 0x02:
937 		*type = "mouse";
938 		return 0;
939 	case 0x03:
940 		*type = "numpad";
941 		return 0;
942 	case 0x04:
943 		*type = "presenter";
944 		return 0;
945 	case 0x08:
946 		*type = "trackball";
947 		return 0;
948 	case 0x09:
949 		*type = "touchpad";
950 		return 0;
951 	}
952 	return -ENOENT;
953 }
954 
955 int
956 hidpp10_enable_notifications(struct uhidpp_softc *sc, uint8_t device_id)
957 {
958 	struct uhidpp_report resp;
959 	uint8_t params[3];
960 
961 	/* Device reporting flags. */
962 	params[0] = HIDPP_NOTIF_DEVICE_BATTERY_STATUS;
963 	/* Receiver reporting flags. */
964 	params[1] = HIDPP_NOTIF_RECEIVER_WIRELESS |
965 	    HIDPP_NOTIF_RECEIVER_SOFTWARE_PRESENT;
966 	/* Device reporting flags (continued). */
967 	params[2] = 0;
968 
969 	return hidpp_send_rap_report(sc,
970 	    HIDPP_REPORT_ID_SHORT,
971 	    device_id,
972 	    HIDPP_SET_REGISTER,
973 	    HIDPP_REG_ENABLE_REPORTS,
974 	    params, sizeof(params), &resp);
975 }
976 
977 int
978 hidpp20_root_get_feature(struct uhidpp_softc *sc, uint8_t device_id,
979     uint16_t feature, uint8_t *feature_idx, uint8_t *feature_type)
980 {
981 	struct uhidpp_report resp;
982 	uint8_t params[2] = { feature >> 8, feature & 0xff };
983 	int error;
984 
985 	error = hidpp_send_fap_report(sc,
986 	    HIDPP_REPORT_ID_LONG,
987 	    device_id,
988 	    HIDPP20_FEAT_ROOT_ID,
989 	    HIDPP20_FEAT_ROOT_GET_FEATURE_FUNC,
990 	    params, sizeof(params), &resp);
991 	if (error)
992 		return error;
993 
994 	if (resp.fap.params[0] == 0)
995 		return -ENOENT;
996 
997 	*feature_idx = resp.fap.params[0];
998 	*feature_type = resp.fap.params[1];
999 	return 0;
1000 }
1001 
1002 int
1003 hidpp20_feature_get_count(struct uhidpp_softc *sc, uint8_t device_id,
1004     uint8_t feature_idx, uint8_t *count)
1005 {
1006 	struct uhidpp_report resp;
1007 	int error;
1008 
1009 	error = hidpp_send_fap_report(sc,
1010 	    HIDPP_REPORT_ID_LONG,
1011 	    device_id,
1012 	    feature_idx,
1013 	    HIDPP20_FEAT_FEATURE_COUNT_FUNC,
1014 	    NULL, 0, &resp);
1015 	if (error)
1016 		return error;
1017 
1018 	*count = resp.fap.params[0];
1019 	return 0;
1020 }
1021 
1022 int
1023 hidpp20_feature_get_id(struct uhidpp_softc *sc, uint8_t device_id,
1024     uint8_t feature_idx, uint8_t idx, uint16_t *id, uint8_t *type)
1025 {
1026 	struct uhidpp_report resp;
1027 	uint8_t params[1] = { idx };
1028 	int error;
1029 
1030 	error = hidpp_send_fap_report(sc,
1031 	    HIDPP_REPORT_ID_LONG,
1032 	    device_id,
1033 	    feature_idx,
1034 	    HIDPP20_FEAT_FEATURE_ID_FUNC,
1035 	    params, sizeof(params), &resp);
1036 	if (error)
1037 		return error;
1038 
1039 	*id = bemtoh16(resp.fap.params);
1040 	*type = resp.fap.params[2];
1041 	return 0;
1042 }
1043 
1044 int
1045 hidpp20_battery_get_level_status(struct uhidpp_softc *sc, uint8_t device_id,
1046     uint8_t feature_idx, uint8_t *level, uint8_t *next_level, uint8_t *status)
1047 {
1048 	struct uhidpp_report resp;
1049 	int error;
1050 
1051 	error = hidpp_send_fap_report(sc,
1052 	    HIDPP_REPORT_ID_LONG,
1053 	    device_id,
1054 	    feature_idx,
1055 	    HIDPP20_FEAT_BATTERY_LEVEL_FUNC,
1056 	    NULL, 0, &resp);
1057 	if (error)
1058 		return error;
1059 
1060 	*level = resp.fap.params[0];
1061 	*next_level = resp.fap.params[1];
1062 	*status = resp.fap.params[2];
1063 	return 0;
1064 }
1065 
1066 int
1067 hidpp20_battery_get_capability(struct uhidpp_softc *sc, uint8_t device_id,
1068     uint8_t feature_idx, uint8_t *nlevels)
1069 {
1070 	struct uhidpp_report resp;
1071 	int error;
1072 
1073 	error = hidpp_send_fap_report(sc,
1074 	    HIDPP_REPORT_ID_LONG,
1075 	    device_id,
1076 	    feature_idx,
1077 	    HIDPP20_FEAT_BATTERY_CAPABILITY_FUNC,
1078 	    NULL, 0, &resp);
1079 	if (error)
1080 		return error;
1081 	*nlevels = resp.fap.params[0];
1082 	return 0;
1083 }
1084 
1085 int
1086 hidpp_send_validate(uint8_t report_id, int nparams)
1087 {
1088 	if (report_id == HIDPP_REPORT_ID_SHORT) {
1089 		if (nparams > HIDPP_REPORT_SHORT_PARAMS_MAX)
1090 			return -EMSGSIZE;
1091 	} else if (report_id == HIDPP_REPORT_ID_LONG) {
1092 		if (nparams > HIDPP_REPORT_LONG_PARAMS_MAX)
1093 			return -EMSGSIZE;
1094 	} else {
1095 		return -EINVAL;
1096 	}
1097 	return 0;
1098 }
1099 
1100 int
1101 hidpp_send_fap_report(struct uhidpp_softc *sc, uint8_t report_id,
1102     uint8_t device_id, uint8_t feature_idx, uint8_t funcidx_swid,
1103     uint8_t *params, int nparams, struct uhidpp_report *resp)
1104 {
1105 	struct uhidpp_report req;
1106 	int error;
1107 
1108 	error = hidpp_send_validate(report_id, nparams);
1109 	if (error)
1110 		return error;
1111 
1112 	memset(&req, 0, sizeof(req));
1113 	req.device_id = device_id;
1114 	req.fap.feature_idx = feature_idx;
1115 	req.fap.funcidx_swid =
1116 	    (funcidx_swid << HIDPP_SOFTWARE_ID_LEN) | HIDPP_SOFTWARE_ID;
1117 	memcpy(req.fap.params, params, nparams);
1118 	return hidpp_send_report(sc, report_id, &req, resp);
1119 }
1120 
1121 int
1122 hidpp_send_rap_report(struct uhidpp_softc *sc, uint8_t report_id,
1123     uint8_t device_id, uint8_t sub_id, uint8_t reg_address,
1124     uint8_t *params, int nparams, struct uhidpp_report *resp)
1125 {
1126 	struct uhidpp_report req;
1127 	int error;
1128 
1129 	error = hidpp_send_validate(report_id, nparams);
1130 	if (error)
1131 		return error;
1132 
1133 	memset(&req, 0, sizeof(req));
1134 	req.device_id = device_id;
1135 	req.rap.sub_id = sub_id;
1136 	req.rap.reg_address = reg_address;
1137 	memcpy(req.rap.params, params, nparams);
1138 	return hidpp_send_report(sc, report_id, &req, resp);
1139 }
1140 
1141 int
1142 hidpp_send_report(struct uhidpp_softc *sc, uint8_t report_id,
1143     struct uhidpp_report *req, struct uhidpp_report *resp)
1144 {
1145 	int error, len, n;
1146 
1147 	MUTEX_ASSERT_LOCKED(&sc->sc_mtx);
1148 
1149 	if (report_id == HIDPP_REPORT_ID_SHORT)
1150 		len = HIDPP_REPORT_SHORT_LENGTH;
1151 	else if (report_id == HIDPP_REPORT_ID_LONG)
1152 		len = HIDPP_REPORT_LONG_LENGTH;
1153 	else
1154 		return -EINVAL;
1155 
1156 	DREPORT(__func__, report_id, (const unsigned char *)req, len);
1157 
1158 	/* Wait until any ongoing command has completed. */
1159 	while (sc->sc_resp_state != UHIDPP_RESP_NONE)
1160 		uhidpp_sleep(sc, INFSLP);
1161 	sc->sc_req = req;
1162 	sc->sc_resp = resp;
1163 	sc->sc_resp_state = UHIDPP_RESP_WAIT;
1164 	/*
1165 	 * The mutex must be temporarily released while calling
1166 	 * uhidev_set_report() as it might end up sleeping.
1167 	 */
1168 	mtx_leave(&sc->sc_mtx);
1169 
1170 	n = uhidev_set_report(sc->sc_hdev.sc_parent, UHID_OUTPUT_REPORT,
1171 	    report_id, req, len);
1172 
1173 	mtx_enter(&sc->sc_mtx);
1174 	if (len != n) {
1175 		error = -EBUSY;
1176 		goto out;
1177 	}
1178 	/*
1179 	 * The interrupt could already have been received while the mutex was
1180 	 * released. Otherwise, wait for it.
1181 	 */
1182 	if (sc->sc_resp_state == UHIDPP_RESP_WAIT) {
1183 		/* Timeout taken from the hid-logitech-hidpp Linux driver. */
1184 		error = uhidpp_sleep(sc, SEC_TO_NSEC(5));
1185 		if (error) {
1186 			error = -error;
1187 			goto out;
1188 		}
1189 	}
1190 
1191 	if (sc->sc_resp_state == UHIDPP_RESP_ERROR)
1192 		error = -EIO;
1193 	else if (sc->sc_resp_state == HIDPP_REPORT_ID_SHORT &&
1194 	    resp->rap.sub_id == HIDPP_ERROR)
1195 		error = resp->rap.params[1];
1196 	else if (sc->sc_resp_state == HIDPP_REPORT_ID_LONG &&
1197 	    resp->fap.feature_idx == HIDPP20_ERROR)
1198 		error = resp->fap.params[1];
1199 
1200 out:
1201 	sc->sc_req = NULL;
1202 	sc->sc_resp = NULL;
1203 	sc->sc_resp_state = UHIDPP_RESP_NONE;
1204 	wakeup(sc);
1205 	return error;
1206 }
1207 
1208 #ifdef UHIDPP_DEBUG
1209 
1210 void
1211 uhidd_dump_report(const char *prefix, uint8_t repid, const unsigned char *buf,
1212     u_int buflen)
1213 {
1214 	u_int i;
1215 
1216 	printf("%s: %02x ", prefix, repid);
1217 	for (i = 0; i < buflen; i++) {
1218 		printf("%02x%s", buf[i],
1219 		    i == 2 ? " [" : (i + 1 < buflen ? " " : ""));
1220 	}
1221 	printf("]\n");
1222 }
1223 
1224 #endif
1225