summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/bluetooth/btdev.h26
-rw-r--r--sys/dev/bluetooth/bthidev.c224
-rw-r--r--sys/dev/bluetooth/bthidev.h10
-rw-r--r--sys/dev/bluetooth/bthub.c112
-rw-r--r--sys/dev/bluetooth/btkbd.c13
-rw-r--r--sys/dev/bluetooth/btms.c32
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;