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