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