summaryrefslogtreecommitdiff
path: root/lib/libbluetooth
diff options
context:
space:
mode:
authorgdamore <gdamore@NetBSD.org>2006-06-19 15:44:33 +0000
committergdamore <gdamore@NetBSD.org>2006-06-19 15:44:33 +0000
commita5c89047c05c5d03bdf7663f4585fb0bed64a924 (patch)
tree69f226b62ddfe2f9187d03b1f1f79cff67264727 /lib/libbluetooth
parent052a8ad2ad25caabbef9124f0a7c9f0980e20beb (diff)
Initial import of bluetooth stack on behalf of Iain Hibbert. (plunky@,
NetBSD Foundation Membership still pending.) This stack was written by Iain under sponsorship from Itronix Inc. The stack includes support for rfcomm networking (networking via your bluetooth enabled cell phone), hid devices (keyboards/mice), and headsets. Drivers for both PCMCIA and USB bluetooth controllers are included.
Diffstat (limited to 'lib/libbluetooth')
-rw-r--r--lib/libbluetooth/Makefile42
-rw-r--r--lib/libbluetooth/bluetooth.3371
-rw-r--r--lib/libbluetooth/bluetooth.c373
-rw-r--r--lib/libbluetooth/bluetooth.conf.5233
-rw-r--r--lib/libbluetooth/bluetooth.h123
-rw-r--r--lib/libbluetooth/devaddr.c106
-rw-r--r--lib/libbluetooth/lexer.l158
-rw-r--r--lib/libbluetooth/parser.y612
-rw-r--r--lib/libbluetooth/shlib_version5
9 files changed, 2023 insertions, 0 deletions
diff --git a/lib/libbluetooth/Makefile b/lib/libbluetooth/Makefile
new file mode 100644
index 00000000000..c5333ce5d35
--- /dev/null
+++ b/lib/libbluetooth/Makefile
@@ -0,0 +1,42 @@
+# $NetBSD: Makefile,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+
+LIB= bluetooth
+
+SRCS= bluetooth.c devaddr.c lexer.l parser.y
+MAN= bluetooth.3 bluetooth.conf.5
+
+CPPFLAGS+= -I${.CURDIR}
+
+LPREFIX= _btyy
+YPREFIX= _btyy
+YHEADER= 1
+
+INCS= bluetooth.h
+INCSDIR= /usr/include
+
+MLINKS+= bluetooth.3 bt_gethostbyname.3
+MLINKS+= bluetooth.3 bt_gethostbyaddr.3
+MLINKS+= bluetooth.3 bt_gethostent.3
+MLINKS+= bluetooth.3 bt_sethostent.3
+MLINKS+= bluetooth.3 bt_endhostent.3
+
+MLINKS+= bluetooth.3 bt_getprotobyname.3
+MLINKS+= bluetooth.3 bt_getprotobynumber.3
+MLINKS+= bluetooth.3 bt_getprotoent.3
+MLINKS+= bluetooth.3 bt_setprotoent.3
+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_openconfig.3
+MLINKS+= bluetooth.3 bt_getconfig.3
+MLINKS+= bluetooth.3 bt_freeconfig.3
+MLINKS+= bluetooth.3 bt_eachconfig.3
+MLINKS+= bluetooth.3 bt_closeconfig.3
+MLINKS+= bluetooth.3 bt_printconfig.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libbluetooth/bluetooth.3 b/lib/libbluetooth/bluetooth.3
new file mode 100644
index 00000000000..cb5a92732b4
--- /dev/null
+++ b/lib/libbluetooth/bluetooth.3
@@ -0,0 +1,371 @@
+.\" $NetBSD: bluetooth.3,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+.\"
+.\" Copyright (c) 2003 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.
+.\"
+.\" $Id: bluetooth.3,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+.\" $FreeBSD: src/lib/libbluetooth/bluetooth.3,v 1.7 2005/01/21 10:26:11 ru Exp $
+.\"
+.Dd May 7, 2003
+.Dt BLUETOOTH 3
+.Os
+.Sh NAME
+.Nm bt_gethostbyname ,
+.Nm bt_gethostbyaddr ,
+.Nm bt_gethostent ,
+.Nm bt_sethostent ,
+.Nm bt_endhostent ,
+.Nm bt_getprotobyname ,
+.Nm bt_getprotobynumber ,
+.Nm bt_getprotoent ,
+.Nm bt_setprotoent ,
+.Nm bt_endprotoent ,
+.Nm bt_aton ,
+.Nm bt_ntoa ,
+.Nm bt_devaddr ,
+.Nm bt_devname ,
+.Nm bt_openconfig ,
+.Nm bt_getconfig ,
+.Nm bt_freeconfig ,
+.Nm bt_eachconfig ,
+.Nm bt_closeconfig ,
+.Nm bt_printconfig
+.Nd Bluetooth routines
+.Sh LIBRARY
+.Lb libbluetooth
+.Sh SYNOPSIS
+.In bluetooth.h
+.Ft struct hostent *
+.Fn bt_gethostbyname "const char *name"
+.Ft struct hostent *
+.Fn bt_gethostbyaddr "const char *addr" "int len" "int type"
+.Ft struct hostent *
+.Fn bt_gethostent void
+.Ft void
+.Fn bt_sethostent "int stayopen"
+.Ft void
+.Fn bt_endhostent void
+.Ft struct protoent *
+.Fn bt_getprotobyname "const char *name"
+.Ft struct protoent *
+.Fn bt_getprotobynumber "int proto"
+.Ft struct protoent *
+.Fn bt_getprotoent void
+.Ft void
+.Fn bt_setprotoent "int stayopen"
+.Ft void
+.Fn bt_endprotoent void
+.Ft int
+.Fn bt_aton "const char *str" "bdaddr_t *ba"
+.Ft const char *
+.Fn bt_ntoa "const bdaddr_t *ba" "char *str"
+.Ft int
+.Fn bt_devaddr "const char *name" "bdaddr_t *addr"
+.Ft int
+.Fn bt_devname "char *name" "const bdaddr_t *addr"
+.Ft bt_handle_t
+.Fn bt_openconfig "const char *name"
+.Ft bt_cfgentry_t
+.Fn bt_getconfig "bt_handle_t handle" "const bdaddr_t *ba"
+.Ft int
+.Fn bt_eachconfig "bt_handle_t handle" "void (*func)(bt_cfgentry_t *, void *)" "void *arg"
+.Ft void
+.Fn bt_freeconfig "bt_cfgentry_t *cfg"
+.Ft int
+.Fn bt_closeconfig "bt_handle_t handle"
+.Ft int
+.Fn bt_printconfig "FILE *fp" "bt_cfgentry_t *cfg"
+.Sh DESCRIPTION
+The
+.Fn bt_gethostent ,
+.Fn bt_gethostbyname
+and
+.Fn bt_gethostbyaddr
+functions
+each return a pointer to an object with the
+.Vt hostent
+structure describing a Bluetooth host
+referenced by name or by address, respectively.
+.Pp
+The
+.Fa name
+argument passed to
+.Fn bt_gethostbyname
+should point to a
+.Dv NUL Ns -terminated
+hostname.
+The
+.Fa addr
+argument passed to
+.Fn bt_gethostbyaddr
+should point to an address which is
+.Fa len
+bytes long,
+in binary form
+(i.e., not a Bluetooth BD_ADDR in human readable
+.Tn ASCII
+form).
+The
+.Fa type
+argument specifies the address family of this address and must be set to
+.Dv AF_BLUETOOTH .
+.Pp
+The structure returned contains the information obtained from a line in
+.Pa /etc/bluetooth/hosts
+file.
+.Pp
+The
+.Fn bt_sethostent
+function controls whether
+.Pa /etc/bluetooth/hosts
+file should stay open after each call to
+.Fn bt_gethostbyname
+or
+.Fn bt_gethostbyaddr .
+If the
+.Fa stayopen
+flag is non-zero, the file will not be closed.
+.Pp
+The
+.Fn bt_endhostent
+function closes the
+.Pa /etc/bluetooth/hosts
+file.
+.Pp
+The
+.Fn bt_getprotoent ,
+.Fn bt_getprotobyname
+and
+.Fn bt_getprotobynumber
+functions each return a pointer to an object with the
+.Vt protoent
+structure describing a Bluetooth Protocol Service Multiplexor referenced
+by name or number, respectively.
+.Pp
+The
+.Fa name
+argument passed to
+.Fn bt_getprotobyname
+should point to a
+.Dv NUL Ns -terminated
+Bluetooth Protocol Service Multiplexor name.
+The
+.Fa proto
+argument passed to
+.Fn bt_getprotobynumber
+should have numeric value of the desired Bluetooth Protocol Service Multiplexor.
+.Pp
+The structure returned contains the information obtained from a line in
+.Pa /etc/bluetooth/protocols
+file.
+.Pp
+The
+.Fn bt_setprotoent
+function controls whether
+.Pa /etc/bluetooth/protocols
+file should stay open after each call to
+.Fn bt_getprotobyname
+or
+.Fn bt_getprotobynumber .
+If the
+.Fa stayopen
+flag is non-zero, the file will not be closed.
+.Pp
+The
+.Fn bt_endprotoent
+function closes the
+.Pa /etc/bluetooth/protocols
+file.
+.Pp
+The
+.Fn bt_aton
+routine interprets the specified character string as a Bluetooth address,
+placing the address into the structure provided.
+It returns 1 if the string was successfully interpreted,
+or 0 if the string is invalid.
+.Pp
+The routine
+.Fn bt_ntoa
+takes a Bluetooth address and places an
+.Tn ASCII
+string representing the address into the buffer provided.
+It is up to the caller to ensure that provided buffer has enough space.
+If no buffer was provided then an internal static buffer will be used.
+.Pp
+The
+.Fn bt_devaddr
+function interprets the specified character string as the
+address or device name of a Bluetooth device on the local system, and
+places the device address in the structure provided, if any.
+It 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.
+It returns 1 when the device was found, otherwise 0.
+.Pp
+The
+.Fn bt_openconfig ,
+.Fn bt_getconfig ,
+.Fn bt_eachconfig ,
+and
+.Fn bt_closeconfig
+functions can be used to extract configuration entries from files in the
+.Xr bluetooth.conf 5
+file format. If
+.Dv NULL
+is specified as the file name to
+.Fn bt_openconfig ,
+the default file name of
+.Pa /etc/bluetooth/bluetooth.conf
+will be used.
+.Fn bt_getconfig
+will scan the config file for a matching BD_ADDR and return a
+pointer to a dynamically allocated
+.Ar bt_cfgentry_t
+structure which must be freed with
+.Fn bt_freeconfig .
+The
+.Fn bt_eachconfig
+function can be used to iterate through all entries in the config file,
+with each config entry being passed to the given function in turn, then
+freed automatically.
+.Pp
+The
+.Fn bt_printconfig
+function will print a config entry to the file pointer
+in a format compatible with reading it later.
+.Sh FILES
+.Bl -tag -width ".Pa /etc/bluetooth/hosts" -compact
+.It Pa /etc/bluetooth/bluetooth.conf
+.It Pa /etc/bluetooth/hosts
+.It Pa /etc/bluetooth/protocols
+.El
+.Sh EXAMPLES
+Print out the hostname associated with a specific BD_ADDR:
+.Bd -literal -offset indent
+const char *bdstr = "00:01:02:03:04:05";
+bdaddr_t bd;
+struct hostent *hp;
+
+if (!bt_aton(bdstr, &bd))
+ errx(1, "can't parse BD_ADDR %s", bdstr);
+
+if ((hp = bt_gethostbyaddr((const char *)&bd,
+ sizeof(bd), AF_BLUETOOTH)) == NULL)
+ errx(1, "no name associated with %s", bdstr);
+
+printf("name associated with %s is %s\en", bdstr, hp->h_name);
+.Ed
+.Sh DIAGNOSTICS
+Error return status from
+.Fn bt_gethostent ,
+.Fn bt_gethostbyname
+and
+.Fn bt_gethostbyaddr
+is indicated by return of a
+.Dv NULL
+pointer.
+The external integer
+.Va h_errno
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The routine
+.Xr herror 3
+can be used to print an error message describing the failure.
+If its argument
+.Fa string
+is
+.Pf non- Dv NULL ,
+it is printed, followed by a colon and a space.
+The error message is printed with a trailing newline.
+.Pp
+The variable
+.Va h_errno
+can have the following values:
+.Bl -tag -width ".Dv HOST_NOT_FOUND"
+.It Dv HOST_NOT_FOUND
+No such host is known.
+.It Dv NO_RECOVERY
+Some unexpected server failure was encountered.
+This is a non-recoverable error.
+.El
+.Pp
+The
+.Fn bt_getprotoent ,
+.Fn bt_getprotobyname
+and
+.Fn bt_getprotobynumber
+return
+.Dv NULL
+on EOF or error.
+.Sh SEE ALSO
+.Xr bluetooth.conf 5 ,
+.Xr gethostbyaddr 3 ,
+.Xr gethostbyname 3 ,
+.Xr getprotobyname 3 ,
+.Xr getprotobynumber 3 ,
+.Xr herror 3 ,
+.Xr inet_aton 3 ,
+.Xr inet_ntoa 3
+.Sh CAVEAT
+The
+.Fn bt_gethostent
+function reads the next line of
+.Pa /etc/bluetooth/hosts ,
+opening the file if necessary.
+.Pp
+The
+.Fn bt_sethostent
+function opens and/or rewinds the
+.Pa /etc/bluetooth/hosts
+file.
+.Pp
+The
+.Fn bt_getprotoent
+function reads the next line of
+.Pa /etc/bluetooth/protocols ,
+opening the file if necessary.
+.Pp
+The
+.Fn bt_setprotoent
+function opens and/or rewinds the
+.Pa /etc/bluetooth/protocols
+file.
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
+.An Iain Hibbert
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+.Sh HISTORY
+.Nm libbluetooth
+first appeard in
+.Fx
+was ported to
+.Nx 4.0
+and extended by
+.An Iain Hibbert
+for Itronix, Inc.
diff --git a/lib/libbluetooth/bluetooth.c b/lib/libbluetooth/bluetooth.c
new file mode 100644
index 00000000000..a5991337837
--- /dev/null
+++ b/lib/libbluetooth/bluetooth.c
@@ -0,0 +1,373 @@
+/* $NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
+
+/*
+ * bluetooth.c
+ *
+ * Copyright (c) 2001-2003 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.
+ *
+ * $Id: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+ * $FreeBSD: src/lib/libbluetooth/bluetooth.c,v 1.2 2004/03/05 08:10:17 markm Exp $
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $");
+
+#include <bluetooth.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _PATH_BT_HOSTS "/etc/bluetooth/hosts"
+#define _PATH_BT_PROTOCOLS "/etc/bluetooth/protocols"
+#define MAXALIASES 35
+
+static FILE *hostf = NULL;
+static int host_stayopen = 0;
+static struct hostent host;
+static bdaddr_t host_addr;
+static char *host_addr_ptrs[2];
+static char *host_aliases[MAXALIASES];
+
+static FILE *protof = NULL;
+static int proto_stayopen = 0;
+static struct protoent proto;
+static char *proto_aliases[MAXALIASES];
+
+static char buf[BUFSIZ + 1];
+
+static int bt_hex_byte (char const *str);
+static int bt_hex_nibble (char nibble);
+
+struct hostent *
+bt_gethostbyname(char const *name)
+{
+ struct hostent *p;
+ char **cp;
+
+ bt_sethostent(host_stayopen);
+ while ((p = bt_gethostent()) != NULL) {
+ if (strcasecmp(p->h_name, name) == 0)
+ break;
+ for (cp = p->h_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ bt_endhostent();
+
+ return (p);
+}
+
+struct hostent *
+bt_gethostbyaddr(char const *addr, socklen_t len, int type)
+{
+ struct hostent *p;
+
+ if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+
+ bt_sethostent(host_stayopen);
+ while ((p = bt_gethostent()) != NULL)
+ if (p->h_addrtype == type && memcmp(p->h_addr, addr, len) == 0)
+ break;
+ bt_endhostent();
+
+ return (p);
+}
+
+struct hostent *
+bt_gethostent(void)
+{
+ char *p, *cp, **q;
+
+ if (hostf == NULL)
+ hostf = fopen(_PATH_BT_HOSTS, "r");
+
+ if (hostf == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+again:
+ if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ if (*p == '#')
+ goto again;
+ if ((cp = strpbrk(p, "#\n")) == NULL)
+ goto again;
+ *cp = 0;
+ if ((cp = strpbrk(p, " \t")) == NULL)
+ goto again;
+ *cp++ = 0;
+ if (bt_aton(p, &host_addr) == 0)
+ goto again;
+ host_addr_ptrs[0] = (char *) &host_addr;
+ host_addr_ptrs[1] = NULL;
+ host.h_addr_list = host_addr_ptrs;
+ host.h_length = sizeof(host_addr);
+ host.h_addrtype = AF_BLUETOOTH;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ host.h_name = cp;
+ q = host.h_aliases = host_aliases;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = 0;
+ while (cp != NULL && *cp != 0) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = 0;
+ }
+ *q = NULL;
+ h_errno = NETDB_SUCCESS;
+
+ return (&host);
+}
+
+void
+bt_sethostent(int stayopen)
+{
+ if (hostf == NULL)
+ hostf = fopen(_PATH_BT_HOSTS, "r");
+ else
+ rewind(hostf);
+
+ host_stayopen = stayopen;
+}
+
+void
+bt_endhostent(void)
+{
+ if (hostf != NULL && host_stayopen == 0) {
+ (void) fclose(hostf);
+ hostf = NULL;
+ }
+}
+
+struct protoent *
+bt_getprotobyname(char const *name)
+{
+ struct protoent *p;
+ char **cp;
+
+ bt_setprotoent(proto_stayopen);
+ while ((p = bt_getprotoent()) != NULL) {
+ if (strcmp(p->p_name, name) == 0)
+ break;
+ for (cp = p->p_aliases; *cp != 0; cp++)
+ if (strcmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ bt_endprotoent();
+
+ return (p);
+}
+
+struct protoent *
+bt_getprotobynumber(int num)
+{
+ struct protoent *p;
+
+ bt_setprotoent(proto_stayopen);
+ while ((p = bt_getprotoent()) != NULL)
+ if (p->p_proto == num)
+ break;
+ bt_endprotoent();
+
+ return (p);
+}
+
+struct protoent *
+bt_getprotoent(void)
+{
+ char *p, *cp, **q;
+
+ if (protof == NULL)
+ protof = fopen(_PATH_BT_PROTOCOLS, "r");
+
+ if (protof == NULL)
+ return (NULL);
+again:
+ if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ if ((cp = strpbrk(p, "#\n")) == NULL)
+ goto again;
+ *cp = '\0';
+ proto.p_name = p;
+ if ((cp = strpbrk(p, " \t")) == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ proto.p_proto = (int)strtol(cp, NULL, 0);
+ q = proto.p_aliases = proto_aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp != NULL && *cp != 0) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &proto_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+
+ return (&proto);
+}
+
+void
+bt_setprotoent(int stayopen)
+{
+ if (protof == NULL)
+ protof = fopen(_PATH_BT_PROTOCOLS, "r");
+ else
+ rewind(protof);
+
+ proto_stayopen = stayopen;
+}
+
+void
+bt_endprotoent(void)
+{
+ if (protof != NULL) {
+ (void) fclose(protof);
+ protof = NULL;
+ }
+}
+
+char const *
+bt_ntoa(bdaddr_t const *ba, char *str)
+{
+ static char buffer[24];
+
+ if (str == NULL)
+ str = buffer;
+
+ sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+ ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
+
+ return (str);
+}
+
+int
+bt_aton(char const *str, bdaddr_t *ba)
+{
+ int i, b;
+ char *end = NULL;
+
+ memset(ba, 0, sizeof(*ba));
+
+ for (i = 5, end = strchr(str, ':');
+ i > 0 && *str != '\0' && end != NULL;
+ i --, str = end + 1, end = strchr(str, ':')) {
+ switch (end - str) {
+ case 1:
+ b = bt_hex_nibble(str[0]);
+ break;
+
+ case 2:
+ b = bt_hex_byte(str);
+ break;
+
+ default:
+ b = -1;
+ break;
+ }
+
+ if (b < 0)
+ return (0);
+
+ ba->b[i] = b;
+ }
+
+ if (i != 0 || end != NULL || *str == 0)
+ return (0);
+
+ switch (strlen(str)) {
+ case 1:
+ b = bt_hex_nibble(str[0]);
+ break;
+
+ case 2:
+ b = bt_hex_byte(str);
+ break;
+
+ default:
+ b = -1;
+ break;
+ }
+
+ if (b < 0)
+ return (0);
+
+ ba->b[i] = b;
+
+ return (1);
+}
+
+static int
+bt_hex_byte(char const *str)
+{
+ int n1, n2;
+
+ if ((n1 = bt_hex_nibble(str[0])) < 0)
+ return (-1);
+
+ if ((n2 = bt_hex_nibble(str[1])) < 0)
+ return (-1);
+
+ return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
+}
+
+static int
+bt_hex_nibble(char nibble)
+{
+ if ('0' <= nibble && nibble <= '9')
+ return (nibble - '0');
+
+ if ('a' <= nibble && nibble <= 'f')
+ return (nibble - 'a' + 0xa);
+
+ if ('A' <= nibble && nibble <= 'F')
+ return (nibble - 'A' + 0xa);
+
+ return (-1);
+}
diff --git a/lib/libbluetooth/bluetooth.conf.5 b/lib/libbluetooth/bluetooth.conf.5
new file mode 100644
index 00000000000..2ec0d877246
--- /dev/null
+++ b/lib/libbluetooth/bluetooth.conf.5
@@ -0,0 +1,233 @@
+.\" $NetBSD: bluetooth.conf.5,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+.\"
+.\" Copyright (c) 2006 Itronix Inc.
+.\" 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.
+.\" 3. The name of Itronix Inc. may not be used to endorse
+.\" or promote products derived from this software without specific
+.\" prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``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 ITRONIX INC. 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.
+.\"
+.\"
+.\" Copyright (c) 2001-2002 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.
+.\"
+.Dd March 30, 2006
+.Dt BLUETOOTH.CONF 5
+.Os
+.Sh NAME
+.Nm bluetooth.conf
+.Nd
+Bluetooth remote devices configuration file.
+.Sh DESCRIPTION
+The
+.Nm
+file is the default configuration file used by the
+.Xr bthcid 8 ,
+and
+.Xr btcontrol 8
+programs.
+.Pp
+The
+.Nm
+file is a free-form
+.Tn ASCII
+text file.
+It is parsed by the recursive-descent parser built into the
+.Xr bluetooth 3
+library.
+The file may contain extra tabs and newlines for formatting purposes.
+Keywords in the file are case-sensitive.
+Comments may be placed anywhere within the file (except within quotes).
+Comments begin with the
+.Ql #
+character and end at the end of the line.
+.Sh FILE FORMAT
+The
+.Nm
+file consists of a list of
+.Cm device
+entries.
+Each remote Bluetooth device is identified by its unique BD_ADDR.
+Each
+.Cm device
+entry defines options and information for a remote Bluetooth device.
+.Pp
+The
+.Cm device
+entry
+.Pp
+.Cm device
+{
+.Cm option Ar argument ;
+.Oo
+.Cm option Ar argument ;
+.Oc
+}
+.Pp
+The supported options and arguments are as follows:
+.Bl -tag -width indent
+.It Cm bdaddr Ar BD_ADDR
+This required value is the Bluetooth Device Address of the remote device and
+can be obtained by placing the device into Discoverable mode and using the
+.Xr btconfig 8
+program
+.Pa Inquiry
+command.
+.It Cm type Ar type
+This optional entry will indicate to the
+.Xr btcontrol 8
+program how to attach this device to the system.
+.Ar type
+can be one of:
+.Pp
+.Bl -tag -compact
+.It hid
+Human Interface Device
+.It hset
+Audio Headset
+.El
+.It Cm name Ar device_name
+Specify user friendly name for the entry.
+Name is a string in straight double quotes.
+.It Cm key Ar link_key
+Specify a link key for the entry.
+Link key is hexadecimal string up to 32 characters in length starting with
+.Ql 0x .
+.Pp
+It is not generally necessary to store link keys in the
+.Pa /etc/bluetooth/bluetooth.conf
+file as the
+.Xr bthcid 8
+daemon will keep them elsewhere.
+.It Cm pin Ar PIN_code
+Specify PIN code for the entry.
+PIN code is a string up to 16 characters in length in straight double quotes.
+If no PIN is given, and the baseband connection requires authentication, the
+.Xr bthcid 8
+daemon will attempt to contact clients for a PIN before sending a negative
+response.
+.Pp
+It is not generally necessary to store PINs in the
+.Pa /etc/bluetooth/bluetooth.conf
+file as the
+.Xr btpin 1
+utility can be used to register PINs with the
+.Xr bthcid 8
+daemon prior to pairing a device.
+.It Cm control_channel Ar channel
+This RFCOMM channel number used to contact the HSET device.
+.It Cm control_psm Ar psm
+The PSM value that an HID device uses for control messages.
+.It Cm interrupt_psm Ar psm
+The PSM value that an HID device uses for interrupt messages.
+.It Cm reconnect_initiate Ar bool
+This should be 'true' if the HID device normally initiates reconnection after
+link loss, and if not set (or set to 'false') will cause the
+.Xr bthidev 4
+driver to initiate connections.
+.It Cm battery_power Ar bool
+This should be 'true' if the HID device runs from battery power.
+.It Cm normally_connectable Ar bool
+This should be 'true' if the HID device is normally available for incoming
+connections.
+.It Cm hid_descriptor
+This block of hexadecimal bytes is a description of HID device capabilities
+as according to the USB HID specifications, and can be displayed in
+human readable form using the
+.Xr btcontrol 8
+program
+.Pa Parse
+command.
+.El
+.Sh EXAMPLES
+A sample
+.Nm
+file:
+.Bd -literal
+# Ericsson T68 phone
+device {
+ bdaddr 00:80:37:5e:4d:d4;
+ name "Ericsson T68 phone";
+ pin "0000"; # PIN code
+}
+
+# example HID
+device {
+ bdaddr 00:50:f2:e5:68:84;
+ attach hid;
+ name "Example HID";
+ key 0x00112233445566778899aabbccddeeff;
+ control_psm 0x0011;
+ interrupt_psm 0x0013;
+ reconnect_initiate false;
+ normally_connectable false;
+ hid_descriptor {
+ 0x05 0x01 0x09 0x02 0xa1 0x01 0x85 0x02
+ 0x09 0x01 0xa1 0x00 0x05 0x09 0x19 0x01
+ 0x29 0x05 0x15 0x00 0x25 0x01 0x75 0x01
+ 0x95 0x05 0x81 0x02 0x75 0x03 0x95 0x01
+ 0x81 0x01 0x05 0x01 0x09 0x30 0x09 0x31
+ 0x09 0x38 0x15 0x81 0x25 0x7f 0x75 0x08
+ 0x95 0x03 0x81 0x06 0xc0 0xc0 0x05 0x0c
+ 0x09 0x01 0xa1 0x01 0x85 0x03 0x05 0x01
+ 0x09 0x02 0xa1 0x02 0x06 0x00 0xff 0x15
+ 0x00 0x25 0x03 0x95 0x01 0x75 0x02 0x0a
+ 0x01 0xfe 0x81 0x02 0x75 0x06 0x81 0x01
+ 0xc0 0xc0
+ };
+}
+.Ed
+.Sh FILES
+.Bl -tag -compact
+.It Pa /etc/bluetooth/bluetooth.conf
+.El
+.Sh SEE ALSO
+.Xr btpin 1 ,
+.Xr bluetooth 3 ,
+.Xr bthcid 8 ,
+.Xr btcontrol 8
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
+.An Iain Hibbert
+for Itronix, Inc.
diff --git a/lib/libbluetooth/bluetooth.h b/lib/libbluetooth/bluetooth.h
new file mode 100644
index 00000000000..76a2a86ecaf
--- /dev/null
+++ b/lib/libbluetooth/bluetooth.h
@@ -0,0 +1,123 @@
+/* $NetBSD: bluetooth.h,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
+
+/*
+ * bluetooth.h
+ *
+ * Copyright (c) 2001-2003 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.
+ *
+ * $Id: bluetooth.h,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+ * $FreeBSD: src/lib/libbluetooth/bluetooth.h,v 1.2 2005/03/17 21:39:44 emax Exp $
+ */
+
+#ifndef _BLUETOOTH_H_
+#define _BLUETOOTH_H_
+
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netbt/bluetooth.h>
+#include <netbt/hci.h>
+#include <netbt/l2cap.h>
+#include <stdio.h>
+
+/*
+ * Bluetooth remote device config information.
+ *
+ * Entries will be empty if no value was specified
+ * in the configuration file.
+ */
+typedef struct {
+ bdaddr_t bdaddr; /* device address */
+ int type; /* device type */
+ char *name; /* NUL terminated string */
+ uint8_t *pin; /* uint8_t[HCI_PIN_SIZE] */
+ uint8_t *key; /* uint8_t[HCI_KEY_SIZE] */
+ uint8_t *hid_descriptor; /* uint8_t[hid_length] */
+ int hid_length;
+ uint16_t control_psm;
+ uint8_t control_channel;
+ uint16_t interrupt_psm;
+ uint8_t reconnect_initiate;
+ uint8_t normally_connectable;
+ uint8_t battery_power;
+} bt_cfgentry_t;
+
+__BEGIN_DECLS
+
+/*
+ * Interface to the outside world
+ */
+
+struct hostent * bt_gethostbyname (char const *);
+struct hostent * bt_gethostbyaddr (char const *, socklen_t, int);
+struct hostent * bt_gethostent (void);
+void bt_sethostent (int);
+void bt_endhostent (void);
+
+struct protoent * bt_getprotobyname (char const *);
+struct protoent * bt_getprotobynumber (int);
+struct protoent * bt_getprotoent (void);
+void bt_setprotoent (int);
+void bt_endprotoent (void);
+
+char const * bt_ntoa (bdaddr_t const *, char *);
+int bt_aton (char const *, bdaddr_t *);
+
+int bt_devaddr (const char *, bdaddr_t *);
+int bt_devname (char *, const bdaddr_t *);
+
+typedef struct bt_handle *bt_handle_t;
+
+bt_handle_t bt_openconfig (const char *);
+bt_cfgentry_t * bt_getconfig (bt_handle_t, const bdaddr_t *);
+int bt_eachconfig (bt_handle_t, void (*func)(bt_cfgentry_t *, void *), void *);
+void bt_freeconfig (bt_cfgentry_t *);
+int bt_closeconfig (bt_handle_t);
+int bt_printconfig (FILE *, bt_cfgentry_t *);
+
+#ifdef COMPAT_BLUEZ
+/*
+ * Linux BlueZ compatibility
+ */
+
+#define bacmp(ba1, ba2) memcmp((ba1), (ba2), sizeof(bdaddr_t))
+#define bacpy(dst, src) memcpy((dst), (src), sizeof(bdaddr_t))
+#define ba2str(ba, str) bt_ntoa((ba), (str))
+#define str2ba(str, ba) (bt_aton((str), (ba)) == 1 ? 0 : -1)
+
+#define htobs(x) htole16(x)
+#define htobl(x) htole32(x)
+#define btohs(x) le16toh(x)
+#define btohl(x) le32toh(x)
+
+#define bt_malloc(n) malloc(n)
+#define bt_free(p) free(p)
+
+#endif /* COMPAT_BLUEZ */
+
+__END_DECLS
+
+#endif /* ndef _BLUETOOTH_H_ */
diff --git a/lib/libbluetooth/devaddr.c b/lib/libbluetooth/devaddr.c
new file mode 100644
index 00000000000..e62c90342dc
--- /dev/null
+++ b/lib/libbluetooth/devaddr.c
@@ -0,0 +1,106 @@
+/* $NetBSD: devaddr.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
+
+/*-
+ * Copyright (c) 2006 Itronix Inc.
+ * All rights reserved.
+ *
+ * Written by Iain Hibbert for Itronix Inc.
+ *
+ * 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.
+ * 3. The name of Itronix Inc. may not be used to endorse
+ * or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``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 ITRONIX INC. 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: devaddr.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $");
+
+#include <sys/ioctl.h>
+#include <bluetooth.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+bt_devaddr(const char *name, bdaddr_t *addr)
+{
+ struct btreq btr;
+ bdaddr_t bdaddr;
+ int s;
+
+ if (name == NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ if (addr == NULL)
+ addr = &bdaddr;
+
+ if (bt_aton(name, addr))
+ return bt_devname(NULL, addr);
+
+ memset(&btr, 0, sizeof(btr));
+ strlcpy(btr.btr_name, name, HCI_DEVNAME_SIZE);
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (s == -1)
+ return 0;
+
+ if (ioctl(s, SIOCGBTINFO, &btr) < 0)
+ return 0;
+
+ close(s);
+
+ bdaddr_copy(addr, &btr.btr_bdaddr);
+ return 1;
+}
+
+int
+bt_devname(char *name, const bdaddr_t *addr)
+{
+ struct btreq btr;
+ int s;
+
+ if (addr == NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ memset(&btr, 0, sizeof(btr));
+ bdaddr_copy(&btr.btr_bdaddr, addr);
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (s == -1)
+ return 0;
+
+ if (ioctl(s, SIOCGBTINFOA, &btr) < 0)
+ return 0;
+
+ close(s);
+
+ if (name != NULL)
+ strlcpy(name, btr.btr_name, HCI_DEVNAME_SIZE);
+
+ return 1;
+}
diff --git a/lib/libbluetooth/lexer.l b/lib/libbluetooth/lexer.l
new file mode 100644
index 00000000000..a26e4e2d13b
--- /dev/null
+++ b/lib/libbluetooth/lexer.l
@@ -0,0 +1,158 @@
+/* $NetBSD: lexer.l,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
+
+%{
+/*-
+ * Copyright (c) 2006 Itronix Inc.
+ * All rights reserved.
+ *
+ * Written by Iain Hibbert for Itronix Inc.
+ *
+ * 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.
+ * 3. The name of Itronix Inc. may not be used to endorse
+ * or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``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 ITRONIX INC. 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.
+ */
+/*
+ * lexer.l
+ *
+ * Copyright (c) 2001-2002 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.
+ *
+ * $Id: lexer.l,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+ * $FreeBSD: src/usr.sbin/bluetooth/hcsecd/lexer.l,v 1.1 2003/05/10 21:50:35 julian Exp $
+ */
+
+#include <bluetooth.h>
+#include <string.h>
+#include "parser.h"
+
+int yylex(void);
+%}
+
+%option yylineno noyywrap nounput
+
+delim [ \t\n]
+ws {delim}+
+empty {delim}*
+comment \#.*
+
+hexdigit [0-9a-fA-F]
+hexbyte {hexdigit}{hexdigit}
+digit [0-9]
+value {digit}+
+
+device_word device
+bdaddr_word bdaddr
+name_word name
+key_word key
+pin_word pin
+control_psm_word control_psm
+control_channel_word control_channel
+interrupt_psm_word interrupt_psm
+reconnect_initiate_word reconnect_initiate
+battery_power_word battery_power
+normally_connectable_word normally_connectable
+hid_descriptor_word hid_descriptor
+true_word true
+false_word false
+type_word type
+hid_word hid
+hset_word hset
+
+bdaddrstring {hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}
+hexstring 0x{hexbyte}{1,16}
+string \".+\"
+
+%%
+
+\; return (';');
+\: return (':');
+\{ return ('{');
+\} return ('}');
+
+{ws} ;
+{empty} ;
+{comment} ;
+
+{device_word} return (T_DEVICE);
+{bdaddr_word} return (T_BDADDR);
+{name_word} return (T_NAME);
+{key_word} return (T_KEY);
+{pin_word} return (T_PIN);
+{control_psm_word} return (T_CONTROL_PSM);
+{control_channel_word} return (T_CONTROL_CHANNEL);
+{interrupt_psm_word} return (T_INTERRUPT_PSM);
+{reconnect_initiate_word} return (T_RECONNECT_INITIATE);
+{battery_power_word} return (T_BATTERY_POWER);
+{normally_connectable_word} return (T_NORMALLY_CONNECTABLE);
+{hid_descriptor_word} return (T_HID_DESCRIPTOR);
+{true_word} return (T_TRUE);
+{false_word} return (T_FALSE);
+{type_word} return (T_TYPE);
+{hid_word} return (T_HID);
+{hset_word} return (T_HSET);
+
+{bdaddrstring} {
+ return (bt_aton(yytext, &_btyylval.bdaddr) ?
+ T_BDADDRSTRING : T_ERROR);
+ }
+
+{hexstring} {
+ _btyylval.string = &yytext[2];
+ return (T_HEXSTRING);
+ }
+
+{string} {
+ yytext[strlen(yytext) - 1] = 0;
+ _btyylval.string = &yytext[1];
+ return (T_STRING);
+ }
+
+{value} {
+ _btyylval.value = atoi(yytext);
+ return (T_VALUE);
+ }
+
+. return (T_ERROR);
+
+%%
diff --git a/lib/libbluetooth/parser.y b/lib/libbluetooth/parser.y
new file mode 100644
index 00000000000..0a2578a65c6
--- /dev/null
+++ b/lib/libbluetooth/parser.y
@@ -0,0 +1,612 @@
+/* $NetBSD: parser.y,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
+
+%{
+/*-
+ * Copyright (c) 2006 Itronix Inc.
+ * 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.
+ * 3. The name of Itronix Inc. may not be used to endorse
+ * or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``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 ITRONIX INC. 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.
+ */
+/*
+ * parser.y
+ *
+ * Copyright (c) 2001-2002 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.
+ *
+ * $Id: parser.y,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+ * $FreeBSD: src/usr.sbin/bluetooth/hcsecd/parser.y,v 1.4 2004/09/14 20:04:33 emax Exp $
+ */
+
+#include <bluetooth.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <dev/bluetooth/btdev.h>
+
+struct bt_handle {
+ FILE *fp;
+};
+
+int _btyyparse (void);
+int _btyylex (void);
+void _btyyerror (const char *);
+
+static int hexcpy (uint8_t *, const char *, int);
+
+extern int _btyylineno;
+extern FILE *_btyyin;
+
+static void *arg;
+static const bdaddr_t *bdaddr;
+static int count;
+static bt_cfgentry_t *found;
+static void (*func)(bt_cfgentry_t *, void *);
+
+static bt_cfgentry_t *entry;
+static uint8_t hid_buffer[1024];
+static int hid_length;
+%}
+
+%union {
+ char *string;
+ bdaddr_t bdaddr;
+ int value;
+}
+
+%token <string> T_STRING T_HEXSTRING
+%token <bdaddr> T_BDADDRSTRING
+%token <value> T_VALUE
+%token T_DEVICE
+%token T_BDADDR
+%token T_NAME
+%token T_KEY
+%token T_PIN
+%token T_TYPE
+%token T_HID
+%token T_HSET
+%token T_CONTROL_PSM
+%token T_CONTROL_CHANNEL
+%token T_INTERRUPT_PSM
+%token T_RECONNECT_INITIATE
+%token T_BATTERY_POWER
+%token T_NORMALLY_CONNECTABLE
+%token T_HID_DESCRIPTOR
+
+%token T_TRUE
+%token T_FALSE
+%token T_ERROR
+
+%%
+
+config:
+ line
+ | config line
+ ;
+
+line:
+ T_DEVICE
+ {
+ entry = malloc(sizeof(bt_cfgentry_t));
+ if (entry == NULL)
+ YYABORT;
+
+ memset(entry, 0, sizeof(bt_cfgentry_t));
+ }
+ '{' options '}'
+ {
+ if (bdaddr != NULL) {
+ if (bdaddr_same(&entry->bdaddr, bdaddr)) {
+ bt_freeconfig(found);
+ found = entry;
+ } else
+ bt_freeconfig(entry);
+ }
+
+ if (func != NULL) {
+ (*func)(entry, arg);
+ bt_freeconfig(entry);
+ }
+
+ entry = NULL;
+ count++;
+ }
+ ;
+
+options:
+ option ';'
+ | options option ';'
+ ;
+
+option:
+ bdaddr
+ | type
+ | name
+ | key
+ | pin
+ | control_psm
+ | control_channel
+ | interrupt_psm
+ | reconnect_initiate
+ | battery_power
+ | normally_connectable
+ | hid_descriptor
+ | parser_error
+ ;
+
+bdaddr:
+ T_BDADDR T_BDADDRSTRING
+ {
+ bdaddr_copy(&entry->bdaddr, &$2);
+ }
+ ;
+
+type:
+ T_TYPE T_HID
+ {
+ entry->type = BTDEV_HID;
+ }
+ | T_TYPE T_HSET
+ {
+ entry->type = BTDEV_HSET;
+ }
+ ;
+
+name:
+ T_NAME T_STRING
+ {
+ if (entry->name != NULL)
+ free(entry->name);
+
+ entry->name = strdup($2);
+ if (entry->name == NULL)
+ YYABORT;
+ }
+ ;
+
+key:
+ T_KEY T_HEXSTRING
+ {
+ if (entry->key == NULL) {
+ entry->key = malloc(HCI_KEY_SIZE);
+ if (entry->key == NULL)
+ YYABORT;
+ }
+
+ memset(entry->key, 0, HCI_KEY_SIZE);
+ hexcpy(entry->key, $2, HCI_KEY_SIZE);
+ }
+ ;
+
+pin:
+ T_PIN T_STRING
+ {
+ if (entry->pin == NULL) {
+ entry->pin = malloc(HCI_PIN_SIZE);
+ if (entry->pin == NULL)
+ YYABORT;
+ }
+
+ strncpy((char *)entry->pin, $2, HCI_PIN_SIZE);
+ }
+ | T_PIN T_HEXSTRING
+ {
+ if (entry->pin == NULL) {
+ entry->pin = malloc(HCI_PIN_SIZE);
+ if (entry->pin == NULL)
+ YYABORT;
+ }
+
+ memset(entry->pin, 0, HCI_PIN_SIZE);
+ hexcpy(entry->pin, $2, HCI_PIN_SIZE);
+ }
+ ;
+
+control_psm:
+ T_CONTROL_PSM T_HEXSTRING
+ {
+ if (strlen($2) > sizeof(entry->control_psm) * 2) {
+ errno = EINVAL;
+ YYABORT;
+ }
+
+ entry->control_psm = (uint16_t)strtoul($2, NULL, 16);
+ }
+ ;
+
+control_channel:
+ T_CONTROL_CHANNEL T_VALUE
+ {
+ entry->control_channel = (uint8_t)$2;
+ }
+ ;
+
+interrupt_psm:
+ T_INTERRUPT_PSM T_HEXSTRING
+ {
+ if (strlen($2) > sizeof(entry->interrupt_psm) * 2) {
+ errno = EINVAL;
+ YYABORT;
+ }
+
+ entry->interrupt_psm = (uint16_t)strtoul($2, NULL, 16);
+ }
+ ;
+
+reconnect_initiate:
+ T_RECONNECT_INITIATE T_TRUE
+ {
+ entry->reconnect_initiate = 1;
+ }
+ | T_RECONNECT_INITIATE T_FALSE
+ {
+ entry->reconnect_initiate = 0;
+ }
+ ;
+
+battery_power:
+ T_BATTERY_POWER T_TRUE
+ {
+ entry->battery_power = 1;
+ }
+ | T_BATTERY_POWER T_FALSE
+ {
+ entry->battery_power = 0;
+ }
+ ;
+
+normally_connectable:
+ T_NORMALLY_CONNECTABLE T_TRUE
+ {
+ entry->normally_connectable = 1;
+ }
+ | T_NORMALLY_CONNECTABLE T_FALSE
+ {
+ entry->normally_connectable = 0;
+ }
+ ;
+
+hid_descriptor:
+ T_HID_DESCRIPTOR
+ {
+ hid_length = 0;
+ }
+ '{' hid_descriptor_bytes '}'
+ {
+ if (entry->hid_descriptor != NULL)
+ free(entry->hid_descriptor);
+
+ entry->hid_descriptor = malloc(hid_length);
+ if (entry->hid_descriptor == NULL)
+ YYABORT;
+
+ memcpy(entry->hid_descriptor, hid_buffer, hid_length);
+ entry->hid_length = hid_length;
+ }
+ ;
+
+hid_descriptor_bytes:
+ hid_descriptor_byte
+ | hid_descriptor_bytes hid_descriptor_byte
+ ;
+
+hid_descriptor_byte:
+ T_HEXSTRING
+ {
+ if (hid_length >= sizeof(hid_buffer)) {
+ errno = ENOBUFS;
+ YYABORT;
+ }
+
+ if (strlen($1) != 2) {
+ errno = EINVAL;
+ YYABORT;
+ }
+
+ hid_buffer[hid_length++] = (uint8_t)strtoul($1, NULL, 16);
+ }
+ ;
+
+parser_error:
+ T_ERROR
+ {
+ errno = EINVAL;
+ YYABORT;
+ }
+
+%%
+
+/* Display parser error message */
+void
+_btyyerror(const char *message)
+{
+
+ /* fprintf(stderr, "%s in line %d", message, _btyylineno); */
+ count = -1;
+}
+
+/* Convert hex ASCII to int4 */
+static int
+hexa2int4(char a)
+{
+
+ if ('0' <= a && a <= '9')
+ return (a - '0');
+
+ if ('A' <= a && a <= 'F')
+ return (a - 'A' + 0xa);
+
+ if ('a' <= a && a <= 'f')
+ return (a - 'a' + 0xa);
+
+ /* NOTREACHED */
+ return 0;
+}
+
+/* Convert ASCII hex string to uint8 array */
+static int
+hexcpy(uint8_t *dest, const char *src, int len)
+{
+ int n;
+
+ for (n = 0 ; n < len && *src != '\0' ; n++) {
+ *dest++ = (hexa2int4(src[0]) << 4) | hexa2int4(src[1]);
+ src += 2;
+ }
+
+ return n;
+}
+
+/* Open config file */
+bt_handle_t
+bt_openconfig(const char *name)
+{
+ bt_handle_t handle;
+
+ handle = malloc(sizeof(bt_handle_t));
+ if (handle == NULL)
+ return NULL;
+
+ memset(handle, 0, sizeof(bt_handle_t));
+
+ if (name == NULL)
+ name = "/etc/bluetooth/bluetooth.conf";
+
+ handle->fp = fopen(name, "r");
+ if (handle->fp == NULL) {
+ free(handle);
+ return NULL;
+ }
+
+ return handle;
+}
+
+/* Find config entry for device */
+bt_cfgentry_t *
+bt_getconfig(bt_handle_t handle, const bdaddr_t *device)
+{
+
+ if (handle == NULL || handle->fp == NULL) {
+ errno = EBADF;
+ return NULL;
+ }
+
+ arg = NULL;
+ bdaddr = device;
+ count = 0;
+ found = NULL;
+ func = NULL;
+
+ _btyyin = handle->fp;
+ rewind(_btyyin);
+ _btyyparse();
+ _btyyin = NULL;
+
+ if (found == NULL)
+ errno = ENOENT;
+
+ return found;
+}
+
+/* Call function for each config entry */
+int
+bt_eachconfig(bt_handle_t handle, void (*f)(bt_cfgentry_t *, void *), void *a)
+{
+
+ if (handle == NULL || handle->fp == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ arg = a;
+ bdaddr = NULL;
+ count = 0;
+ found = NULL;
+ func = f;
+
+ _btyyin = handle->fp;
+ rewind(_btyyin);
+ _btyyparse();
+ _btyyin = NULL;
+
+ return count;
+}
+
+/* Free config entry */
+void
+bt_freeconfig(bt_cfgentry_t *cfg)
+{
+
+ if (cfg == NULL)
+ return;
+
+ if (cfg->name)
+ free(cfg->name);
+
+ if (cfg->pin)
+ free(cfg->pin);
+
+ if (cfg->key)
+ free(cfg->key);
+
+ if (cfg->hid_descriptor)
+ free(cfg->hid_descriptor);
+
+ free(cfg);
+}
+
+/* Close config file */
+int
+bt_closeconfig(bt_handle_t handle)
+{
+ int rv;
+
+ if (handle == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ rv = fclose(handle->fp);
+ handle->fp = NULL;
+ free(handle);
+
+ return rv;
+}
+
+#define OPT "\t%-23s "
+#define Q "\""
+#define HEX "0x%4.4x"
+#define DEC "%d"
+#define KEY "0x%s"
+#define STR "%s"
+#define SLEN "%.*s"
+#define EOL ";\n"
+
+/* Print config entry */
+int
+bt_printconfig(FILE *fp, bt_cfgentry_t *cfg)
+{
+ int i, n;
+
+ if (cfg == NULL || fp == NULL)
+ return -1;
+
+ fprintf(fp, "device {\n");
+ fprintf(fp, OPT STR EOL, "bdaddr", bt_ntoa(&cfg->bdaddr, NULL));
+
+ if (cfg->type != 0) {
+ const char *type;
+
+ switch (cfg->type) {
+ case BTDEV_HID:
+ type = "hid";
+ break;
+
+ case BTDEV_HSET:
+ type = "hset";
+ break;
+
+ default:
+ type = "unknown";
+ break;
+ }
+
+ fprintf(fp, OPT STR EOL, "type", type);
+ }
+
+ if (cfg->name != NULL)
+ fprintf(fp, OPT Q STR Q EOL, "name", cfg->name);
+
+ if (cfg->pin != NULL)
+ fprintf(fp, OPT Q SLEN Q EOL, "pin", HCI_PIN_SIZE, cfg->pin);
+
+ if (cfg->key != NULL) {
+ fprintf(fp, OPT STR, "key", "0x");
+
+ n = HCI_KEY_SIZE - 1;
+ while (n > 1 && cfg->key[n] == 0)
+ n--;
+
+ for (i = 0 ; i <= n ; i++)
+ fprintf(fp, "%2.2x", cfg->key[i]);
+
+ fprintf(fp, EOL);
+ }
+
+ if (cfg->control_psm != 0)
+ fprintf(fp, OPT HEX EOL, "control_psm", cfg->control_psm);
+
+ if (cfg->interrupt_psm != 0)
+ fprintf(fp, OPT HEX EOL, "interrupt_psm", cfg->interrupt_psm);
+
+ if (cfg->control_channel != 0)
+ fprintf(fp, OPT DEC EOL, "control_channel", cfg->control_channel);
+
+ if (cfg->reconnect_initiate != 0)
+ fprintf(fp, OPT STR EOL, "reconnect_initiate", "true");
+
+ if (cfg->battery_power != 0)
+ fprintf(fp, OPT STR EOL, "battery_power", "true");
+
+ if (cfg->normally_connectable != 0)
+ fprintf(fp, OPT STR EOL, "normally_connectable", "true");
+
+ if (cfg->hid_descriptor != NULL) {
+ fprintf(fp, OPT "{", "hid_descriptor");
+
+ for (i = 0 ; i < cfg->hid_length ; i++)
+ fprintf(fp, "%s0x%2.2x",
+ ((i % 8) ? " " : "\n\t\t"),
+ cfg->hid_descriptor[i]);
+
+ fprintf(fp, "\n\t}" EOL);
+ }
+
+ fprintf(fp, "}\n");
+
+ return 0;
+}
diff --git a/lib/libbluetooth/shlib_version b/lib/libbluetooth/shlib_version
new file mode 100644
index 00000000000..e3b49e9e2aa
--- /dev/null
+++ b/lib/libbluetooth/shlib_version
@@ -0,0 +1,5 @@
+# $NetBSD: shlib_version,v 1.1 2006/06/19 15:44:36 gdamore Exp $
+# Remember to update distrib/sets/lists/base/shl.* when changing
+#
+major=2
+minor=0