svn commit: r189462 - head/lib/libbluetooth

Maksim Yevmenkin emax at FreeBSD.org
Fri Mar 6 15:30:08 PST 2009


Author: emax
Date: Fri Mar  6 23:30:07 2009
New Revision: 189462
URL: http://svn.freebsd.org/changeset/base/189462

Log:
  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

Added:
  head/lib/libbluetooth/dev.c   (contents, props changed)
  head/lib/libbluetooth/hci.c   (contents, props changed)
Modified:
  head/lib/libbluetooth/Makefile
  head/lib/libbluetooth/bluetooth.3
  head/lib/libbluetooth/bluetooth.c
  head/lib/libbluetooth/bluetooth.h

Modified: head/lib/libbluetooth/Makefile
==============================================================================
--- head/lib/libbluetooth/Makefile	Fri Mar  6 23:29:00 2009	(r189461)
+++ head/lib/libbluetooth/Makefile	Fri Mar  6 23:30:07 2009	(r189462)
@@ -9,7 +9,7 @@ CFLAGS+=	-I${.CURDIR} -I${.CURDIR}/../..
 
 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

Modified: head/lib/libbluetooth/bluetooth.3
==============================================================================
--- head/lib/libbluetooth/bluetooth.3	Fri Mar  6 23:29:00 2009	(r189461)
+++ head/lib/libbluetooth/bluetooth.3	Fri Mar  6 23:30:07 2009	(r189462)
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin at yahoo.com>
+.\" Copyright (c) 2003-2009 Maksim Yevmenkin <m_evmenkin at 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 pr
 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 at yahoo.com
 .Sh BUGS

Modified: head/lib/libbluetooth/bluetooth.c
==============================================================================
--- head/lib/libbluetooth/bluetooth.c	Fri Mar  6 23:29:00 2009	(r189461)
+++ head/lib/libbluetooth/bluetooth.c	Fri Mar  6 23:30:07 2009	(r189462)
@@ -1,7 +1,9 @@
 /*
  * bluetooth.c
- *
- * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin at yahoo.com>
+ */
+
+/*-
+ * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin at yahoo.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without

Modified: head/lib/libbluetooth/bluetooth.h
==============================================================================
--- head/lib/libbluetooth/bluetooth.h	Fri Mar  6 23:29:00 2009	(r189461)
+++ head/lib/libbluetooth/bluetooth.h	Fri Mar  6 23:30:07 2009	(r189462)
@@ -1,7 +1,9 @@
 /*
  * bluetooth.h
- *
- * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin at yahoo.com>
+ */
+
+/*-
+ * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin at 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      (v
 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)
  */

Added: head/lib/libbluetooth/dev.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libbluetooth/dev.c	Fri Mar  6 23:30:07 2009	(r189462)
@@ -0,0 +1,95 @@
+/*
+ * dev.c
+ */
+
+/*-
+ * Copyright (c) 2009 Maksim Yevmenkin <m_evmenkin at 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);
+}
+

Added: head/lib/libbluetooth/hci.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libbluetooth/hci.c	Fri Mar  6 23:30:07 2009	(r189462)
@@ -0,0 +1,246 @@
+/*
+ * hci.c
+ */
+
+/*-
+ * Copyright (c) 2009 Maksim Yevmenkin <m_evmenkin at 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);
+}
+


More information about the svn-src-all mailing list