diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2008-02-24 21:46:20 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2008-02-24 21:46:20 +0000 |
commit | 8b56fd8028eb15e94de291467a4bf213a13f0b3a (patch) | |
tree | bd3d86efff3a7f1f48de401e03ed235036f1afd6 /sys/dev/bluetooth | |
parent | e1b76e90d81c71953efdcba2e828cdeae87cd7a9 (diff) |
Sync Bluetooth HID drivers with NetBSD and adopt to our needs, as we
don't have problib
Diffstat (limited to 'sys/dev/bluetooth')
-rw-r--r-- | sys/dev/bluetooth/btdev.h | 26 | ||||
-rw-r--r-- | sys/dev/bluetooth/bthidev.c | 224 | ||||
-rw-r--r-- | sys/dev/bluetooth/bthidev.h | 10 | ||||
-rw-r--r-- | sys/dev/bluetooth/bthub.c | 112 | ||||
-rw-r--r-- | sys/dev/bluetooth/btkbd.c | 13 | ||||
-rw-r--r-- | sys/dev/bluetooth/btms.c | 32 |
6 files changed, 323 insertions, 94 deletions
diff --git a/sys/dev/bluetooth/btdev.h b/sys/dev/bluetooth/btdev.h index e158b9598e6..d08ed593280 100644 --- a/sys/dev/bluetooth/btdev.h +++ b/sys/dev/bluetooth/btdev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: btdev.h,v 1.3 2007/09/01 17:06:26 xsa Exp $ */ +/* $OpenBSD: btdev.h,v 1.4 2008/02/24 21:46:19 uwe Exp $ */ /* $NetBSD: btdev.h,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */ /*- @@ -35,6 +35,8 @@ #ifndef _DEV_BLUETOOTH_BTDEV_H_ #define _DEV_BLUETOOTH_BTDEV_H_ +#include <netbt/bluetooth.h> + /* * Bluetooth Device attach arguments (from userland) */ @@ -42,6 +44,7 @@ struct btdev_attach_args { bdaddr_t bd_laddr; /* local address */ bdaddr_t bd_raddr; /* remote address */ uint16_t bd_type; /* device type */ + int bd_mode; /* link mode */ union { struct { /* HID arguments */ @@ -55,28 +58,38 @@ struct btdev_attach_args { struct { /* HSET arguments */ uint8_t hset_channel; /* RFCOMM channel */ uint8_t hset_mtu; /* SCO mtu */ + int hset_listen; /* connect or listen */ } bdd_hset; - struct { /* Advance Audio arguments */ - } bdd_a2dp; + struct { /* HF arguments */ + uint8_t hf_channel; /* RFCOMM channel */ + uint8_t hf_mtu; /* SCO mtu */ + int hf_listen; /* connect or listen */ + } bdd_hf; } bdd; }; #define bd_hid bdd.bdd_hid #define bd_hset bdd.bdd_hset -#define bd_a2dp bdd.bdd_a2dp +#define bd_hf bdd.bdd_hf /* btdev type */ #define BTDEV_HID 0x0001 #define BTDEV_HSET 0x0002 +#define BTDEV_HF 0x0003 + +/* btdev link mode */ +#define BTDEV_MODE_NONE 0 +#define BTDEV_MODE_AUTH 1 +#define BTDEV_MODE_ENCRYPT 2 +#define BTDEV_MODE_SECURE 3 /* bthid flags */ #define BTHID_INITIATE (1 << 0) /* normally initiate */ -#define BTHID_CONNECT (1 << 1) /* initiate connect */ /* btdev attach/detach ioctl's */ #define BTDEV_ATTACH _IOW('b', 14, struct btdev_attach_args) -#define BTDEV_DETACH _IOW('b', 15, bdaddr_t) +#define BTDEV_DETACH _IOW('b', 15, struct btdev_attach_args) #ifdef _KERNEL @@ -86,6 +99,7 @@ struct btdev_attach_args { struct btdev { struct device sc_dev; /* system device */ bdaddr_t sc_addr; /* device bdaddr */ + uint16_t sc_type; /* device type */ LIST_ENTRY(btdev) sc_next; }; diff --git a/sys/dev/bluetooth/bthidev.c b/sys/dev/bluetooth/bthidev.c index 4304f6cc02b..2ac50931dd6 100644 --- a/sys/dev/bluetooth/bthidev.c +++ b/sys/dev/bluetooth/bthidev.c @@ -1,5 +1,5 @@ -/* $OpenBSD: bthidev.c,v 1.1 2007/09/01 17:06:26 xsa Exp $ */ -/* $NetBSD: bthidev.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */ +/* $OpenBSD: bthidev.c,v 1.2 2008/02/24 21:46:19 uwe Exp $ */ +/* $NetBSD: bthidev.c,v 1.13 2007/11/12 19:19:32 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -55,13 +55,13 @@ /* bthidev softc */ struct bthidev_softc { - struct btdev sc_btdev; /* device+ */ + struct btdev sc_btdev; /* base device */ uint16_t sc_state; uint16_t sc_flags; bdaddr_t sc_laddr; /* local address */ bdaddr_t sc_raddr; /* remote address */ - + int sc_mode; /* link mode */ void *sc_desc; /* HID descriptor */ int sc_dlen; /* descriptor length */ @@ -79,6 +79,10 @@ struct bthidev_softc { int sc_attempts; /* connection attempts */ }; +/* sc_flags */ +#define BTHID_RECONNECT (1 << 0) /* reconnect on link loss */ +#define BTHID_CONNECTING (1 << 1) /* we are connecting */ + /* device state */ #define BTHID_CLOSED 0 #define BTHID_WAIT_CTL 1 @@ -88,12 +92,14 @@ struct bthidev_softc { #define BTHID_RETRY_INTERVAL 5 /* seconds between connection attempts */ +/* bthidev internals */ void bthidev_timeout(void *); int bthidev_listen(struct bthidev_softc *); int bthidev_connect(struct bthidev_softc *); int bthidev_output(struct bthidev *, uint8_t *, int); void bthidev_null(struct bthidev *, uint8_t *, int); +/* autoconf(9) glue */ int bthidev_match(struct device *, void *, void *); void bthidev_attach(struct device *, struct device *, void *); int bthidev_detach(struct device *, int); @@ -123,6 +129,7 @@ void *bthidev_ctl_newconn(void *, struct sockaddr_bt *, void *bthidev_int_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); void bthidev_complete(void *, int); +void bthidev_linkmode(void *, int); void bthidev_input(void *, struct mbuf *); const struct btproto bthidev_ctl_proto = { @@ -131,7 +138,7 @@ const struct btproto bthidev_ctl_proto = { bthidev_ctl_disconnected, bthidev_ctl_newconn, bthidev_complete, - NULL, + bthidev_linkmode, bthidev_input, }; @@ -141,22 +148,21 @@ const struct btproto bthidev_int_proto = { bthidev_int_disconnected, bthidev_int_newconn, bthidev_complete, - NULL, + bthidev_linkmode, bthidev_input, }; +/***************************************************************************** + * + * bthidev autoconf(9) routines + */ int bthidev_match(struct device *self, void *match, void *aux) { struct btdev_attach_args *bda = (struct btdev_attach_args *)aux; - if (bda->bd_type != BTDEV_HID - || L2CAP_PSM_INVALID(bda->bd_hid.hid_ctl) - || L2CAP_PSM_INVALID(bda->bd_hid.hid_int) - || bda->bd_hid.hid_desc == NULL - || bda->bd_hid.hid_dlen == 0 - || bda->bd_hid.hid_dlen > MAX_DESCRIPTOR_LEN) + if (bda->bd_type != BTDEV_HID) return 0; return 1; @@ -168,7 +174,7 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) struct bthidev_softc *sc = (struct bthidev_softc *)self; struct btdev_attach_args *bda = (struct btdev_attach_args *)aux; struct bthidev_attach_args bha; - struct bthidev *dev; + struct bthidev *hidev; struct hid_data *d; struct hid_item h; int maxid, rep, s; @@ -179,6 +185,9 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) LIST_INIT(&sc->sc_list); timeout_set(&sc->sc_reconnect, bthidev_timeout, sc); sc->sc_state = BTHID_CLOSED; + sc->sc_flags = BTHID_CONNECTING; + sc->sc_ctlpsm = L2CAP_PSM_HID_CNTL; + sc->sc_intpsm = L2CAP_PSM_HID_INTR; /* * copy in our configuration info @@ -186,20 +195,48 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) bdaddr_copy(&sc->sc_laddr, &bda->bd_laddr); bdaddr_copy(&sc->sc_raddr, &bda->bd_raddr); - sc->sc_ctlpsm = bda->bd_hid.hid_ctl; - sc->sc_intpsm = bda->bd_hid.hid_int; + if (bda->bd_mode != BTDEV_MODE_NONE) { + if (bda->bd_mode == BTDEV_MODE_AUTH) { + sc->sc_mode = L2CAP_LM_AUTH; + printf(" auth"); + } else if (bda->bd_mode == BTDEV_MODE_ENCRYPT) { + sc->sc_mode = L2CAP_LM_ENCRYPT; + printf(" encrypt"); + } else if (bda->bd_mode == BTDEV_MODE_SECURE) { + sc->sc_mode = L2CAP_LM_SECURE; + printf(" secure"); + } else { + printf(" unknown link-mode: %d\n", bda->bd_mode); + return; + } + } + + if (!L2CAP_PSM_INVALID(bda->bd_hid.hid_ctl)) + sc->sc_ctlpsm = bda->bd_hid.hid_ctl; + + if (!L2CAP_PSM_INVALID(bda->bd_hid.hid_int)) + sc->sc_intpsm = bda->bd_hid.hid_int; - sc->sc_flags = bda->bd_hid.hid_flags; - if (sc->sc_flags & BTHID_INITIATE) - sc->sc_flags |= BTHID_CONNECT; + if (bda->bd_hid.hid_flags & BTHID_INITIATE) + sc->sc_flags |= BTHID_RECONNECT; + if (bda->bd_hid.hid_desc == NULL || + bda->bd_hid.hid_dlen == 0 || + bda->bd_hid.hid_dlen > MAX_DESCRIPTOR_LEN) { + printf(": no descriptor\n"); + return; + } sc->sc_dlen = bda->bd_hid.hid_dlen; sc->sc_desc = malloc(bda->bd_hid.hid_dlen, M_BTHIDEV, M_WAITOK); if (sc->sc_desc == NULL) { - printf(" no memory\n"); + printf(": no memory\n"); + return; + } + if (copyin(bda->bd_hid.hid_desc, sc->sc_desc, bda->bd_hid.hid_dlen)) { + free(sc->sc_desc, M_BTHIDEV); + printf(": no descriptor"); return; } - copyin(bda->bd_hid.hid_desc, sc->sc_desc, bda->bd_hid.hid_dlen); /* * Parse the descriptor and attach child devices, one per report. @@ -214,7 +251,7 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) hid_end_parse(d); if (maxid < 0) { - printf(" no reports found\n"); + printf(": no reports found\n"); return; } @@ -233,14 +270,14 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) bha.ba_output = bthidev_output; bha.ba_id = rep; - dev = (struct bthidev *)config_found_sm(self, &bha, + hidev = (struct bthidev *)config_found_sm(self, &bha, bthidev_print, bthidevsubmatch); - if (dev != NULL) { - dev->sc_parent = &sc->sc_btdev; - dev->sc_id = rep; - dev->sc_input = bha.ba_input; - dev->sc_feature = bha.ba_feature; - LIST_INSERT_HEAD(&sc->sc_list, dev, sc_next); + if (hidev != NULL) { + hidev->sc_parent = &sc->sc_btdev; + hidev->sc_id = rep; + hidev->sc_input = bha.ba_input; + hidev->sc_feature = bha.ba_feature; + LIST_INSERT_HEAD(&sc->sc_list, hidev, sc_next); } } @@ -248,10 +285,10 @@ bthidev_attach(struct device *parent, struct device *self, void *aux) * start bluetooth connections */ s = splsoftnet(); - if ((sc->sc_flags & BTHID_INITIATE) == 0) + if ((sc->sc_flags & BTHID_RECONNECT) == 0) bthidev_listen(sc); - if (sc->sc_flags & BTHID_CONNECT) + if (sc->sc_flags & BTHID_CONNECTING) bthidev_connect(sc); splx(s); } @@ -260,7 +297,7 @@ int bthidev_detach(struct device *self, int flags) { struct bthidev_softc *sc = (struct bthidev_softc *)self; - struct bthidev *dev; + struct bthidev *hidev; int s; s = splsoftnet(); @@ -292,15 +329,16 @@ bthidev_detach(struct device *self, int flags) sc->sc_ctl = NULL; } + /* remove timeout */ sc->sc_state = BTHID_DETACHING; timeout_del(&sc->sc_reconnect); splx(s); /* detach children */ - while ((dev = LIST_FIRST(&sc->sc_list)) != NULL) { - LIST_REMOVE(dev, sc_next); - config_detach(&dev->sc_dev, flags); + while ((hidev = LIST_FIRST(&sc->sc_list)) != NULL) { + LIST_REMOVE(hidev, sc_next); + config_detach(&hidev->sc_dev, flags); } /* release descriptor */ @@ -311,6 +349,9 @@ bthidev_detach(struct device *self, int flags) return 0; } +/* + * bthidev config print + */ int bthidev_print(void *aux, const char *pnp) { @@ -345,24 +386,35 @@ bthidevsubmatch(struct device *parent, void *match, void *aux) */ /* - * callouts are scheduled to initiate outgoing connections - * after the connection has been lost. + * callouts are scheduled after connections have been lost, in order + * to clean up and reconnect. */ void bthidev_timeout(void *arg) { struct bthidev_softc *sc = arg; - int s, err; + int s; s = splsoftnet(); switch (sc->sc_state) { case BTHID_CLOSED: - sc->sc_flags |= BTHID_CONNECT; - err = bthidev_connect(sc); - if (err) - printf("%s: connect failed (%d)\n", - sc->sc_btdev.sc_dev.dv_xname, err); + if (sc->sc_int != NULL) { + l2cap_disconnect(sc->sc_int, 0); + break; + } + + if (sc->sc_ctl != NULL) { + l2cap_disconnect(sc->sc_ctl, 0); + break; + } + + if (sc->sc_flags & BTHID_RECONNECT) { + sc->sc_flags |= BTHID_CONNECTING; + bthidev_connect(sc); + break; + } + break; case BTHID_WAIT_CTL: @@ -405,6 +457,10 @@ bthidev_listen(struct bthidev_softc *sc) if (err) return err; + err = l2cap_setopt(sc->sc_ctl_l, SO_L2CAP_LM, &sc->sc_mode); + if (err) + return err; + sa.bt_psm = sc->sc_ctlpsm; err = l2cap_bind(sc->sc_ctl_l, &sa); if (err) @@ -421,6 +477,10 @@ bthidev_listen(struct bthidev_softc *sc) if (err) return err; + err = l2cap_setopt(sc->sc_int_l, SO_L2CAP_LM, &sc->sc_mode); + if (err) + return err; + sa.bt_psm = sc->sc_intpsm; err = l2cap_bind(sc->sc_int_l, &sa); if (err) @@ -458,6 +518,10 @@ bthidev_connect(struct bthidev_softc *sc) return err; } + err = l2cap_setopt(sc->sc_ctl, SO_L2CAP_LM, &sc->sc_mode); + if (err) + return err; + bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); err = l2cap_bind(sc->sc_ctl, &sa); if (err) { @@ -490,8 +554,7 @@ bthidev_connect(struct bthidev_softc *sc) void bthidev_connecting(void *arg) { - - /* dont care */ + /* don't care */ } void @@ -507,12 +570,16 @@ bthidev_ctl_connected(void *arg) KASSERT(sc->sc_ctl != NULL); KASSERT(sc->sc_int == NULL); - if (sc->sc_flags & BTHID_CONNECT) { + if (sc->sc_flags & BTHID_CONNECTING) { /* initiate connect on interrupt PSM */ err = l2cap_attach(&sc->sc_int, &bthidev_int_proto, sc); if (err) goto fail; + err = l2cap_setopt(sc->sc_int, SO_L2CAP_LM, &sc->sc_mode); + if (err) + goto fail; + memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; @@ -551,7 +618,7 @@ bthidev_int_connected(void *arg) KASSERT(sc->sc_int != NULL); sc->sc_attempts = 0; - sc->sc_flags &= ~BTHID_CONNECT; + sc->sc_flags &= ~BTHID_CONNECTING; sc->sc_state = BTHID_OPEN; printf("%s: connected\n", sc->sc_btdev.sc_dev.dv_xname); @@ -561,7 +628,8 @@ bthidev_int_connected(void *arg) * Disconnected * * Depending on our state, this could mean several things, but essentially - * we are lost. + * we are lost. If both channels are closed, and we are marked to reconnect, + * schedule another try otherwise just give up. They will contact us. */ void bthidev_ctl_disconnected(void *arg, int err) @@ -578,11 +646,19 @@ bthidev_ctl_disconnected(void *arg, int err) if (sc->sc_int == NULL) { printf("%s: disconnected\n", sc->sc_btdev.sc_dev.dv_xname); - if (sc->sc_flags & BTHID_INITIATE) + if (sc->sc_flags & BTHID_RECONNECT) timeout_add(&sc->sc_reconnect, BTHID_RETRY_INTERVAL * hz); else sc->sc_state = BTHID_WAIT_CTL; + } else { + /* + * The interrupt channel should have been closed first, + * but its potentially unsafe to detach that from here. + * Give them a second to do the right thing or let the + * callout handle it. + */ + timeout_add(&sc->sc_reconnect, hz); } } @@ -600,12 +676,19 @@ bthidev_int_disconnected(void *arg, int err) if (sc->sc_ctl == NULL) { printf("%s: disconnected\n", sc->sc_btdev.sc_dev.dv_xname); + sc->sc_flags &= ~BTHID_CONNECTING; - if (sc->sc_flags & BTHID_INITIATE) + if (sc->sc_flags & BTHID_RECONNECT) timeout_add(&sc->sc_reconnect, BTHID_RETRY_INTERVAL * hz); else sc->sc_state = BTHID_WAIT_CTL; + } else { + /* + * The control channel should be closing also, allow + * them a chance to do that before we force it. + */ + timeout_add(&sc->sc_reconnect, hz); } } @@ -623,7 +706,7 @@ bthidev_ctl_newconn(void *arg, struct sockaddr_bt *laddr, struct bthidev_softc *sc = arg; if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0 - || (sc->sc_flags & BTHID_INITIATE) + || (sc->sc_flags & BTHID_CONNECTING) || sc->sc_state != BTHID_WAIT_CTL || sc->sc_ctl != NULL || sc->sc_int != NULL) @@ -640,7 +723,7 @@ bthidev_int_newconn(void *arg, struct sockaddr_bt *laddr, struct bthidev_softc *sc = arg; if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0 - || (sc->sc_flags & BTHID_INITIATE) + || (sc->sc_flags & BTHID_CONNECTING) || sc->sc_state != BTHID_WAIT_INT || sc->sc_ctl == NULL || sc->sc_int != NULL) @@ -657,6 +740,27 @@ bthidev_complete(void *arg, int count) /* dont care */ } +void +bthidev_linkmode(void *arg, int new) +{ + struct bthidev_softc *sc = arg; + + if ((sc->sc_mode & L2CAP_LM_AUTH) && !(new & L2CAP_LM_AUTH)) + printf("%s: auth failed\n", sc->sc_btdev.sc_dev.dv_xname); + else if ((sc->sc_mode & L2CAP_LM_ENCRYPT) && !(new & L2CAP_LM_ENCRYPT)) + printf("%s: encrypt off\n", sc->sc_btdev.sc_dev.dv_xname); + else if ((sc->sc_mode & L2CAP_LM_SECURE) && !(new & L2CAP_LM_SECURE)) + printf("%s: insecure\n", sc->sc_btdev.sc_dev.dv_xname); + else + return; + + if (sc->sc_int != NULL) + l2cap_disconnect(sc->sc_int, 0); + + if (sc->sc_ctl != NULL) + l2cap_disconnect(sc->sc_ctl, 0); +} + /* * Receive reports from the protocol stack. */ @@ -664,7 +768,7 @@ void bthidev_input(void *arg, struct mbuf *m) { struct bthidev_softc *sc = arg; - struct bthidev *dev; + struct bthidev *hidev; uint8_t *data; int len; @@ -687,15 +791,15 @@ bthidev_input(void *arg, struct mbuf *m) if (len < 3) goto release; - LIST_FOREACH(dev, &sc->sc_list, sc_next) { - if (data[1] == dev->sc_id) { + LIST_FOREACH(hidev, &sc->sc_list, sc_next) { + if (data[1] == hidev->sc_id) { switch (BTHID_DATA_PARAM(data[0])) { case BTHID_DATA_INPUT: - (*dev->sc_input)(dev, data + 2, len - 2); + (*hidev->sc_input)(hidev, data + 2, len - 2); break; case BTHID_DATA_FEATURE: - (*dev->sc_feature)(dev, data + 2, len - 2); + (*hidev->sc_feature)(hidev, data + 2, len - 2); break; default: @@ -747,7 +851,7 @@ release: */ void -bthidev_null(struct bthidev *dev, uint8_t *report, int len) +bthidev_null(struct bthidev *hidev, uint8_t *report, int len) { /* @@ -757,9 +861,9 @@ bthidev_null(struct bthidev *dev, uint8_t *report, int len) } int -bthidev_output(struct bthidev *dev, uint8_t *report, int rlen) +bthidev_output(struct bthidev *hidev, uint8_t *report, int rlen) { - struct bthidev_softc *sc = (struct bthidev_softc *)dev->sc_parent; + struct bthidev_softc *sc = (struct bthidev_softc *)hidev->sc_parent; struct mbuf *m; int s, err; @@ -789,7 +893,7 @@ bthidev_output(struct bthidev *dev, uint8_t *report, int rlen) * data[2..N] = report */ mtod(m, uint8_t *)[0] = (uint8_t)((BTHID_DATA << 4) | BTHID_DATA_OUTPUT); - mtod(m, uint8_t *)[1] = dev->sc_id; + mtod(m, uint8_t *)[1] = hidev->sc_id; memcpy(mtod(m, uint8_t *) + 2, report, rlen); m->m_pkthdr.len = m->m_len = rlen + 2; diff --git a/sys/dev/bluetooth/bthidev.h b/sys/dev/bluetooth/bthidev.h index 76765bfaf6d..cfc7341fcdc 100644 --- a/sys/dev/bluetooth/bthidev.h +++ b/sys/dev/bluetooth/bthidev.h @@ -1,5 +1,5 @@ -/* $OpenBSD: bthidev.h,v 1.2 2007/09/01 17:06:26 xsa Exp $ */ -/* $NetBSD: bthidev.h,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */ +/* $OpenBSD: bthidev.h,v 1.3 2008/02/24 21:46:19 uwe Exp $ */ +/* $NetBSD: bthidev.h,v 1.4 2007/11/03 17:41:03 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -35,12 +35,15 @@ #ifndef _DEV_BLUETOOTH_BTHIDEV_H_ #define _DEV_BLUETOOTH_BTHIDEV_H_ +#ifdef _KERNEL + #define BTHIDBUSCF_REPORTID 0 #define BTHIDBUSCF_REPORTID_DEFAULT -1 #define bthidevcf_reportid cf_loc[BTHIDBUSCF_REPORTID] #define BTHIDEV_UNK_REPORTID BTHIDBUSCF_REPORTID_DEFAULT +/* HID device header */ struct bthidev { struct device sc_dev; struct btdev *sc_parent; @@ -57,6 +60,7 @@ struct bthidev { LIST_ENTRY(bthidev) sc_next; }; +/* HID device attach arguments */ struct bthidev_attach_args { void *ba_desc; /* descriptor */ int ba_dlen; /* descriptor length */ @@ -70,4 +74,6 @@ struct bthidev_attach_args { (struct bthidev *, uint8_t *, int); }; +#endif /* _KERNEL */ + #endif /* _DEV_BLUETOOTH_BTHIDEV_H_ */ diff --git a/sys/dev/bluetooth/bthub.c b/sys/dev/bluetooth/bthub.c index 31a3d52b42b..e5d209e034c 100644 --- a/sys/dev/bluetooth/bthub.c +++ b/sys/dev/bluetooth/bthub.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bthub.c,v 1.3 2007/07/23 14:45:38 mk Exp $ */ +/* $OpenBSD: bthub.c,v 1.4 2008/02/24 21:46:19 uwe Exp $ */ /* * Copyright (c) 2007 Uwe Stuehler <uwe@openbsd.org> @@ -25,14 +25,20 @@ #include <netbt/bluetooth.h> +#include <dev/bluetooth/btdev.h> + struct bthub_softc { struct device sc_dev; int sc_open; + bdaddr_t sc_laddr; + LIST_HEAD(, btdev) sc_list; }; int bthub_match(struct device *, void *, void *); void bthub_attach(struct device *, struct device *, void *); int bthub_detach(struct device *, int); +int bthub_print(void *, const char *); +int bthub_devioctl(dev_t, u_long, struct btdev_attach_args *); struct cfattach bthub_ca = { sizeof(struct bthub_softc), bthub_match, bthub_attach, bthub_detach @@ -51,10 +57,11 @@ bthub_match(struct device *parent, void *match, void *aux) void bthub_attach(struct device *parent, struct device *self, void *aux) { - bdaddr_t *addr = aux; struct bthub_softc *sc = (struct bthub_softc *)self; + bdaddr_t *addr = aux; sc->sc_open = 0; + bdaddr_copy(&sc->sc_laddr, addr); printf(" %02x:%02x:%02x:%02x:%02x:%02x\n", addr->b[5], addr->b[4], addr->b[3], @@ -64,7 +71,10 @@ bthub_attach(struct device *parent, struct device *self, void *aux) int bthub_detach(struct device *self, int flags) { + struct bthub_softc *sc = (struct bthub_softc *)self; + struct btdev *btdev; int maj, mn; + int err; /* Locate the major number */ for (maj = 0; maj < nchrdev; maj++) @@ -75,10 +85,37 @@ bthub_detach(struct device *self, int flags) mn = self->dv_unit; vdevgone(maj, mn, mn, VCHR); + /* Detach all child devices. */ + while (!LIST_EMPTY(&sc->sc_list)) { + btdev = LIST_FIRST(&sc->sc_list); + LIST_REMOVE(btdev, sc_next); + + err = config_detach(&btdev->sc_dev, flags); + if (err && (flags & DETACH_FORCE) == 0) { + LIST_INSERT_HEAD(&sc->sc_list, btdev, sc_next); + return err; + } + } + return (0); } int +bthub_print(void *aux, const char *parentname) +{ + struct btdev_attach_args *bd = aux; + bdaddr_t *raddr = &bd->bd_raddr; + + if (parentname != NULL) + return QUIET; + + printf(" %02x:%02x:%02x:%02x:%02x:%02x", + raddr->b[5], raddr->b[4], raddr->b[3], raddr->b[2], + raddr->b[1], raddr->b[0]); + return QUIET; +} + +int bthubopen(dev_t dev, int flag, int mode, struct proc *p) { struct device *dv; @@ -117,6 +154,75 @@ bthubclose(dev_t dev, int flag, int mode, struct proc *p) int bthubioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { - return (ENOTTY); + struct btdev_attach_args *bd; + int err; + + switch (cmd) { + case BTDEV_ATTACH: + case BTDEV_DETACH: + bd = (struct btdev_attach_args *)data; + err = bthub_devioctl(dev, cmd, bd); + break; + default: + err = ENOTTY; + } + + return err; +} + +int +bthub_devioctl(dev_t dev, u_long cmd, struct btdev_attach_args *bd) +{ + struct device *dv; + struct bthub_softc *sc; + struct btdev *btdev; + int unit; + + /* Locate the relevant bthub. */ + for (unit = 0; unit < bthub_cd.cd_ndevs; unit++) { + if ((dv = bthub_cd.cd_devs[unit]) == NULL) + continue; + + sc = (struct bthub_softc *)dv; + if (bdaddr_same(&sc->sc_laddr, &bd->bd_laddr)) + break; + } + if (unit == bthub_cd.cd_ndevs) + return (ENXIO); + + /* Locate matching child device, if any. */ + LIST_FOREACH(btdev, &sc->sc_list, sc_next) { + if (!bdaddr_same(&btdev->sc_addr, &bd->bd_raddr)) + continue; + if (btdev->sc_type != bd->bd_type) + continue; + break; + } + + switch (cmd) { + case BTDEV_ATTACH: + if (btdev != NULL) + return EADDRINUSE; + + dv = config_found(&sc->sc_dev, bd, bthub_print); + if (dv == NULL) + return ENXIO; + + btdev = (struct btdev *)dv; + bdaddr_copy(&btdev->sc_addr, &bd->bd_raddr); + btdev->sc_type = bd->bd_type; + LIST_INSERT_HEAD(&sc->sc_list, btdev, sc_next); + break; + + case BTDEV_DETACH: + if (btdev == NULL) + return ENXIO; + + LIST_REMOVE(btdev, sc_next); + config_detach(&btdev->sc_dev, DETACH_FORCE); + break; + } + + return 0; } diff --git a/sys/dev/bluetooth/btkbd.c b/sys/dev/bluetooth/btkbd.c index 0d65a8efc18..2793c32c1dc 100644 --- a/sys/dev/bluetooth/btkbd.c +++ b/sys/dev/bluetooth/btkbd.c @@ -1,5 +1,5 @@ -/* $OpenBSD: btkbd.c,v 1.2 2007/09/01 17:06:26 xsa Exp $ */ -/* $NetBSD: btkbd.c,v 1.7 2007/07/09 21:00:31 ad Exp $ */ +/* $OpenBSD: btkbd.c,v 1.3 2008/02/24 21:46:19 uwe Exp $ */ +/* $NetBSD: btkbd.c,v 1.9 2007/11/03 18:24:01 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -107,6 +107,7 @@ struct btkbd_softc { #endif }; +/* autoconf(9) methods */ int btkbd_match(struct device *, void *, void *); void btkbd_attach(struct device *, struct device *, void *); int btkbd_detach(struct device *, int); @@ -122,6 +123,7 @@ const struct cfattach btkbd_ca = { btkbd_detach, }; +/* wskbd(4) accessops */ int btkbd_enable(void *, int); void btkbd_set_leds(void *, int); int btkbd_ioctl(void *, u_long, caddr_t, int, struct proc *); @@ -192,8 +194,7 @@ btkbd_attach(struct device *parent, struct device *self, void *aux) #ifdef WSDISPLAY_COMPAT_RAWKBD #ifdef BTKBD_REPEAT - timeout_set(&sc->sc_repeat, NULL, NULL); - /* callout_setfunc(&sc->sc_repeat, btkbd_repeat, sc); */ + timeout_set(&sc->sc_repeat, btkbd_repeat, sc); #endif #endif @@ -520,8 +521,6 @@ btkbd_input(struct bthidev *self, uint8_t *data, int len) timeout_del(&sc->sc_repeat); if (npress != 0) { sc->sc_nrep = npress; - timeout_del(&sc->sc_repeat); - timeout_set(&sc->sc_repeat, btkbd_repeat, sc); timeout_add(&sc->sc_repeat, hz * REP_DELAY1 / 1000); } #endif @@ -550,8 +549,6 @@ btkbd_repeat(void *arg) s = spltty(); wskbd_rawinput(sc->sc_wskbd, sc->sc_rep, sc->sc_nrep); splx(s); - timeout_del(&sc->sc_repeat); - timeout_set(&sc->sc_repeat, btkbd_repeat, sc); timeout_add(&sc->sc_repeat, hz * REP_DELAYN / 1000); } #endif diff --git a/sys/dev/bluetooth/btms.c b/sys/dev/bluetooth/btms.c index bfbd43fbbaa..0f02861ff67 100644 --- a/sys/dev/bluetooth/btms.c +++ b/sys/dev/bluetooth/btms.c @@ -1,5 +1,5 @@ -/* $OpenBSD: btms.c,v 1.2 2007/09/01 17:06:26 xsa Exp $ */ -/* $NetBSD: btms.c,v 1.6 2007/03/04 06:01:45 christos Exp $ */ +/* $OpenBSD: btms.c,v 1.3 2008/02/24 21:46:19 uwe Exp $ */ +/* $NetBSD: btms.c,v 1.7 2007/11/03 17:41:03 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -81,6 +81,7 @@ struct btms_softc { #define BTMS_HASZ (1 << 1) /* has Z direction */ #define BTMS_HASW (1 << 2) /* has W direction */ +/* autoconf(9) methods */ int btms_match(struct device *, void *, void *); void btms_attach(struct device *, struct device *, void *); int btms_detach(struct device *, int); @@ -97,14 +98,14 @@ const struct cfattach btms_ca = { }; /* wsmouse(4) accessops */ -int btms_enable(void *); -int btms_ioctl(void *, u_long, caddr_t, int, struct proc *); -void btms_disable(void *); - -const struct wsmouse_accessops btms_accessops = { - btms_enable, - btms_ioctl, - btms_disable, +int btms_wsmouse_enable(void *); +int btms_wsmouse_ioctl(void *, u_long, caddr_t, int, struct proc *); +void btms_wsmouse_disable(void *); + +const struct wsmouse_accessops btms_wsmouse_accessops = { + btms_wsmouse_enable, + btms_wsmouse_ioctl, + btms_wsmouse_disable, }; /* bthid methods */ @@ -167,7 +168,7 @@ btms_attach(struct device *parent, struct device *self, void *aux) zloc = &sc->sc_loc_z; if (hl) { if (NOTMOUSE(flags)) { - printf("\n%s: Wheel report 0x%04x not supported\n", + printf("\n%s: Wheel report 0x%04x ignored\n", sc->sc_hidev.sc_dev.dv_xname, flags); /* ignore Bad Z coord */ @@ -223,7 +224,7 @@ btms_attach(struct device *parent, struct device *self, void *aux) sc->sc_flags & BTMS_HASZ ? " and Z dir" : "", sc->sc_flags & BTMS_HASW ? "s" : ""); - wsma.accessops = &btms_accessops; + wsma.accessops = &btms_wsmouse_accessops; wsma.accesscookie = sc; sc->sc_wsmouse = config_found((struct device *)sc, @@ -245,7 +246,7 @@ btms_detach(struct device *self, int flags) } int -btms_enable(void *self) +btms_wsmouse_enable(void *self) { struct btms_softc *sc = (struct btms_softc *)self; @@ -257,7 +258,8 @@ btms_enable(void *self) } int -btms_ioctl(void *self, u_long cmd, caddr_t data, int flag, struct proc *p) +btms_wsmouse_ioctl(void *self, u_long cmd, caddr_t data, int flag, + struct proc *p) { /* struct btms_softc *sc = (struct btms_softc *)self; */ @@ -271,7 +273,7 @@ btms_ioctl(void *self, u_long cmd, caddr_t data, int flag, struct proc *p) } void -btms_disable(void *self) +btms_wsmouse_disable(void *self) { struct btms_softc *sc = (struct btms_softc *)self; |