From 2934a9b8d9db4222e81a6b07bc058f24eb3589cf Mon Sep 17 00:00:00 2001 From: miod Date: Thu, 5 Aug 2010 13:13:17 +0000 Subject: [PATCH] Allow bthidev_output() to not grab the bt lock, to prevent lock recursion when trying to send commands from input callbacks. Makes the caps/num/scroll lock keys on btkbd correctly lit the leds instead of panic'ing. Noticed and fix tested by mlarkin@, "do whatever you want in bt" deraadt@ --- sys/dev/bluetooth/bthidev.c | 12 +++++++----- sys/dev/bluetooth/bthidev.h | 4 ++-- sys/dev/bluetooth/btkbd.c | 12 ++++++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/sys/dev/bluetooth/bthidev.c b/sys/dev/bluetooth/bthidev.c index 2df63415440..5ae67ea721f 100644 --- a/sys/dev/bluetooth/bthidev.c +++ b/sys/dev/bluetooth/bthidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bthidev.c,v 1.7 2010/07/02 15:01:10 blambert Exp $ */ +/* $OpenBSD: bthidev.c,v 1.8 2010/08/05 13:13:17 miod Exp $ */ /* $NetBSD: bthidev.c,v 1.16 2008/08/06 15:01:23 plunky Exp $ */ /*- @@ -95,7 +95,7 @@ struct bthidev_softc { void bthidev_timeout(void *); int bthidev_listen(struct bthidev_softc *); int bthidev_connect(struct bthidev_softc *); -int bthidev_output(struct bthidev *, uint8_t *, int); +int bthidev_output(struct bthidev *, uint8_t *, int, int); void bthidev_null(struct bthidev *, uint8_t *, int); /* autoconf(9) glue */ @@ -856,7 +856,7 @@ bthidev_null(struct bthidev *hidev, uint8_t *report, int len) } int -bthidev_output(struct bthidev *hidev, uint8_t *report, int rlen) +bthidev_output(struct bthidev *hidev, uint8_t *report, int rlen, int nolock) { struct bthidev_softc *sc = (struct bthidev_softc *)hidev->sc_parent; struct mbuf *m; @@ -892,9 +892,11 @@ bthidev_output(struct bthidev *hidev, uint8_t *report, int rlen) memcpy(mtod(m, uint8_t *) + 2, report, rlen); m->m_pkthdr.len = m->m_len = rlen + 2; - mutex_enter(&bt_lock); + if (!nolock) + mutex_enter(&bt_lock); err = l2cap_send(sc->sc_int, m); - mutex_exit(&bt_lock); + if (!nolock) + mutex_exit(&bt_lock); return err; } diff --git a/sys/dev/bluetooth/bthidev.h b/sys/dev/bluetooth/bthidev.h index cfc7341fcdc..2932d02d5c9 100644 --- a/sys/dev/bluetooth/bthidev.h +++ b/sys/dev/bluetooth/bthidev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bthidev.h,v 1.3 2008/02/24 21:46:19 uwe Exp $ */ +/* $OpenBSD: bthidev.h,v 1.4 2010/08/05 13:13:17 miod Exp $ */ /* $NetBSD: bthidev.h,v 1.4 2007/11/03 17:41:03 plunky Exp $ */ /*- @@ -71,7 +71,7 @@ struct bthidev_attach_args { void (*ba_feature) /* feature method */ (struct bthidev *, uint8_t *, int); int (*ba_output) /* output method */ - (struct bthidev *, uint8_t *, int); + (struct bthidev *, uint8_t *, int, int); }; #endif /* _KERNEL */ diff --git a/sys/dev/bluetooth/btkbd.c b/sys/dev/bluetooth/btkbd.c index ff34824c200..5de8553c04a 100644 --- a/sys/dev/bluetooth/btkbd.c +++ b/sys/dev/bluetooth/btkbd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: btkbd.c,v 1.6 2010/07/31 16:04:50 miod Exp $ */ +/* $OpenBSD: btkbd.c,v 1.7 2010/08/05 13:13:17 miod Exp $ */ /* $NetBSD: btkbd.c,v 1.10 2008/09/09 03:54:56 cube Exp $ */ /* @@ -90,7 +90,8 @@ struct btkbd_softc { struct bthidev sc_hidev; /* device */ struct hidkbd sc_kbd; /* keyboard state */ int (*sc_output) /* output method */ - (struct bthidev *, uint8_t *, int); + (struct bthidev *, uint8_t *, int, int); + int sc_inintr; }; /* autoconf(9) methods */ @@ -188,7 +189,7 @@ btkbd_set_leds(void *self, int leds) if (hidkbd_set_leds(kbd, leds, &report) != 0) { if (sc->sc_output != NULL) (*sc->sc_output)(&sc->sc_hidev, &report, - sizeof(report)); + sizeof(report), sc->sc_inintr); } } @@ -216,6 +217,9 @@ btkbd_input(struct bthidev *self, uint8_t *data, int len) struct btkbd_softc *sc = (struct btkbd_softc *)self; struct hidkbd *kbd = &sc->sc_kbd; - if (kbd->sc_enabled != 0) + if (kbd->sc_enabled != 0) { + sc->sc_inintr = 1; hidkbd_input(kbd, data, len); + sc->sc_inintr = 0; + } } -- 2.20.1