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