libhci
Maksim Yevmenkin
maksim.yevmenkin at gmail.com
Fri Feb 13 17:17:55 PST 2009
Iain,
>> anyway, what would you suggest to use instead of dev_id? device name
>> (i.e. ubt0)? anything else? cant use bd_addr because (in freebsd at
>> least) device has to be "initialized" before bd_addr is known.
>
> for sure, a generic API would need to use the device name. Internally it
> can translate to whatever the local hardware control API uses.
>
>> i will take a look at ms api. but surely we have ability to send and
>> receive hci commands/events and enumerate all radios in the system in
>> addition to inquiry, dont you think?
>
> enumerating the radios is useful, yes, but having a function to set the
> afh_map or some other setting? I think that this is only required by the
> administrator program (hccontrol in your case) so why does it need to be
> in a shared library?
>
> In a way, its similar for the string functions. What program needs to be
> able to print the features list? Only a shell based admin tool in
> reality, even a graphical program might want to provide such a feature
> list in a different format anyway..
i kinda started to work on hci/bluetooth shims. please take a look at
the attached patch. this is basically to implement bt_devname() and
bt_devaddr() similar to netbsd and i also added bt_hci_devinfo() and
bt_hci_devenum() inspired by linux-bluez.
i also plan to add bt_hci_devinquiry() and possibly bt_hci_devreq(),
bt_hci_devsend() and bt_hci_devrecv(). the later 2 are to send command
and receive event only.
thanks,
max
-------------- next part --------------
Index: dev.c
===================================================================
--- dev.c (revision 0)
+++ dev.c (revision 0)
@@ -0,0 +1,93 @@
+/*
+ * 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_hci_devenum_cb_t bt_devaddr_match;
+
+int
+bt_devaddr(char const *devname, bdaddr_t *addr)
+{
+ struct bt_hci_devinfo di;
+
+ if (bt_hci_devinfo(devname, &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_hci_devenum(0, &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_hci_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);
+}
+
Index: hci.c
===================================================================
--- hci.c (revision 0)
+++ hci.c (revision 0)
@@ -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_hci_dev2node (char const *devname, char *nodename, int nnlen);
+
+int
+bt_hci_devinfo(char const *devname, struct bt_hci_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, success;
+
+ if (devname == NULL || di == NULL) {
+ errno = EINVAL;
+ return (0);
+ }
+
+ memset(&ha, 0, sizeof(ha));
+ ha.hci_len = sizeof(ha);
+ ha.hci_family = AF_BLUETOOTH;
+
+ if (bt_aton(devname, &rp.r1.bdaddr)) {
+ if (!bt_devname(ha.hci_node, &rp.r1.bdaddr))
+ return (0);
+ } else if (bt_hci_dev2node(devname, ha.hci_node,
+ sizeof(ha.hci_node)) == NULL) {
+ errno = ENXIO;
+ return (0);
+ }
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
+ if (s < 0)
+ return (0);
+
+ success = 0;
+
+ 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;
+
+ success = 1;
+bad:
+ close(s);
+
+ return (success);
+}
+
+int
+bt_hci_devenum(int limit, bt_hci_devenum_cb_t cb, void *arg)
+{
+ struct ng_btsocket_hci_raw_node_list_names rp;
+ struct bt_hci_devinfo di;
+ struct sockaddr_hci ha;
+ int s, i;
+
+ if (cb == NULL || limit < 0) {
+ errno = EINVAL;
+ return (0);
+ }
+
+ rp.num_names = (limit > 0)? limit : 16; /* XXX why 16?? */
+ rp.names = (struct nodeinfo *) calloc(rp.num_names,
+ sizeof(struct nodeinfo));
+ if (rp.names == NULL) {
+ errno = ENOMEM;
+ return (0);
+ }
+
+ 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 (0);
+ }
+
+ 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 (0);
+ }
+
+ for (i = 0; i < rp.num_names; i ++) {
+ if (bt_hci_devinfo(rp.names[i].name, &di) < 0)
+ 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 (1);
+}
+
+static char *
+bt_hci_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);
+}
+
Index: bluetooth.3
===================================================================
--- bluetooth.3 (revision 188108)
+++ bluetooth.3 (working copy)
@@ -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_hci_devenum_cb_t) "int s" "struct bt_hci_devinfo const *di" "void *arg"
+.Ft int
+.Fn bt_hci_devinfo "char const *devname" "struct bt_hci_devinfo *di"
+.Ft int
+.Fn bt_hci_devenum "int limit" "bt_hci_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,113 @@
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_hci_devinfo
+function populates prodivded
+.Vt bt_hci_devinfo
+structure with the information about Bluetooth device
+.Fa devname .
+The function returns 1 when successful otherwise 0.
+The
+.Vt bt_hci_devinfo
+structure is defined as follows
+.Bd -literal -offset indent
+struct bt_hci_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 */
+ uint32_t link_policy_info;
+ uint32_t packet_type_info;
+ uint32_t role_switch_info;
+ uint32_t debug;
+};
+.Ed
+.Pp
+The
+.Fn bt_hci_devenum
+function enumerates up to
+.Fa limit
+Bluetooth devices present in the system.
+If passed
+.Fa limit
+is zero, the internal default limit will be used.
+For every device found,
+the function will call provided
+.Fa cb
+callback function which should be of
+.Vt bt_hci_devenum_cb_t
+type.
+The callback function is passed a connected
+.Dv HCI
+socket
+.Fa s ,
+fully populated
+.Vt bt_hci_devinfo
+structure
+.Fa di
+and
+.Fa arg
+argument provided to the
+.Fn bt_hci_devenum .
+The callback function can stop enumeration by returning a value of less
+or equal to zero.
+The
+.Fn bt_hci_devenum
+uses the same socket for the duration of enumeration.
+The function guarantees that the socket,
+passed to the callback function,
+will be bound and connected to the Bluetooth device being enumerated.
+The function returns 1 when enumeration was successful otherwise 0.
+.Pp
+The
.Fn bdaddr_same ,
.Fn bdaddr_any
and
@@ -287,7 +404,8 @@
.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
Index: bluetooth.c
===================================================================
--- bluetooth.c (revision 188108)
+++ bluetooth.c (working copy)
@@ -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
Index: bluetooth.h
===================================================================
--- bluetooth.h (revision 188108)
+++ bluetooth.h (working copy)
@@ -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,60 @@
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_DEVNAME_SIZE NG_NODESIZ
+#define HCI_DEVFEATURES_SIZE NG_HCI_FEATURES_SIZE
+
+struct bt_hci_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 */
+ uint32_t link_policy_info;
+ uint32_t packet_type_info;
+ uint32_t role_switch_info;
+ uint32_t debug;
+};
+
+typedef int (bt_hci_devenum_cb_t)(int,struct bt_hci_devinfo const *,void *);
+
+int bt_hci_devinfo (char const *devname, struct bt_hci_devinfo *di);
+int bt_hci_devenum (int limit, bt_hci_devenum_cb_t *cb, void *arg);
+
/*
* bdaddr utility functions (from NetBSD)
*/
Index: Makefile
===================================================================
--- Makefile (revision 188108)
+++ Makefile (working copy)
@@ -7,9 +7,11 @@
WARNS?= 2
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys
+DEBUG_FLAGS= -g
+
SHLIB_MAJOR= 3
-SRCS= bluetooth.c
+SRCS= bluetooth.c dev.c hci.c
INCS= bluetooth.h
MLINKS+= bluetooth.3 bt_gethostbyname.3
@@ -27,6 +29,12 @@
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_hci_devinfo.3
+MLINKS+= bluetooth.3 bt_hci_devenum.3
+
MLINKS+= bluetooth.3 bdaddr_same.3
MLINKS+= bluetooth.3 bdaddr_any.3
MLINKS+= bluetooth.3 bdaddr_copy.3
More information about the freebsd-bluetooth
mailing list