summaryrefslogtreecommitdiffstats
path: root/lib/libbluetooth
diff options
context:
space:
mode:
authoremax <emax@FreeBSD.org>2009-03-06 23:30:07 +0000
committeremax <emax@FreeBSD.org>2009-03-06 23:30:07 +0000
commit791c32740527d11d0d8e99d0be7dc42f77bb81e7 (patch)
tree6d586208bf9c5f1fcf2714ca0c5e1c816f8d4f64 /lib/libbluetooth
parent280ce52aab6914245390757714695bd5c1f777d2 (diff)
downloadFreeBSD-src-791c32740527d11d0d8e99d0be7dc42f77bb81e7.zip
FreeBSD-src-791c32740527d11d0d8e99d0be7dc42f77bb81e7.tar.gz
Add Bluetooth compatibility shims. Inspired by Linux BlueZ and NetBSD.
Discussed with: Iain Hibbert plunky -at- rya-online -dot- net of NetBSD MFC after: 1 month
Diffstat (limited to 'lib/libbluetooth')
-rw-r--r--lib/libbluetooth/Makefile8
-rw-r--r--lib/libbluetooth/bluetooth.3135
-rw-r--r--lib/libbluetooth/bluetooth.c6
-rw-r--r--lib/libbluetooth/bluetooth.h66
-rw-r--r--lib/libbluetooth/dev.c95
-rw-r--r--lib/libbluetooth/hci.c246
6 files changed, 548 insertions, 8 deletions
diff --git a/lib/libbluetooth/Makefile b/lib/libbluetooth/Makefile
index 30c55b8..b64fbb4 100644
--- a/lib/libbluetooth/Makefile
+++ b/lib/libbluetooth/Makefile
@@ -9,7 +9,7 @@ CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys
SHLIB_MAJOR= 3
-SRCS= bluetooth.c
+SRCS= bluetooth.c dev.c hci.c
INCS= bluetooth.h
MLINKS+= bluetooth.3 bt_gethostbyname.3
@@ -27,6 +27,12 @@ MLINKS+= bluetooth.3 bt_endprotoent.3
MLINKS+= bluetooth.3 bt_ntoa.3
MLINKS+= bluetooth.3 bt_aton.3
+MLINKS+= bluetooth.3 bt_devaddr.3
+MLINKS+= bluetooth.3 bt_devname.3
+
+MLINKS+= bluetooth.3 bt_devinfo.3
+MLINKS+= bluetooth.3 bt_devenum.3
+
MLINKS+= bluetooth.3 bdaddr_same.3
MLINKS+= bluetooth.3 bdaddr_any.3
MLINKS+= bluetooth.3 bdaddr_copy.3
diff --git a/lib/libbluetooth/bluetooth.3 b/lib/libbluetooth/bluetooth.3
index c6a0dc3..61fa1e4 100644
--- a/lib/libbluetooth/bluetooth.3
+++ b/lib/libbluetooth/bluetooth.3
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+.\" Copyright (c) 2003-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
.\" $Id: bluetooth.3,v 1.5 2003/05/20 23:04:30 max Exp $
.\" $FreeBSD$
.\"
-.Dd August 13, 2008
+.Dd February 13, 2009
.Dt BLUETOOTH 3
.Os
.Sh NAME
@@ -74,6 +74,16 @@
.Ft const char *
.Fn bt_ntoa "const bdaddr_t *ba" "char *str"
.Ft int
+.Fn bt_devaddr "const char *devname" "bdaddr_t *addr"
+.Ft int
+.Fn bt_devname "char *devname" "const bdaddr_t *addr"
+.Ft int
+.Fn (bt_devenum_cb_t) "int s" "struct bt_devinfo const *di" "void *arg"
+.Ft int
+.Fn bt_devinfo "struct bt_devinfo *di"
+.Ft int
+.Fn bt_devenum "bt_devenum_cb_t *cb" "void *arg"
+.Ft int
.Fn bdaddr_same "const bdaddr_t *a" "const bdaddr_t *b"
.Ft int
.Fn bdaddr_any "const bdaddr_t *a"
@@ -197,6 +207,110 @@ It is up to the caller to ensure that provided buffer has enough space.
If no buffer was provided then internal static buffer will be used.
.Pp
The
+.Fn bt_devaddr
+function interprets the specified
+.Fa devname
+string as the address or device name of a Bluetooth device on the local system,
+and places the device address in the provided
+.Fa bdaddr ,
+if any.
+The function returns 1 if the string was successfully interpreted,
+or 0 if the string did not match any local device.
+The
+.Fn bt_devname
+function takes a Bluetooth device address and copies the local device
+name associated with that address into the buffer provided,
+if any.
+Caller must ensure that provided buffer is at least
+.Dv HCI_DEVNAME_SIZE
+characters in size.
+The function returns 1 when the device was found,
+otherwise 0.
+.Pp
+The
+.Fn bt_devinfo
+function populates prodivded
+.Vt bt_devinfo
+structure with the information about given Bluetooth device.
+The caller is expected to pass Bluetooth device name in the
+.Fa devname
+field of the passed
+.Vt bt_devinfo
+structure.
+The function returns 0 when successful,
+otherwise -1.
+The
+.Vt bt_devinfo
+structure is defined as follows
+.Bd -literal -offset indent
+struct bt_devinfo
+{
+ char devname[HCI_DEVNAME_SIZE];
+
+ uint32_t state;
+
+ bdaddr_t bdaddr;
+ uint16_t _reserved0;
+
+ uint8_t features[HCI_DEVFEATURES_SIZE];
+
+ /* buffer info */
+ uint16_t _reserved1;
+ uint16_t cmd_free;
+ uint16_t sco_size;
+ uint16_t sco_pkts;
+ uint16_t sco_free;
+ uint16_t acl_size;
+ uint16_t acl_pkts;
+ uint16_t acl_free;
+
+ /* stats */
+ uint32_t cmd_sent;
+ uint32_t evnt_recv;
+ uint32_t acl_recv;
+ uint32_t acl_sent;
+ uint32_t sco_recv;
+ uint32_t sco_sent;
+ uint32_t bytes_recv;
+ uint32_t bytes_sent;
+
+ /* misc/specific */
+ uint16_t link_policy_info;
+ uint16_t packet_type_info;
+ uint16_t role_switch_info;
+ uint16_t debug;
+
+ uint8_t _padding[20];
+};
+.Ed
+.Pp
+The
+.Fn bt_devenum
+function enumerates Bluetooth devices present in the system.
+For every device found,
+the function will call provided
+.Fa cb
+callback function which should be of
+.Vt bt_devenum_cb_t
+type.
+The callback function is passed a
+.Dv HCI
+socket
+.Fa s ,
+fully populated
+.Vt bt_devinfo
+structure
+.Fa di
+and
+.Fa arg
+argument provided to the
+.Fn bt_devenum .
+The callback function can stop enumeration by returning a value
+that is greater than zero.
+The function returns number of successfully enumerated devices,
+or -1 if an error occurred.
+.Pp
+The
.Fn bdaddr_same ,
.Fn bdaddr_any
and
@@ -287,7 +401,8 @@ on EOF or error.
.Xr getprotobynumber 3 ,
.Xr herror 3 ,
.Xr inet_aton 3 ,
-.Xr inet_ntoa 3
+.Xr inet_ntoa 3 ,
+.Xr ng_hci 4
.Sh CAVEAT
The
.Fn bt_gethostent
@@ -312,6 +427,20 @@ The
function opens and/or rewinds the
.Pa /etc/bluetooth/protocols
file.
+.Pp
+The
+.Fn bt_devenum
+function enumerates up to
+.Dv HCI_DEVMAX
+Bluetooth devices.
+During enumeration the
+.Fn bt_devenum
+function uses the same
+.Dv HCI
+socket.
+The function guarantees that the socket,
+passed to the callback function,
+will be bound and connected to the Bluetooth device being enumerated.
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
.Sh BUGS
diff --git a/lib/libbluetooth/bluetooth.c b/lib/libbluetooth/bluetooth.c
index f206aee..23b7df0 100644
--- a/lib/libbluetooth/bluetooth.c
+++ b/lib/libbluetooth/bluetooth.c
@@ -1,7 +1,9 @@
/*
* bluetooth.c
- *
- * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ */
+
+/*-
+ * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/lib/libbluetooth/bluetooth.h b/lib/libbluetooth/bluetooth.h
index 0b62466..d481d05 100644
--- a/lib/libbluetooth/bluetooth.h
+++ b/lib/libbluetooth/bluetooth.h
@@ -1,7 +1,9 @@
/*
* bluetooth.h
- *
- * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ */
+
+/*-
+ * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,9 +37,12 @@
#include <sys/types.h>
#include <sys/bitstring.h>
#include <sys/endian.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <errno.h>
#include <netdb.h>
+#include <netgraph/ng_message.h>
#include <netgraph/bluetooth/include/ng_hci.h>
#include <netgraph/bluetooth/include/ng_l2cap.h>
#include <netgraph/bluetooth/include/ng_btsocket.h>
@@ -72,6 +77,63 @@ void bt_endprotoent (void);
char const * bt_ntoa (bdaddr_t const *ba, char *str);
int bt_aton (char const *str, bdaddr_t *ba);
+/* bt_devXXXX() functions (inspired by NetBSD) */
+int bt_devaddr (char const *devname, bdaddr_t *addr);
+int bt_devname (char *devname, bdaddr_t const *addr);
+
+/*
+ * Bluetooth HCI functions
+ */
+
+#define HCI_DEVMAX 32 /* arbitrary */
+#define HCI_DEVNAME_SIZE NG_NODESIZ
+#define HCI_DEVFEATURES_SIZE NG_HCI_FEATURES_SIZE
+
+struct bt_devinfo
+{
+ char devname[HCI_DEVNAME_SIZE];
+
+ uint32_t state; /* device/implementation specific */
+
+ bdaddr_t bdaddr;
+ uint16_t _reserved0;
+
+ uint8_t features[HCI_DEVFEATURES_SIZE];
+
+ /* buffer info */
+ uint16_t _reserved1;
+ uint16_t cmd_free;
+ uint16_t sco_size;
+ uint16_t sco_pkts;
+ uint16_t sco_free;
+ uint16_t acl_size;
+ uint16_t acl_pkts;
+ uint16_t acl_free;
+
+ /* stats */
+ uint32_t cmd_sent;
+ uint32_t evnt_recv;
+ uint32_t acl_recv;
+ uint32_t acl_sent;
+ uint32_t sco_recv;
+ uint32_t sco_sent;
+ uint32_t bytes_recv;
+ uint32_t bytes_sent;
+
+ /* misc/specific */
+ uint16_t link_policy_info;
+ uint16_t packet_type_info;
+ uint16_t role_switch_info;
+ uint16_t debug;
+
+ uint8_t _padding[20]; /* leave space for future additions */
+};
+
+typedef int (bt_devenum_cb_t)(int, struct bt_devinfo const *, void *);
+
+int bt_devinfo (struct bt_devinfo *di);
+int bt_devenum (bt_devenum_cb_t *cb, void *arg);
+
/*
* bdaddr utility functions (from NetBSD)
*/
diff --git a/lib/libbluetooth/dev.c b/lib/libbluetooth/dev.c
new file mode 100644
index 0000000..1f9e745
--- /dev/null
+++ b/lib/libbluetooth/dev.c
@@ -0,0 +1,95 @@
+/*
+ * dev.c
+ */
+
+/*-
+ * Copyright (c) 2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <bluetooth.h>
+#include <stdio.h>
+#include <string.h>
+
+struct bt_devaddr_match_arg
+{
+ char devname[HCI_DEVNAME_SIZE];
+ bdaddr_t const *bdaddr;
+};
+
+static bt_devenum_cb_t bt_devaddr_match;
+
+int
+bt_devaddr(char const *devname, bdaddr_t *addr)
+{
+ struct bt_devinfo di;
+
+ strlcpy(di.devname, devname, sizeof(di.devname));
+
+ if (bt_devinfo(&di) < 0)
+ return (0);
+
+ if (addr != NULL)
+ bdaddr_copy(addr, &di.bdaddr);
+
+ return (1);
+}
+
+int
+bt_devname(char *devname, bdaddr_t const *addr)
+{
+ struct bt_devaddr_match_arg arg;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.bdaddr = addr;
+
+ if (bt_devenum(&bt_devaddr_match, &arg) < 0)
+ return (0);
+
+ if (arg.devname[0] == '\0') {
+ errno = ENXIO;
+ return (0);
+ }
+
+ if (devname != NULL)
+ strlcpy(devname, arg.devname, HCI_DEVNAME_SIZE);
+
+ return (1);
+}
+
+static int
+bt_devaddr_match(int s, struct bt_devinfo const *di, void *arg)
+{
+ struct bt_devaddr_match_arg *m = (struct bt_devaddr_match_arg *)arg;
+
+ if (!bdaddr_same(&di->bdaddr, m->bdaddr))
+ return (0);
+
+ strlcpy(m->devname, di->devname, sizeof(m->devname));
+
+ return (1);
+}
+
diff --git a/lib/libbluetooth/hci.c b/lib/libbluetooth/hci.c
new file mode 100644
index 0000000..b6ae10b
--- /dev/null
+++ b/lib/libbluetooth/hci.c
@@ -0,0 +1,246 @@
+/*
+ * hci.c
+ */
+
+/*-
+ * Copyright (c) 2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <bluetooth.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static char * bt_dev2node (char const *devname, char *nodename, int nnlen);
+
+int
+bt_devinfo(struct bt_devinfo *di)
+{
+ union {
+ struct ng_btsocket_hci_raw_node_state r0;
+ struct ng_btsocket_hci_raw_node_bdaddr r1;
+ struct ng_btsocket_hci_raw_node_features r2;
+ struct ng_btsocket_hci_raw_node_buffer r3;
+ struct ng_btsocket_hci_raw_node_stat r4;
+ struct ng_btsocket_hci_raw_node_link_policy_mask r5;
+ struct ng_btsocket_hci_raw_node_packet_mask r6;
+ struct ng_btsocket_hci_raw_node_role_switch r7;
+ struct ng_btsocket_hci_raw_node_debug r8;
+ } rp;
+ struct sockaddr_hci ha;
+ int s, rval;
+
+ if (di == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ memset(&ha, 0, sizeof(ha));
+ ha.hci_len = sizeof(ha);
+ ha.hci_family = AF_BLUETOOTH;
+
+ if (bt_aton(di->devname, &rp.r1.bdaddr)) {
+ if (!bt_devname(ha.hci_node, &rp.r1.bdaddr))
+ return (-1);
+ } else if (bt_dev2node(di->devname, ha.hci_node,
+ sizeof(ha.hci_node)) == NULL) {
+ errno = ENXIO;
+ return (-1);
+ }
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
+ if (s < 0)
+ return (-1);
+
+ rval = -1;
+
+ if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
+ connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0)
+ goto bad;
+ strlcpy(di->devname, ha.hci_node, sizeof(di->devname));
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STATE, &rp.r0, sizeof(rp.r0)) < 0)
+ goto bad;
+ di->state = rp.r0.state;
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &rp.r1, sizeof(rp.r1)) < 0)
+ goto bad;
+ bdaddr_copy(&di->bdaddr, &rp.r1.bdaddr);
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &rp.r2, sizeof(rp.r2)) < 0)
+ goto bad;
+ memcpy(di->features, rp.r2.features, sizeof(di->features));
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &rp.r3, sizeof(rp.r3)) < 0)
+ goto bad;
+ di->cmd_free = rp.r3.buffer.cmd_free;
+ di->sco_size = rp.r3.buffer.sco_size;
+ di->sco_pkts = rp.r3.buffer.sco_pkts;
+ di->sco_free = rp.r3.buffer.sco_free;
+ di->acl_size = rp.r3.buffer.acl_size;
+ di->acl_pkts = rp.r3.buffer.acl_pkts;
+ di->acl_free = rp.r3.buffer.acl_free;
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &rp.r4, sizeof(rp.r4)) < 0)
+ goto bad;
+ di->cmd_sent = rp.r4.stat.cmd_sent;
+ di->evnt_recv = rp.r4.stat.evnt_recv;
+ di->acl_recv = rp.r4.stat.acl_recv;
+ di->acl_sent = rp.r4.stat.acl_sent;
+ di->sco_recv = rp.r4.stat.sco_recv;
+ di->sco_sent = rp.r4.stat.sco_sent;
+ di->bytes_recv = rp.r4.stat.bytes_recv;
+ di->bytes_sent = rp.r4.stat.bytes_sent;
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK,
+ &rp.r5, sizeof(rp.r5)) < 0)
+ goto bad;
+ di->link_policy_info = rp.r5.policy_mask;
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK,
+ &rp.r6, sizeof(rp.r6)) < 0)
+ goto bad;
+ di->packet_type_info = rp.r6.packet_mask;
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH,
+ &rp.r7, sizeof(rp.r7)) < 0)
+ goto bad;
+ di->role_switch_info = rp.r7.role_switch;
+
+ if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &rp.r8, sizeof(rp.r8)) < 0)
+ goto bad;
+ di->debug = rp.r8.debug;
+
+ rval = 0;
+bad:
+ close(s);
+
+ return (rval);
+}
+
+int
+bt_devenum(bt_devenum_cb_t cb, void *arg)
+{
+ struct ng_btsocket_hci_raw_node_list_names rp;
+ struct bt_devinfo di;
+ struct sockaddr_hci ha;
+ int s, i, count;
+
+ rp.num_names = HCI_DEVMAX;
+ rp.names = (struct nodeinfo *) calloc(rp.num_names,
+ sizeof(struct nodeinfo));
+ if (rp.names == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ memset(&ha, 0, sizeof(ha));
+ ha.hci_len = sizeof(ha);
+ ha.hci_family = AF_BLUETOOTH;
+ ha.hci_node[0] = 'x';
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
+ if (s < 0) {
+ free(rp.names);
+
+ return (-1);
+ }
+
+ if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
+ connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
+ ioctl(s, SIOC_HCI_RAW_NODE_LIST_NAMES, &rp, sizeof(rp)) < 0) {
+ close(s);
+ free(rp.names);
+
+ return (-1);
+ }
+
+ for (count = 0, i = 0; i < rp.num_names; i ++) {
+ strlcpy(di.devname, rp.names[i].name, sizeof(di.devname));
+ if (bt_devinfo(&di) < 0)
+ continue;
+
+ count ++;
+
+ if (cb == NULL)
+ continue;
+
+ strlcpy(ha.hci_node, rp.names[i].name, sizeof(ha.hci_node));
+ if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
+ connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0)
+ continue;
+
+ if ((*cb)(s, &di, arg) > 0)
+ break;
+ }
+
+ close (s);
+ free(rp.names);
+
+ return (count);
+}
+
+static char *
+bt_dev2node(char const *devname, char *nodename, int nnlen)
+{
+ static char const * bt_dev_prefix[] = {
+ "btccc", /* 3Com Bluetooth PC-CARD */
+ "h4", /* UART/serial Bluetooth devices */
+ "ubt", /* Bluetooth USB devices */
+ NULL /* should be last */
+ };
+
+ static char _nodename[HCI_DEVNAME_SIZE];
+ char const **p;
+ char *ep;
+ int plen, unit;
+
+ if (nodename == NULL) {
+ nodename = _nodename;
+ nnlen = HCI_DEVNAME_SIZE;
+ }
+
+ for (p = bt_dev_prefix; *p != NULL; p ++) {
+ plen = strlen(*p);
+ if (strncmp(devname, *p, plen) != 0)
+ continue;
+
+ unit = strtoul(devname + plen, &ep, 10);
+ if (*ep != '\0' &&
+ strcmp(ep, "hci") != 0 &&
+ strcmp(ep, "l2cap") != 0)
+ return (NULL); /* can't make sense of device name */
+
+ snprintf(nodename, nnlen, "%s%uhci", *p, unit);
+
+ return (nodename);
+ }
+
+ return (NULL);
+}
+
OpenPOWER on IntegriCloud