Update Bluetooth code.

Reviewed by: M. Warner Losh <imp@bsdimp.com>; John Hay <jhay@freebsd.org>
Approved by: M. Warner Losh <imp@bsdimp.com> (mentor)
This commit is contained in:
Maksim Yevmenkin 2003-10-12 22:04:24 +00:00
parent 907d866750
commit 0986ab12e4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121054
109 changed files with 5997 additions and 988 deletions

56
etc/bluetooth/hcsecd.conf Normal file
View file

@ -0,0 +1,56 @@
# $Id: hcsecd.conf,v 1.1 2003/05/26 22:50:47 max Exp $
# $FreeBSD$
#
# HCI security daemon configuration file
#
# Format:
#
# device {
# option value ;
# }
#
# Possible options and values
#
# Options Values
# ----------------------------------
# bdaddr xx:xx:xx:xx:xx:xx ; - remote device BD_ADDR
# name "any char" ; - to set user friendly device name
# key 0x11223344 | nokey ; - to set link key for the device
# pin "secret" | nopin ; - to PIN code for the device
#
# Notes:
#
# Currently there is no way to select keys/PIN code based on which
# local device received the request. Everything is based on remote
# device BD_ADDR.
#
# "nokey" means that no link key has been defined and we should
# send Link_Key_Negative_Reply command to the device.
#
# "nopin" means that no PIN code has been defined and we should
# send PIN_Code_Negative_Reply command to the device
#
# Default entry is applied if no better match found
# It MUST have 00:00:00:00:00:00 as bdaddr
device {
bdaddr 00:00:00:00:00:00;
name "Default entry";
key nokey;
pin nopin;
}
device {
bdaddr 00:1:2:3:4:5;
name "Dummy";
key nokey;
pin "0000";
}
device {
bdaddr 00:11:22:33:44:55;
name "Dummy";
key 0x00112233445566778899aabbccddeeff; # 16 bytes key (hex string)
pin nopin;
}

11
etc/bluetooth/hosts Normal file
View file

@ -0,0 +1,11 @@
# $Id: hosts,v 1.1 2003/05/21 17:48:40 max Exp $
# $FreeBSD$
#
# Bluetooth Host Database
#
# This file should contain the Bluetooth addresses and aliases for hosts.
#
# BD_ADDR Name [ alias0 alias1 ... ]
ff:ff:ff:00:00:00 localhost local # Magic sdpd address

21
etc/bluetooth/protocols Normal file
View file

@ -0,0 +1,21 @@
# $Id: protocols,v 1.2 2003/05/21 22:17:14 max Exp $
# $FreeBSD$
#
# Bluetooth Protocol/Service Multiplexor (PSM) names and numbers
#
# See also http://www.bluetoothsig.org/assigned-numbers/
#
# Protocol PSM Alias Reference
sdp 1 SDP # Service Discovery Protocol
rfcomm 3 RFCOMM # RFCOMM with TS 07.10
tcs-bin 5 TCS-BIN # Telephony Control Specification
tcs-bin-cordless 7 TCS-BIN-CORDLESS # Telephony Control Specification
bnep 15 BNEP # Bluetooth Network Encapsulation Protocol
hid-control 17 HID-Control # Human Interface Device (control)
hid-interrupt 19 HID-Interrupt # Human Interface Device (interrupt)
upnp 21 UPnP # See ESDP, Bluetooth SIG
avctp 23 AVCTP # Audio/Video Control Transport Protocol
avdtp 25 AVDTP # Audio/Video Distribution Transport Protocol
udi-c-plane 29 UDI-C-Plane # Unrestricted Digital Information Profile

View file

@ -23,12 +23,13 @@
SUBDIR= ${_csu} libcom_err libcrypt libkvm msun libmd \
libncurses libradius librpcsvc libsbuf libtacplus libutil libypclnt \
${_compat} libalias ${_libatm} ${_libbind} libbz2 libc ${_libc_r} \
${_compat} libalias ${_libatm} ${_libbind} \
${_libbluetooth} libbz2 libc ${_libc_r} \
libcalendar libcam libcompat libdevinfo libdevstat ${_libdisk} \
libedit libexpat libfetch libform libftpio libgeom ${_libio} libipsec \
libipx libisc libkiconv libmenu ${_libmilter} ${_libmp} ${_libncp} \
libnetgraph libopie libpam libpanel libpcap ${_libpthread} \
${_libsm} ${_libsmb} ${_libsmdb} ${_libsmutil} \
${_libsdp} ${_libsm} ${_libsmb} ${_libsmdb} ${_libsmutil} \
libstand libtelnet ${_libthr} libufs libugidfw ${_libusbhid} \
${_libvgl} libwrap libxpg4 liby libz
@ -68,7 +69,9 @@ _libusbhid= libusbhid
.if ${MACHINE_ARCH} == "i386"
_compat= compat
_libbluetooth= libbluetooth
_libncp= libncp
_libsdp= libsdp
_libsmb= libsmb
_libvgl= libvgl
.endif

30
lib/libbluetooth/Makefile Normal file
View file

@ -0,0 +1,30 @@
# $Id: Makefile,v 1.5 2003/07/22 18:38:04 max Exp $
# $FreeBSD$
LIB= bluetooth
MAN= bluetooth.3
WARNS?= 2
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys
SHLIB_MAJOR= 1
SRCS= bluetooth.c
INCS= bluetooth.h
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
.include <bsd.lib.mk>

View file

@ -0,0 +1,293 @@
.\" 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.5 2003/05/20 23:04:30 max Exp $
.\" $FreeBSD$
.\"
.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
.Nd get Bluetooth host entry
.Pp
.Nm bt_getprotobyname ,
.Nm bt_getprotobynumber ,
.Nm bt_getprotoent ,
.Nm bt_setprotoent ,
.Nm bt_endprotoent
.Nd get Bluetooth Protocol Service Multiplexor entry
.Pp
.Nm bt_aton ,
.Nm bt_ntoa
.Nd Bluetooth address manipulation 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"
.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 an 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 internal static buffer will be used.
.Sh FILES
.Bl -tag -width /etc/bluetooth/hosts -compact
.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
.Fn herror
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 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 Null pointer (0) on
.Dv EOF
or error.
.Sh SEE ALSO
.Xr gethostbyaddr 3 ,
.Xr gethostbyname 3 ,
.Xr getprotobyaddr 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 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 AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View file

@ -0,0 +1,369 @@
/*
* 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.3 2003/05/20 23:04:30 max Exp $
* $FreeBSD$
*/
#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, int 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 && bcmp(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 proto)
{
struct protoent *p;
bt_setprotoent(proto_stayopen);
while ((p = bt_getprotoent()) != NULL)
if (p->p_proto == proto)
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 = atoi(cp);
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 != NULL && 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);
}

View file

@ -0,0 +1,78 @@
/*
* 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.5 2003/09/14 23:28:42 max Exp $
* $FreeBSD$
*/
#ifndef _BLUETOOTH_H_
#define _BLUETOOTH_H_
#include <sys/types.h>
#include <sys/bitstring.h>
#include <sys/endian.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <netgraph/bluetooth/include/ng_hci.h>
#include <netgraph/bluetooth/include/ng_l2cap.h>
#include <netgraph/bluetooth/include/ng_btsocket.h>
__BEGIN_DECLS
/*
* Lunux 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)
/*
* Interface to the outside world
*/
struct hostent * bt_gethostbyname (char const *name);
struct hostent * bt_gethostbyaddr (char const *addr, int len, int type);
struct hostent * bt_gethostent (void);
void bt_sethostent (int stayopen);
void bt_endhostent (void);
struct protoent * bt_getprotobyname (char const *name);
struct protoent * bt_getprotobynumber (int proto);
struct protoent * bt_getprotoent (void);
void bt_setprotoent (int stayopen);
void bt_endprotoent (void);
char const * bt_ntoa (bdaddr_t const *ba, char *str);
int bt_aton (char const *str, bdaddr_t *ba);
__END_DECLS
#endif /* ndef _BLUETOOTH_H_ */

33
lib/libsdp/Makefile Normal file
View file

@ -0,0 +1,33 @@
# $Id: Makefile,v 1.2 2003/09/07 20:34:19 max Exp $
# $FreeBSD$
LIB= sdp
MAN= sdp.3
WARNS?= 2
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys
SHLIB_MAJOR= 1
SRCS= search.c session.c util.c
INCS= sdp.h
MLINKS+= sdp.3 SDP_GET8.3
MLINKS+= sdp.3 SDP_GET16.3
MLINKS+= sdp.3 SDP_GET32.3
MLINKS+= sdp.3 SDP_GET64.3
MLINKS+= sdp.3 SDP_GET128.3
MLINKS+= sdp.3 SDP_PUT8.3
MLINKS+= sdp.3 SDP_PUT16.3
MLINKS+= sdp.3 SDP_PUT32.3
MLINKS+= sdp.3 SDP_PUT64.3
MLINKS+= sdp.3 SDP_PUT128.3
MLINKS+= sdp.3 sdp_open.3
MLINKS+= sdp.3 sdp_open_local.3
MLINKS+= sdp.3 sdp_close.3
MLINKS+= sdp.3 sdp_error.3
MLINKS+= sdp.3 sdp_search.3
MLINKS+= sdp.3 sdp_attr2desc.3
MLINKS+= sdp.3 sdp_uuid2desc.3
.include <bsd.lib.mk>

65
lib/libsdp/sdp-int.h Normal file
View file

@ -0,0 +1,65 @@
/*
* sdp-int.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: sdp-int.h,v 1.1 2003/09/01 23:01:07 max Exp $
* $FreeBSD$
*/
#ifndef _SDP_INT_H_
#define _SDP_INT_H_
__BEGIN_DECLS
#define SDP_UNSOCK_PATH "/var/run/sdp"
#define SDP_UNSOCK_MTU 2048
/*
* SDP session
*/
struct sdp_session {
u_int16_t flags;
#define SDP_SESSION_LOCAL (1 << 0)
u_int16_t tid; /* current session transaction ID (tid) */
u_int16_t omtu; /* outgoing MTU (req buffer size) */
u_int16_t imtu; /* incoming MTU (rsp buffer size) */
u_int8_t *req; /* request buffer (start) */
u_int8_t *req_e; /* request buffer (end) */
u_int8_t *rsp; /* response buffer (start) */
u_int8_t *rsp_e; /* response buffer (end) */
u_int32_t cslen; /* continuation state length */
u_int8_t cs[16];/* continuation state */
int32_t s; /* L2CAP socket */
int32_t error; /* last error code */
};
typedef struct sdp_session sdp_session_t;
typedef struct sdp_session * sdp_session_p;
__END_DECLS
#endif /* ndef _SDP_INT_H_ */

309
lib/libsdp/sdp.3 Normal file
View file

@ -0,0 +1,309 @@
.\" 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: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $
.\" $FreeBSD$
.\"
.Dd September 7, 2003
.Dt SDP 3
.Os
.Sh NAME
.Nm SDP_GET8 ,
.Nm SDP_GET16 ,
.Nm SDP_GET32 ,
.Nm SDP_GET64 ,
.Nm SDP_GET128
.Nd get SDP integer
.Pp
.Nm SDP_PUT8 ,
.Nm SDP_PUT16 ,
.Nm SDP_PUT32 ,
.Nm SDP_PUT64 ,
.Nm SDP_PUT128
.Nd put SPD integer
.Pp
.Nm sdp_open ,
.Nm sdp_open_local ,
.Nm sdp_close
.Nm sdp_error
.Nd control SDP session
.Pp
.Nm sdp_search
.Nd perform SDP query
.Pp
.Nm sdp_attr2desc ,
.Nm sdp_uuid2desc
.Nd convert numeric SDP attribute/UUID value into human readable description
.Sh LIBRARY
.Lb libsdp
.Sh SYNOPSIS
.In bluetooth.h
.In sdp.h
.Fn SDP_GET8 "b" "cp"
.Fn SDP_GET16 "s" "cp"
.Fn SDP_GET32 "l" "cp"
.Fn SDP_GET64 "l" "cp"
.Fn SDP_GET128 "l" "cp"
.Fn SDP_PUT8 "b" "cp"
.Fn SDP_PUT16 "s" "cp"
.Fn SDP_PUT32 "l" "cp"
.Fn SDP_PUT64 "l" "cp"
.Fn SDP_PUT128 "l" "cp"
.Ft void *
.Fn sdp_open "bdaddr_t const *l" "bdaddr_t const *r"
.Ft void *
.Fn sdp_open_local "void"
.Ft int32_t
.Fn sdp_close "void *xs"
.Ft int32_t
.Fn sdp_error "void *xs"
.Ft int32_t
.Fn sdp_search "void *xs" "u_int32_t plen" "u_int16_t const *pp" "u_int32_t alen" "u_int32_t const *ap" "u_int32_t vlen" "sdp_attr_t *vp"
.Ft char const * const
.Fn sdp_attr2desc "u_int16_t attr"
.Ft char const * const
.Fn sdp_uuid2desc "u_int16_t uuid"
.Sh DESCRIPTION
The
.Fn SDP_GET8 ,
.Fn SDP_GET16 ,
.Fn SDP_GET32 ,
.Fn SDP_GET64
and
.Fn SDP_GET128
macros are used to get byte, short, long, long long and 128-bit integer
from the buffer pointed by
.Vt cp
pointer. The pointer is automatically advanced.
.Pp
The
.Fn SDP_PUT8 ,
.Fn SDP_PUT16 ,
.Fn SDP_PUT32 ,
.Fn SDP_PUT64
and
.Fn SDP_PUT128
macros are used to put byte, short, long, long long and 128-bit integer
into the buffer pointed by
.Vt cp
pointer. The pointer is automatically advanced.
.Pp
.Fn sdp_open
and
.Fn sdp_open_local
functions each return a pointer to an opaque object describing SDP session.
The
.Vt l
argument passed to
.Fn sdp_open
function should point to a source BD_ADDR.
If source BD_ADDR is
.Dv NULL
then source address
.Dv NG_HCI_BDADDR_ANY
is used.
The
.Vt r
argument passed to
.Fn sdp_open
function should point to a non
.Dv NULL
remote BD_ADDR.
Remote BD_ADDR can not be
.Dv NG_HCI_BDADDR_ANY .
The
.Fn sdp_open_local
function takes no arguments and opens a connection to a local SDP server.
.Pp
The
.Fn sdp_close
function terminates active SDP session and deletes SDP session object.
The
.Vt xs
parameter should point to a valid SDP session object created with
.Fn sdp_open
or
.Fn sdp_open_local .
.Pp
The
.Fn sdp_error
function returns last error that is stored inside SDP session object.
The
.Vt xs
parameter should point to a valid SDP session object created with
.Fn sdp_open
or
.Fn sdp_open_local .
The error value returned can be converted to a human readable message by
calling
.Xr strerror 3
function.
.Pp
The
.Fn sdp_search
function is used to perform SDP Service Search Attribute Request.
The
.Vt xs
parameter should point to a valid SDP session object created with
.Fn sdp_open
or
.Fn sdp_open_local .
The
.Vt pp
parameter is a Service Search Pattern - an array of one or more Service
Class IDs.
The maximum number of Service Class IDs in the array is 12.
The
.Vt plen
parameter is the length of the Service Search pattern.
The
.Vt ap
parameter is a Attribute ID Range List - an array of one or more SDP Attribute
ID Range. Each attribute ID Range is encoded as a 32-bit unsigned integer data
element, where the high order 16 bits are interpreted as the beginning
attribute ID of the range and the low order 16 bits are interpreted as the
ending attribute ID of the range.
The attribute IDs contained in the Attribute ID Ranges List must be listed in
ascending order without duplication of any attribute ID values.
Note that all attributes may be requested by specifying a range of
0x0000-0xFFFF.
The
.Vt alen
parameter is the length of the Attribute ID Ranges List.
The
.Fn SDP_ATTR_RANGE "lo" "hi"
macro can be used to prepare Attribute ID Range.
The
.Vt vp
parameter should be an array of
.Vt sdp_attr_t
structures.
Each
.Vt sdp_attr_t
structure describes single SDP attribute and defined as follows:
.Bd -literal -offset indent
struct sdp_attr {
u_int16_t flags;
#define SDP_ATTR_OK (0 << 0)
#define SDP_ATTR_INVALID (1 << 0)
#define SDP_ATTR_TRUNCATED (1 << 1)
u_int16_t attr; /* SDP_ATTR_xxx */
u_int32_t vlen; /* length of the value[] in bytes */
u_int8_t *value; /* base pointer */
};
typedef struct sdp_attr sdp_attr_t;
typedef struct sdp_attr * sdp_attr_p;
.Ed
.Pp
The caller of the
.Fn sdp_search
function is expected to prepare the array of
.Vt sdp_attr
structures and for each element of the array both
.Vt vlen
and
.Vt value
must be set.
The
.Fn sdp_search
function will fill each
.Vt sdp_attr_t
structure with attribute and value, i.e. it will set
.Vt flags ,
.Vt attr
and
.Vt vlen
fields.
The actual value of the attribute will be copied into
.Vt value
buffer.
Note: attributes are returned in the order they appear in the Service Search
Attribute Response.
SDP server could return several attributes for the same record.
In this case the order of the attributes will be: all attributes for the first
records, then all attributes for the secord record etc.
.Pp
The
.Fn sdp_attr2desc
and
.Fn sdp_uuid2desc
functions each take a numeric attribute ID/UUID value and convert it to a
human readable description.
.Sh EXAMPLES
The following example shows how to get
.Dv SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
attribute for the
.Dv SDP_SERVICE_CLASS_SERIAL_PORT
service from the remote device.
.Bd -literal -offset indent
bdaddr_t remote;
u_int8_t buffer[1024];
void *ss = NULL;
u_int16_t serv = SDP_SERVICE_CLASS_SERIAL_PORT;
u_int32_t attr = SDP_ATTR_RANGE(
SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer };
/* Obtain/set remote BDADDR here */
if ((ss = sdp_open(NG_HCI_BDADDR_ANY, remote)) == NULL)
/* exit ENOMEM */
if (sdp_error(ss) != 0)
/* exit spd_error(ss) */
if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0)
/* exit sdp_error(ss) */
if (proto.flags != SDP_ATTR_OK)
/* exit see proto.flags for details */
/* If we got here then we have attribute value in proto.value */
.Ed
.Sh DIAGNOSTICS
Both
.Fn sdp_open
and
.Fn sdp_open_local
will return
.Dv NULL
if memory allocation for the new SDP session object fails.
If the new SDP object was created then caller is still expected to call
.Fn sdp_error
to check if there was connection error.
.Pp
The
.Fn sdp_search
function returns non-zero value on error.
The caller is expected to call
.Fn sdp_error
to find out more about error.
.Sh SEE ALSO
.Xr bluetooth 3 ,
.Xr strerror 3
.Sh BUGS
This is client only library for now.
Please report bugs if found.
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

477
lib/libsdp/sdp.h Normal file
View file

@ -0,0 +1,477 @@
/*
* sdp.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: sdp.h,v 1.3 2003/09/05 00:33:59 max Exp $
* $FreeBSD$
*/
#ifndef _SDP_H_
#define _SDP_H_
__BEGIN_DECLS
/*
* Data representation (page 349)
*/
/* Nil, the null type */
#define SDP_DATA_NIL 0x00
/* Unsigned integer */
#define SDP_DATA_UINT8 0x08
#define SDP_DATA_UINT16 0x09
#define SDP_DATA_UINT32 0x0A
#define SDP_DATA_UINT64 0x0B
#define SDP_DATA_UINT128 0x0C
/* Signed two's-complement integer */
#define SDP_DATA_INT8 0x10
#define SDP_DATA_INT16 0x11
#define SDP_DATA_INT32 0x12
#define SDP_DATA_INT64 0x13
#define SDP_DATA_INT128 0x14
/* UUID, a universally unique identifier */
#define SDP_DATA_UUID16 0x19
#define SDP_DATA_UUID32 0x1A
#define SDP_DATA_UUID128 0x1C
/* Text string */
#define SDP_DATA_STR8 0x25
#define SDP_DATA_STR16 0x26
#define SDP_DATA_STR32 0x27
/* Boolean */
#define SDP_DATA_BOOL 0x28
/*
* Data element sequence.
* A data element whose data field is a sequence of data elements
*/
#define SDP_DATA_SEQ8 0x35
#define SDP_DATA_SEQ16 0x36
#define SDP_DATA_SEQ32 0x37
/*
* Data element alternative.
* A data element whose data field is a sequence of data elements from
* which one data element is to be selected.
*/
#define SDP_DATA_ALT8 0x3D
#define SDP_DATA_ALT16 0x3E
#define SDP_DATA_ALT32 0x3F
/* URL, a uniform resource locator */
#define SDP_DATA_URL8 0x45
#define SDP_DATA_URL16 0x46
#define SDP_DATA_URL32 0x47
/*
* Protocols UUID (short) http://www.bluetoothsig.org/assigned-numbers/sdp.htm
* BASE UUID 00000000-0000-1000-8000-00805F9B34FB
*/
#define SDP_UUID_PROTOCOL_SDP 0x0001
#define SDP_UUID_PROTOCOL_UDP 0x0002
#define SDP_UUID_PROTOCOL_RFCOMM 0x0003
#define SDP_UUID_PROTOCOL_TCP 0x0004
#define SDP_UUID_PROTOCOL_TCS_BIN 0x0005
#define SDP_UUID_PROTOCOL_TCS_AT 0x0006
#define SDP_UUID_PROTOCOL_OBEX 0x0008
#define SDP_UUID_PROTOCOL_IP 0x0009
#define SDP_UUID_PROTOCOL_FTP 0x000A
#define SDP_UUID_PROTOCOL_HTTP 0x000C
#define SDP_UUID_PROTOCOL_WSP 0x000E
#define SDP_UUID_PROTOCOL_BNEP 0x000F
#define SDP_UUID_PROTOCOL_UPNP 0x0010
#define SDP_UUID_PROTOCOL_HIDP 0x0011
#define SDP_UUID_PROTOCOL_HARDCOPY_CONTROL_CHANNEL 0x0012
#define SDP_UUID_PROTOCOL_HARDCOPY_DATA_CHANNEL 0x0014
#define SDP_UUID_PROTOCOL_HARDCOPY_NOTIFICATION 0x0016
#define SDP_UUID_PROTOCOL_AVCTP 0x0017
#define SDP_UUID_PROTOCOL_AVDTP 0x0019
#define SDP_UUID_PROTOCOL_CMPT 0x001B
#define SDP_UUID_PROTOCOL_UDI_C_PLANE 0x001D
#define SDP_UUID_PROTOCOL_L2CAP 0x0100
/*
* Service class IDs http://www.bluetoothsig.org/assigned-numbers/sdp.htm
*/
#define SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER 0x1000
#define SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR 0x1001
#define SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP 0x1002
#define SDP_SERVICE_CLASS_SERIAL_PORT 0x1101
#define SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP 0x1102
#define SDP_SERVICE_CLASS_DIALUP_NETWORKING 0x1103
#define SDP_SERVICE_CLASS_IR_MC_SYNC 0x1104
#define SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH 0x1105
#define SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER 0x1106
#define SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND 0x1107
#define SDP_SERVICE_CLASS_HEADSET 0x1108
#define SDP_SERVICE_CLASS_CORDLESS_TELEPHONY 0x1109
#define SDP_SERVICE_CLASS_AUDIO_SOURCE 0x110A
#define SDP_SERVICE_CLASS_AUDIO_SINK 0x110B
#define SDP_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET 0x110C
#define SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION 0x110D
#define SDP_SERVICE_CLASS_AV_REMOTE_CONTROL 0x110E
#define SDP_SERVICE_CLASS_VIDEO_CONFERENCING 0x110F
#define SDP_SERVICE_CLASS_INTERCOM 0x1110
#define SDP_SERVICE_CLASS_FAX 0x1111
#define SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY 0x1112
#define SDP_SERVICE_CLASS_WAP 0x1113
#define SDP_SERVICE_CLASS_WAP_CLIENT 0x1114
#define SDP_SERVICE_CLASS_PANU 0x1115
#define SDP_SERVICE_CLASS_NAP 0x1116
#define SDP_SERVICE_CLASS_GN 0x1117
#define SDP_SERVICE_CLASS_DIRECT_PRINTING 0x1118
#define SDP_SERVICE_CLASS_REFERENCE_PRINTING 0x1119
#define SDP_SERVICE_CLASS_IMAGING 0x111A
#define SDP_SERVICE_CLASS_IMAGING_RESPONDER 0x111B
#define SDP_SERVICE_CLASS_IMAGING_AUTOMATIC_ARCHIVE 0x111C
#define SDP_SERVICE_CLASS_IMAGING_REFERENCED_OBJECTS 0x111D
#define SDP_SERVICE_CLASS_HANDSFREE 0x111E
#define SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY 0x111F
#define SDP_SERVICE_CLASS_DIRECT_PRINTING_REFERENCE_OBJECTS 0x1120
#define SDP_SERVICE_CLASS_REFLECTED_UI 0x1121
#define SDP_SERVICE_CLASS_BASIC_PRINTING 0x1122
#define SDP_SERVICE_CLASS_PRINTING_STATUS 0x1123
#define SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE 0x1124
#define SDP_SERVICE_CLASS_HARDCOPY_CABLE_REPLACEMENT 0x1125
#define SDP_SERVICE_CLASS_HCR_PRINT 0x1126
#define SDP_SERVICE_CLASS_HCR_SCAN 0x1127
#define SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS 0x1128
#define SDP_SERVICE_CLASS_VIDEO_CONFERENCING_GW 0x1129
#define SDP_SERVICE_CLASS_UDI_MT 0x112A
#define SDP_SERVICE_CLASS_UDI_TA 0x112B
#define SDP_SERVICE_CLASS_AUDIO_VIDEO 0x112C
#define SDP_SERVICE_CLASS_SIM_ACCESS 0x112D
#define SDP_SERVICE_CLASS_PNP_INFORMATION 0x1200
#define SDP_SERVICE_CLASS_GENERIC_NETWORKING 0x1201
#define SDP_SERVICE_CLASS_GENERIC_FILE_TRANSFER 0x1202
#define SDP_SERVICE_CLASS_GENERIC_AUDIO 0x1203
#define SDP_SERVICE_CLASS_GENERIC_TELEPHONY 0x1204
#define SDP_SERVICE_CLASS_UPNP 0x1205
#define SDP_SERVICE_CLASS_UPNP_IP 0x1206
#define SDP_SERVICE_CLASS_ESDP_UPNP_IP_PAN 0x1300
#define SDP_SERVICE_CLASS_ESDP_UPNP_IP_LAP 0x1301
#define SDP_SERVICE_CLASS_ESDP_UPNP_L2CAP 0x1302
/*
* Universal attribute definitions (page 366) and
* http://www.bluetoothsig.org/assigned-numbers/sdp.htm
*/
#define SDP_ATTR_RANGE(lo, hi) \
(u_int32_t)(((u_int16_t)(lo) << 16) | ((u_int16_t)(hi)))
#define SDP_ATTR_SERVICE_RECORD_HANDLE 0x0000
#define SDP_ATTR_SERVICE_CLASS_ID_LIST 0x0001
#define SDP_ATTR_SERVICE_RECORD_STATE 0x0002
#define SDP_ATTR_SERVICE_ID 0x0003
#define SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST 0x0004
#define SDP_ATTR_BROWSE_GROUP_LIST 0x0005
#define SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST 0x0006
#define SDP_ATTR_SERVICE_INFO_TIME_TO_LIVE 0x0007
#define SDP_ATTR_SERVICE_AVAILABILITY 0x0008
#define SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST 0x0009
#define SDP_ATTR_DOCUMENTATION_URL 0x000A
#define SDP_ATTR_CLIENT_EXECUTABLE_URL 0x000B
#define SDP_ATTR_ICON_URL 0x000C
#define SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS 0x000D
#define SDP_ATTR_GROUP_ID 0x0200
#define SDP_ATTR_IP_SUBNET 0x0200
#define SDP_ATTR_VERSION_NUMBER_LIST 0x0200
#define SDP_ATTR_SERVICE_DATABASE_STATE 0x0201
#define SDP_ATTR_SERVICE_VERSION 0x0300
#define SDP_ATTR_EXTERNAL_NETWORK 0x0301
#define SDP_ATTR_NETWORK 0x0301
#define SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301
#define SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302
#define SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302
#define SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303
#define SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303
#define SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304
#define SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305
#define SDP_ATTR_NETWORK_ADDRESS 0x0306
#define SDP_ATTR_WAP_GATEWAY 0x0307
#define SDP_ATTR_HOME_PAGE_URL 0x0308
#define SDP_ATTR_WAP_STACK_TYPE 0x0309
#define SDP_ATTR_SECURITY_DESCRIPTION 0x030A
#define SDP_ATTR_NET_ACCESS_TYPE 0x030B
#define SDP_ATTR_MAX_NET_ACCESS_RATE 0x030C
#define SDP_ATTR_IPV4_SUBNET 0x030D
#define SDP_ATTR_IPV6_SUBNET 0x030E
#define SDP_ATTR_SUPPORTED_CAPABALITIES 0x0310
#define SDP_ATTR_SUPPORTED_FEATURES 0x0311
#define SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312
#define SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313
/*
* The offset must be added to the attribute ID base (contained in the
* LANGUAGE_BASE_ATTRIBUTE_ID_LIST attribute) in order to compute the
* attribute ID for these attributes.
*/
#define SDP_ATTR_SERVICE_NAME_OFFSET 0x0000
#define SDP_ATTR_SERVICE_DESCRIPTION_OFFSET 0x0001
#define SDP_ATTR_PROVIDER_NAME_OFFSET 0x0002
/*
* Protocol data unit (PDU) format (page 352)
*/
#define SDP_PDU_ERROR_RESPONSE 0x01
#define SDP_PDU_SERVICE_SEARCH_REQUEST 0x02
#define SDP_PDU_SERVICE_SEARCH_RESPONSE 0x03
#define SDP_PDU_SERVICE_ATTRIBUTE_REQUEST 0x04
#define SDP_PDU_SERVICE_ATTRIBUTE_RESPONSE 0x05
#define SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST 0x06
#define SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_RESPONSE 0x07
struct sdp_pdu {
u_int8_t pid; /* PDU ID - SDP_PDU_xxx */
u_int16_t tid; /* transaction ID */
u_int16_t len; /* parameters length (in bytes) */
} __attribute__ ((packed));
typedef struct sdp_pdu sdp_pdu_t;
typedef struct sdp_pdu * sdp_pdu_p;
/*
* SDP int128/uint128 parameter
*/
struct int128 {
int8_t b[16];
};
typedef struct int128 int128_t;
typedef struct int128 u_int128_t;
/*
* SDP attribute
*/
struct sdp_attr {
u_int16_t flags;
#define SDP_ATTR_OK (0 << 0)
#define SDP_ATTR_INVALID (1 << 0)
#define SDP_ATTR_TRUNCATED (1 << 1)
u_int16_t attr; /* SDP_ATTR_xxx */
u_int32_t vlen; /* length of the value[] in bytes */
u_int8_t *value; /* base pointer */
};
typedef struct sdp_attr sdp_attr_t;
typedef struct sdp_attr * sdp_attr_p;
/******************************************************************************
* User interface
*****************************************************************************/
/* Inline versions of get/put byte/short/long. Pointer is advanced */
#define SDP_GET8(b, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
(b) = *t_cp; \
(cp) ++; \
}
#define SDP_GET16(s, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
(s) = ((u_int16_t)t_cp[0] << 8) \
| ((u_int16_t)t_cp[1]) \
; \
(cp) += 2; \
}
#define SDP_GET32(l, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
(l) = ((u_int32_t)t_cp[0] << 24) \
| ((u_int32_t)t_cp[1] << 16) \
| ((u_int32_t)t_cp[2] << 8) \
| ((u_int32_t)t_cp[3]) \
; \
(cp) += 4; \
}
#define SDP_GET64(l, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
(l) = ((u_int64_t)t_cp[0] << 56) \
| ((u_int64_t)t_cp[1] << 48) \
| ((u_int64_t)t_cp[2] << 40) \
| ((u_int64_t)t_cp[3] << 32) \
| ((u_int64_t)t_cp[4] << 24) \
| ((u_int64_t)t_cp[5] << 16) \
| ((u_int64_t)t_cp[6] << 8) \
| ((u_int64_t)t_cp[7]) \
; \
(cp) += 8; \
}
#if BYTE_ORDER == LITTLE_ENDIAN
#define SDP_GET128(l, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
(l)->b[15] = *t_cp++; \
(l)->b[14] = *t_cp++; \
(l)->b[13] = *t_cp++; \
(l)->b[12] = *t_cp++; \
(l)->b[11] = *t_cp++; \
(l)->b[10] = *t_cp++; \
(l)->b[9] = *t_cp++; \
(l)->b[8] = *t_cp++; \
(l)->b[7] = *t_cp++; \
(l)->b[6] = *t_cp++; \
(l)->b[5] = *t_cp++; \
(l)->b[4] = *t_cp++; \
(l)->b[3] = *t_cp++; \
(l)->b[2] = *t_cp++; \
(l)->b[1] = *t_cp++; \
(cp) += 16; \
}
#else /* BYTE_ORDER != LITTLE_ENDIAN */
#define SDP_GET128(l, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
(l)->b[0] = *t_cp++; \
(l)->b[1] = *t_cp++; \
(l)->b[2] = *t_cp++; \
(l)->b[3] = *t_cp++; \
(l)->b[4] = *t_cp++; \
(l)->b[5] = *t_cp++; \
(l)->b[6] = *t_cp++; \
(l)->b[7] = *t_cp++; \
(l)->b[8] = *t_cp++; \
(l)->b[9] = *t_cp++; \
(l)->b[10] = *t_cp++; \
(l)->b[11] = *t_cp++; \
(l)->b[12] = *t_cp++; \
(l)->b[13] = *t_cp++; \
(l)->b[14] = *t_cp++; \
(l)->b[15] = *t_cp++; \
(cp) += 16; \
}
#endif /* BYTE_ORDER */
#define SDP_PUT8(b, cp) { \
register u_int8_t t_b = (u_int8_t)(b); \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
*t_cp = t_b; \
(cp) ++; \
}
#define SDP_PUT16(s, cp) { \
register u_int16_t t_s = (u_int16_t)(s); \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += 2; \
}
#define SDP_PUT32(l, cp) { \
register u_int32_t t_l = (u_int32_t)(l); \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += 4; \
}
#define SDP_PUT64(l, cp) { \
register u_int64_t t_l = (u_int64_t)(l); \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
*t_cp++ = t_l >> 56; \
*t_cp++ = t_l >> 48; \
*t_cp++ = t_l >> 40; \
*t_cp++ = t_l >> 32; \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += 8; \
}
#if BYTE_ORDER == LITTLE_ENDIAN
#define SDP_PUT128(l, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
*t_cp++ = (l)->b[15]; \
*t_cp++ = (l)->b[14]; \
*t_cp++ = (l)->b[13]; \
*t_cp++ = (l)->b[12]; \
*t_cp++ = (l)->b[11]; \
*t_cp++ = (l)->b[10]; \
*t_cp++ = (l)->b[9]; \
*t_cp++ = (l)->b[8]; \
*t_cp++ = (l)->b[7]; \
*t_cp++ = (l)->b[6]; \
*t_cp++ = (l)->b[5]; \
*t_cp++ = (l)->b[4]; \
*t_cp++ = (l)->b[3]; \
*t_cp++ = (l)->b[2]; \
*t_cp++ = (l)->b[1]; \
*t_cp = (l)->b[0]; \
(cp) += 16; \
}
#else /* BYTE_ORDER != LITTLE_ENDIAN */
#define SDP_PUT128(l, cp) { \
register u_int8_t *t_cp = (u_int8_t *)(cp); \
*t_cp++ = (l)->b[0]; \
*t_cp++ = (l)->b[1]; \
*t_cp++ = (l)->b[2]; \
*t_cp++ = (l)->b[3]; \
*t_cp++ = (l)->b[4]; \
*t_cp++ = (l)->b[5]; \
*t_cp++ = (l)->b[6]; \
*t_cp++ = (l)->b[7]; \
*t_cp++ = (l)->b[8]; \
*t_cp++ = (l)->b[9]; \
*t_cp++ = (l)->b[10]; \
*t_cp++ = (l)->b[11]; \
*t_cp++ = (l)->b[12]; \
*t_cp++ = (l)->b[13]; \
*t_cp++ = (l)->b[14]; \
*t_cp = (l)->b[15]; \
(cp) += 16; \
}
#endif /* BYTE_ORDER */
void * sdp_open (bdaddr_t const *l, bdaddr_t const *r);
void * sdp_open_local (void);
int32_t sdp_close (void *xs);
int32_t sdp_error (void *xs);
int32_t sdp_search (void *xs,
u_int32_t plen, u_int16_t const *pp,
u_int32_t alen, u_int32_t const *ap,
u_int32_t vlen, sdp_attr_t *vp);
char const * const sdp_attr2desc (u_int16_t attr);
char const * const sdp_uuid2desc (u_int16_t uuid);
void sdp_print (u_int32_t level, u_int8_t const *start,
u_int8_t const *end);
__END_DECLS
#endif /* ndef _SDP_H_ */

383
lib/libsdp/search.c Normal file
View file

@ -0,0 +1,383 @@
/*
* search.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: search.c,v 1.2 2003/09/04 22:12:13 max Exp $
* $FreeBSD$
*/
#include <sys/uio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <bluetooth.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sdp-int.h>
#include <sdp.h>
int32_t
sdp_search(void *xss,
u_int32_t plen, u_int16_t const *pp,
u_int32_t alen, u_int32_t const *ap,
u_int32_t vlen, sdp_attr_t *vp)
{
struct sdp_xpdu {
sdp_pdu_t pdu;
u_int16_t len;
} __attribute__ ((packed)) xpdu;
sdp_session_p ss = (sdp_session_p) xss;
u_int8_t *req = NULL, *rsp = NULL, *rsp_tmp = NULL;
int32_t type, len;
if (ss == NULL)
return (-1);
if (ss->req == NULL || ss->rsp == NULL ||
plen == 0 || pp == NULL || alen == 0 || ap == NULL) {
ss->error = EINVAL;
return (-1);
}
/* Calculate length of the request */
req = ss->req;
plen = plen * (sizeof(pp[0]) + 1);
alen = alen * (sizeof(ap[0]) + 1);
len = plen + sizeof(u_int8_t) + sizeof(u_int16_t) +
/* ServiceSearchPattern */
sizeof(u_int16_t) +
/* MaximumAttributeByteCount */
alen + sizeof(u_int8_t) + sizeof(u_int16_t);
/* AttributeIDList */
if (ss->req_e - req < len) {
ss->error = ENOBUFS;
return (-1);
}
/* Put ServiceSearchPattern */
SDP_PUT8(SDP_DATA_SEQ16, req);
SDP_PUT16(plen, req);
for (; plen > 0; pp ++, plen -= (sizeof(pp[0]) + 1)) {
SDP_PUT8(SDP_DATA_UUID16, req);
SDP_PUT16(*pp, req);
}
/* Put MaximumAttributeByteCount */
SDP_PUT16(0xffff, req);
/* Put AttributeIDList */
SDP_PUT8(SDP_DATA_SEQ16, req);
SDP_PUT16(alen, req);
for (; alen > 0; ap ++, alen -= (sizeof(ap[0]) + 1)) {
SDP_PUT8(SDP_DATA_UINT32, req);
SDP_PUT32(*ap, req);
}
/* Submit ServiceSearchAttributeRequest and wait for response */
ss->cslen = 0;
rsp = ss->rsp;
do {
struct iovec iov[2];
u_int8_t *req_cs = req;
/* Add continuation state (if any) */
if (ss->req_e - req_cs < ss->cslen + 1) {
ss->error = ENOBUFS;
return (-1);
}
SDP_PUT8(ss->cslen, req_cs);
if (ss->cslen > 0) {
memcpy(req_cs, ss->cs, ss->cslen);
req_cs += ss->cslen;
}
/* Prepare SDP PDU header */
xpdu.pdu.pid = SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
xpdu.pdu.tid = htons(ss->tid);
xpdu.pdu.len = htons(req_cs - ss->req);
/* Submit request */
iov[0].iov_base = (void *) &xpdu;
iov[0].iov_len = sizeof(xpdu.pdu);
iov[1].iov_base = (void *) ss->req;
iov[1].iov_len = req_cs - ss->req;
len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0]));
if (len < 0) {
ss->error = errno;
return (-1);
}
/* Read response */
iov[0].iov_base = (void *) &xpdu;
iov[0].iov_len = sizeof(xpdu);
iov[1].iov_base = (void *) rsp;
iov[1].iov_len = ss->imtu;
len = readv(ss->s, iov, sizeof(iov)/sizeof(iov[0]));
if (len < 0) {
ss->error = errno;
return (-1);
}
if (len < sizeof(xpdu)) {
ss->error = ENOMSG;
return (-1);
}
xpdu.pdu.tid = ntohs(xpdu.pdu.tid);
xpdu.pdu.len = ntohs(xpdu.pdu.len);
xpdu.len = ntohs(xpdu.len);
if (xpdu.pdu.pid == SDP_PDU_ERROR_RESPONSE ||
xpdu.pdu.tid != ss->tid ||
xpdu.len > xpdu.pdu.len) {
ss->error = EIO;
return (-1);
}
/* Save continuation state (if any) */
ss->cslen = rsp[xpdu.len];
if (ss->cslen > 0) {
if (ss->cslen > sizeof(ss->cs)) {
ss->error = ENOBUFS;
return (-1);
}
memcpy(ss->cs, rsp + xpdu.len + 1, ss->cslen);
/*
* Ensure that we always have ss->imtu bytes
* available in the ss->rsp buffer
*/
if (ss->rsp_e - rsp <= ss->imtu) {
u_int32_t size, offset;
size = ss->rsp_e - ss->rsp + ss->imtu;
offset = rsp - ss->rsp;
rsp_tmp = realloc(ss->rsp, size);
if (rsp_tmp == NULL) {
ss->error = ENOMEM;
return (-1);
}
ss->rsp = rsp_tmp;
ss->rsp_e = ss->rsp + size;
rsp = ss->rsp + offset;
}
}
rsp += xpdu.len;
ss->tid ++;
} while (ss->cslen > 0);
/*
* If we got here then we have completed SDP transaction and now
* we must populate attribute values into vp array. At this point
* ss->rsp points to the beginning of the response and rsp points
* to the end of the response.
*
* From Bluetooth v1.1 spec page 364
*
* The AttributeLists is a data element sequence where each element
* in turn is a data element sequence representing an attribute list.
* Each attribute list contains attribute IDs and attribute values
* from one service record. The first element in each attribute list
* contains the attribute ID of the first attribute to be returned for
* that service record. The second element in each attribute list
* contains the corresponding attribute value. Successive pairs of
* elements in each attribute list contain additional attribute ID
* and value pairs. Only attributes that have non-null values within
* the service record and whose attribute IDs were specified in the
* SDP_ServiceSearchAttributeRequest are contained in the AttributeLists
* Neither an attribute ID nor attribute value is placed in
* AttributeLists for attributes in the service record that have no
* value. Within each attribute list, the attributes are listed in
* ascending order of attribute ID value.
*/
if (vp == NULL)
goto done;
rsp_tmp = ss->rsp;
/* Skip the first SEQ */
SDP_GET8(type, rsp_tmp);
switch (type) {
case SDP_DATA_SEQ8:
SDP_GET8(len, rsp_tmp);
break;
case SDP_DATA_SEQ16:
SDP_GET16(len, rsp_tmp);
break;
case SDP_DATA_SEQ32:
SDP_GET32(len, rsp_tmp);
break;
default:
ss->error = ENOATTR;
return (-1);
/* NOT REACHED */
}
for (; rsp_tmp < rsp && vlen > 0; ) {
/* Get set of attributes for the next record */
SDP_GET8(type, rsp_tmp);
switch (type) {
case SDP_DATA_SEQ8:
SDP_GET8(len, rsp_tmp);
break;
case SDP_DATA_SEQ16:
SDP_GET16(len, rsp_tmp);
break;
case SDP_DATA_SEQ32:
SDP_GET32(len, rsp_tmp);
break;
default:
ss->error = ENOATTR;
return (-1);
/* NOT REACHED */
}
/* Now rsp_tmp points to list of (attr,value) pairs */
for (; len > 0 && vlen > 0; vp ++, vlen --) {
/* Attribute */
SDP_GET8(type, rsp_tmp);
if (type != SDP_DATA_UINT16) {
ss->error = ENOATTR;
return (-1);
}
SDP_GET16(vp->attr, rsp_tmp);
/* Attribute value */
switch (rsp_tmp[0]) {
case SDP_DATA_NIL:
alen = 0;
break;
case SDP_DATA_UINT8:
case SDP_DATA_INT8:
case SDP_DATA_BOOL:
alen = sizeof(u_int8_t);
break;
case SDP_DATA_UINT16:
case SDP_DATA_INT16:
case SDP_DATA_UUID16:
alen = sizeof(u_int16_t);
break;
case SDP_DATA_UINT32:
case SDP_DATA_INT32:
case SDP_DATA_UUID32:
alen = sizeof(u_int32_t);
break;
case SDP_DATA_UINT64:
case SDP_DATA_INT64:
alen = sizeof(u_int64_t);
break;
case SDP_DATA_UINT128:
case SDP_DATA_INT128:
case SDP_DATA_UUID128:
alen = sizeof(u_int128_t);
break;
case SDP_DATA_STR8:
case SDP_DATA_URL8:
case SDP_DATA_SEQ8:
case SDP_DATA_ALT8:
alen = rsp_tmp[1] + sizeof(u_int8_t);
break;
case SDP_DATA_STR16:
case SDP_DATA_URL16:
case SDP_DATA_SEQ16:
case SDP_DATA_ALT16:
alen = ((u_int16_t)rsp_tmp[1] << 8)
| ((u_int16_t)rsp_tmp[2]);
alen += sizeof(u_int16_t);
break;
case SDP_DATA_STR32:
case SDP_DATA_URL32:
case SDP_DATA_SEQ32:
case SDP_DATA_ALT32:
alen = ((u_int32_t)rsp_tmp[1] << 24)
| ((u_int32_t)rsp_tmp[2] << 16)
| ((u_int32_t)rsp_tmp[3] << 8)
| ((u_int32_t)rsp_tmp[4]);
alen += sizeof(u_int32_t);
break;
default:
ss->error = ENOATTR;
return (-1);
/* NOT REACHED */
}
alen += sizeof(u_int8_t);
if (vp->value != NULL) {
if (alen <= vp->vlen) {
vp->flags = SDP_ATTR_OK;
vp->vlen = alen;
} else
vp->flags = SDP_ATTR_TRUNCATED;
memcpy(vp->value, rsp_tmp, vp->vlen);
} else
vp->flags = SDP_ATTR_INVALID;
len -= (
sizeof(u_int8_t) + sizeof(u_int16_t) +
alen
);
rsp_tmp += alen;
}
}
done:
ss->error = 0;
return (0);
}

174
lib/libsdp/session.c Normal file
View file

@ -0,0 +1,174 @@
/*
* session.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: session.c,v 1.2 2003/09/04 22:12:13 max Exp $
* $FreeBSD$
*/
#include <bluetooth.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sdp-int.h>
#include <sdp.h>
void *
sdp_open(bdaddr_t const *l, bdaddr_t const *r)
{
sdp_session_p ss = NULL;
struct sockaddr_l2cap sa;
socklen_t size;
if ((ss = calloc(1, sizeof(*ss))) == NULL)
goto fail;
if (l == NULL || r == NULL) {
ss->error = EINVAL;
goto fail;
}
ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
if (ss->s < 0) {
ss->error = errno;
goto fail;
}
sa.l2cap_len = sizeof(sa);
sa.l2cap_family = AF_BLUETOOTH;
sa.l2cap_psm = 0;
memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr));
if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
ss->error = errno;
goto fail;
}
sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP);
memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr));
if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
ss->error = errno;
goto fail;
}
size = sizeof(ss->omtu);
if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) {
ss->error = errno;
goto fail;
}
if ((ss->req = malloc(ss->omtu)) == NULL) {
ss->error = ENOMEM;
goto fail;
}
ss->req_e = ss->req + ss->omtu;
size = sizeof(ss->imtu);
if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) {
ss->error = errno;
goto fail;
}
if ((ss->rsp = malloc(ss->imtu)) == NULL) {
ss->error = ENOMEM;
goto fail;
}
ss->rsp_e = ss->rsp + ss->imtu;
ss->error = 0;
fail:
return ((void *) ss);
}
void *
sdp_open_local(void)
{
sdp_session_p ss = NULL;
struct sockaddr_un sa;
if ((ss = calloc(1, sizeof(*ss))) == NULL)
goto fail;
ss->s = socket(PF_UNIX, SOCK_STREAM, 0);
if (ss->s < 0) {
ss->error = errno;
goto fail;
}
sa.sun_len = sizeof(sa);
sa.sun_family = AF_UNIX;
strlcpy(sa.sun_path, SDP_UNSOCK_PATH, sizeof(sa.sun_path));
if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
ss->error = errno;
goto fail;
}
ss->flags |= SDP_SESSION_LOCAL;
ss->imtu = ss->omtu = SDP_UNSOCK_MTU;
if ((ss->req = malloc(ss->omtu)) == NULL) {
ss->error = ENOMEM;
goto fail;
}
ss->req_e = ss->req + ss->omtu;
if ((ss->rsp = malloc(ss->imtu)) == NULL) {
ss->error = ENOMEM;
goto fail;
}
ss->rsp_e = ss->rsp + ss->imtu;
ss->error = 0;
fail:
return ((void *) ss);
}
int32_t
sdp_close(void *xss)
{
sdp_session_p ss = (sdp_session_p) xss;
if (ss != NULL) {
if (ss->s >= 0)
close(ss->s);
if (ss->req != NULL)
free(ss->req);
if (ss->rsp != NULL)
free(ss->rsp);
memset(ss, 0, sizeof(*ss));
free(ss);
}
return (0);
}
int32_t
sdp_error(void *xss)
{
sdp_session_p ss = (sdp_session_p) xss;
return ((ss != NULL)? ss->error : EINVAL);
}

439
lib/libsdp/util.c Normal file
View file

@ -0,0 +1,439 @@
/*
* util.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: util.c,v 1.5 2003/09/08 02:29:35 max Exp $
* $FreeBSD$
*/
#include <bluetooth.h>
#include <stdio.h>
#include <sdp.h>
/*
* SDP attribute description
*/
struct sdp_attr_desc {
u_int32_t attr;
char const *desc;
};
typedef struct sdp_attr_desc sdp_attr_desc_t;
typedef struct sdp_attr_desc * sdp_attr_desc_p;
static sdp_attr_desc_t sdp_uuids_desc[] = {
{ SDP_UUID_PROTOCOL_SDP, "SDP", },
{ SDP_UUID_PROTOCOL_UDP, "UDP", },
{ SDP_UUID_PROTOCOL_RFCOMM, "RFCOMM", },
{ SDP_UUID_PROTOCOL_TCP, "TCP", },
{ SDP_UUID_PROTOCOL_TCS_BIN, "TCS BIN", },
{ SDP_UUID_PROTOCOL_TCS_AT, "TCS AT", },
{ SDP_UUID_PROTOCOL_OBEX, "OBEX", },
{ SDP_UUID_PROTOCOL_IP, "IP", },
{ SDP_UUID_PROTOCOL_FTP, "FTP", },
{ SDP_UUID_PROTOCOL_HTTP, "HTTP", },
{ SDP_UUID_PROTOCOL_WSP, "WSP", },
{ SDP_UUID_PROTOCOL_BNEP, "BNEP", },
{ SDP_UUID_PROTOCOL_UPNP, "UPNP", },
{ SDP_UUID_PROTOCOL_HIDP, "HIDP", },
{ SDP_UUID_PROTOCOL_HARDCOPY_CONTROL_CHANNEL, "Hardcopy Control Channel", },
{ SDP_UUID_PROTOCOL_HARDCOPY_DATA_CHANNEL, "Hardcopy Data Channel", },
{ SDP_UUID_PROTOCOL_HARDCOPY_NOTIFICATION, "Hardcopy Notification", },
{ SDP_UUID_PROTOCOL_AVCTP, "AVCTP", },
{ SDP_UUID_PROTOCOL_AVDTP, "AVDTP", },
{ SDP_UUID_PROTOCOL_CMPT, "CMPT", },
{ SDP_UUID_PROTOCOL_UDI_C_PLANE, "UDI C-Plane", },
{ SDP_UUID_PROTOCOL_L2CAP, "L2CAP", },
/* Service Class IDs/Bluetooth Profile IDs */
{ SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, "Service Discovery Server", },
{ SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR, "Browse Group Descriptor", },
{ SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, "Public Browse Group", },
{ SDP_SERVICE_CLASS_SERIAL_PORT, "Serial Port", },
{ SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP, "LAN Access Using PPP", },
{ SDP_SERVICE_CLASS_DIALUP_NETWORKING, "DailUp Networking", },
{ SDP_SERVICE_CLASS_IR_MC_SYNC, "IrMC Sync", },
{ SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH, "OBEX Object Push", },
{ SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER, "OBEX File Transfer", },
{ SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND, "IrMC Sync Command", },
{ SDP_SERVICE_CLASS_HEADSET, "Headset", },
{ SDP_SERVICE_CLASS_CORDLESS_TELEPHONY, "Cordless Telephony", },
{ SDP_SERVICE_CLASS_AUDIO_SOURCE, "Audio Source", },
{ SDP_SERVICE_CLASS_AUDIO_SINK, "Audio Sink", },
{ SDP_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET, "A/V Remote Control Target", },
{ SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION, "Advanced Audio Distribution", },
{ SDP_SERVICE_CLASS_AV_REMOTE_CONTROL, "A/V Remote Control", },
{ SDP_SERVICE_CLASS_VIDEO_CONFERENCING, "Video Conferencing", },
{ SDP_SERVICE_CLASS_INTERCOM, "Intercom", },
{ SDP_SERVICE_CLASS_FAX, "Fax", },
{ SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY, "Headset Audio Gateway", },
{ SDP_SERVICE_CLASS_WAP, "WAP", },
{ SDP_SERVICE_CLASS_WAP_CLIENT, "WAP Client", },
{ SDP_SERVICE_CLASS_PANU, "PANU", },
{ SDP_SERVICE_CLASS_NAP, "Network Access Point", },
{ SDP_SERVICE_CLASS_GN, "GN", },
{ SDP_SERVICE_CLASS_DIRECT_PRINTING, "Direct Printing", },
{ SDP_SERVICE_CLASS_REFERENCE_PRINTING, "Reference Printing", },
{ SDP_SERVICE_CLASS_IMAGING, "Imaging", },
{ SDP_SERVICE_CLASS_IMAGING_RESPONDER, "Imaging Responder", },
{ SDP_SERVICE_CLASS_IMAGING_AUTOMATIC_ARCHIVE, "Imaging Automatic Archive", },
{ SDP_SERVICE_CLASS_IMAGING_REFERENCED_OBJECTS, "Imaging Referenced Objects", },
{ SDP_SERVICE_CLASS_HANDSFREE, "Handsfree", },
{ SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY, "Handsfree Audio Gateway", },
{ SDP_SERVICE_CLASS_DIRECT_PRINTING_REFERENCE_OBJECTS, "Direct Printing Reference Objects", },
{ SDP_SERVICE_CLASS_REFLECTED_UI, "Reflected UI", },
{ SDP_SERVICE_CLASS_BASIC_PRINTING, "Basic Printing", },
{ SDP_SERVICE_CLASS_PRINTING_STATUS, "Printing Status", },
{ SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE, "Human Interface Device", },
{ SDP_SERVICE_CLASS_HARDCOPY_CABLE_REPLACEMENT, "Hardcopy Cable Replacement", },
{ SDP_SERVICE_CLASS_HCR_PRINT, "HCR Print", },
{ SDP_SERVICE_CLASS_HCR_SCAN, "HCR Scan", },
{ SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS, "Common ISDN Access", },
{ SDP_SERVICE_CLASS_VIDEO_CONFERENCING_GW, "Video Conferencing Gateway", },
{ SDP_SERVICE_CLASS_UDI_MT, "UDI MT", },
{ SDP_SERVICE_CLASS_UDI_TA, "UDI TA", },
{ SDP_SERVICE_CLASS_AUDIO_VIDEO, "Audio/Video", },
{ SDP_SERVICE_CLASS_SIM_ACCESS, "SIM Access", },
{ SDP_SERVICE_CLASS_PNP_INFORMATION, "PNP Information", },
{ SDP_SERVICE_CLASS_GENERIC_NETWORKING, "Generic Networking", },
{ SDP_SERVICE_CLASS_GENERIC_FILE_TRANSFER, "Generic File Transfer", },
{ SDP_SERVICE_CLASS_GENERIC_AUDIO, "Generic Audio", },
{ SDP_SERVICE_CLASS_GENERIC_TELEPHONY, "Generic Telephony", },
{ SDP_SERVICE_CLASS_UPNP, "UPNP", },
{ SDP_SERVICE_CLASS_UPNP_IP, "UPNP IP", },
{ SDP_SERVICE_CLASS_ESDP_UPNP_IP_PAN, "ESDP UPNP IP PAN", },
{ SDP_SERVICE_CLASS_ESDP_UPNP_IP_LAP, "ESDP UPNP IP LAP", },
{ SDP_SERVICE_CLASS_ESDP_UPNP_L2CAP, "ESDP UPNP L2CAP", },
{ 0xffff, NULL, }
};
static sdp_attr_desc_t sdp_attrs_desc[] = {
{ SDP_ATTR_SERVICE_RECORD_HANDLE,
"Record handle",
},
{ SDP_ATTR_SERVICE_CLASS_ID_LIST,
"Service Class ID list",
},
{ SDP_ATTR_SERVICE_RECORD_STATE,
"Service Record State",
},
{ SDP_ATTR_SERVICE_ID,
"Service ID",
},
{ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
"Protocol Descriptor List",
},
{ SDP_ATTR_BROWSE_GROUP_LIST,
"Browse Group List",
},
{ SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST,
"Language Base Attribute ID List",
},
{ SDP_ATTR_SERVICE_INFO_TIME_TO_LIVE,
"Service Info Time-To-Live",
},
{ SDP_ATTR_SERVICE_AVAILABILITY,
"Service Availability",
},
{ SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
"Bluetooh Profile Descriptor List",
},
{ SDP_ATTR_DOCUMENTATION_URL,
"Documentation URL",
},
{ SDP_ATTR_CLIENT_EXECUTABLE_URL,
"Client Executable URL",
},
{ SDP_ATTR_ICON_URL,
"Icon URL",
},
{ SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS,
"Additional Protocol Descriptor Lists" },
{ SDP_ATTR_GROUP_ID,
/*SDP_ATTR_IP_SUBNET,
SDP_ATTR_VERSION_NUMBER_LIST*/
"Group ID/IP Subnet/Version Number List",
},
{ SDP_ATTR_SERVICE_DATABASE_STATE,
"Service Database State",
},
{ SDP_ATTR_SERVICE_VERSION,
"Service Version",
},
{ SDP_ATTR_EXTERNAL_NETWORK,
/*SDP_ATTR_NETWORK,
SDP_ATTR_SUPPORTED_DATA_STORES_LIST*/
"External Network/Network/Supported Data Stores List",
},
{ SDP_ATTR_FAX_CLASS1_SUPPORT,
/*SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL*/
"Fax Class1 Support/Remote Audio Volume Control",
},
{ SDP_ATTR_FAX_CLASS20_SUPPORT,
/*SDP_ATTR_SUPPORTED_FORMATS_LIST*/
"Fax Class20 Support/Supported Formats List",
},
{ SDP_ATTR_FAX_CLASS2_SUPPORT,
"Fax Class2 Support",
},
{ SDP_ATTR_AUDIO_FEEDBACK_SUPPORT,
"Audio Feedback Support",
},
{ SDP_ATTR_NETWORK_ADDRESS,
"Network Address",
},
{ SDP_ATTR_WAP_GATEWAY,
"WAP Gateway",
},
{ SDP_ATTR_HOME_PAGE_URL,
"Home Page URL",
},
{ SDP_ATTR_WAP_STACK_TYPE,
"WAP Stack Type",
},
{ SDP_ATTR_SECURITY_DESCRIPTION,
"Security Description",
},
{ SDP_ATTR_NET_ACCESS_TYPE,
"Net Access Type",
},
{ SDP_ATTR_MAX_NET_ACCESS_RATE,
"Max Net Access Rate",
},
{ SDP_ATTR_IPV4_SUBNET,
"IPv4 Subnet",
},
{ SDP_ATTR_IPV6_SUBNET,
"IPv6 Subnet",
},
{ SDP_ATTR_SUPPORTED_CAPABALITIES,
"Supported Capabalities",
},
{ SDP_ATTR_SUPPORTED_FEATURES,
"Supported Features",
},
{ SDP_ATTR_SUPPORTED_FUNCTIONS,
"Supported Functions",
},
{ SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY,
"Total Imaging Data Capacity",
},
{ 0xffff, NULL, }
};
char const * const
sdp_attr2desc(u_int16_t attr)
{
register sdp_attr_desc_p a = sdp_attrs_desc;
for (; a->desc != NULL; a++)
if (attr == a->attr)
break;
return ((a->desc != NULL)? a->desc : "Unknown");
}
char const * const
sdp_uuid2desc(u_int16_t uuid)
{
register sdp_attr_desc_p a = sdp_uuids_desc;
for (; a->desc != NULL; a++)
if (uuid == a->attr)
break;
return ((a->desc != NULL)? a->desc : "Unknown");
}
void
sdp_print(u_int32_t level, u_int8_t const *start, u_int8_t const *end)
{
union {
int8_t int8;
int16_t int16;
int32_t int32;
int64_t int64;
int128_t int128;
uint8_t uint8;
uint16_t uint16;
uint32_t uint32;
uint64_t uint64;
} value;
u_int8_t type;
u_int32_t i;
if (start == NULL || end == NULL)
return;
while (start < end) {
for (i = 0; i < level; i++)
printf("\t");
SDP_GET8(type, start);
switch (type) {
case SDP_DATA_NIL:
printf("nil\n");
break;
case SDP_DATA_UINT8:
SDP_GET8(value.uint8, start);
printf("uint8 %u\n", value.uint8);
break;
case SDP_DATA_UINT16:
SDP_GET16(value.uint16, start);
printf("uint16 %u\n", value.uint16);
break;
case SDP_DATA_UINT32:
SDP_GET32(value.uint32, start);
printf("uint32 %u\n", value.uint32);
break;
case SDP_DATA_UINT64:
SDP_GET64(value.uint64, start);
printf("uint64 %llu\n", value.uint64);
break;
case SDP_DATA_UINT128:
case SDP_DATA_INT128:
case SDP_DATA_UUID128:
SDP_GET128(&value.int128, start);
printf("int128/uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
*(u_int32_t *)&value.int128.b[0],
*(u_int16_t *)&value.int128.b[4],
*(u_int16_t *)&value.int128.b[6],
*(u_int16_t *)&value.int128.b[8],
*(u_int16_t *)&value.int128.b[10],
*(u_int32_t *)&value.int128.b[12]);
break;
case SDP_DATA_INT8:
SDP_GET8(value.int8, start);
printf("int8 %d\n", value.int8);
break;
case SDP_DATA_INT16:
SDP_GET16(value.int16, start);
printf("int16 %d\n", value.int16);
break;
case SDP_DATA_INT32:
SDP_GET32(value.int32, start);
printf("int32 %d\n", value.int32);
break;
case SDP_DATA_INT64:
SDP_GET64(value.int64, start);
printf("int64 %lld\n", value.int64);
break;
case SDP_DATA_UUID16:
SDP_GET16(value.uint16, start);
printf("uuid16 %#4.4x - %s\n", value.uint16,
sdp_uuid2desc(value.uint16));
break;
case SDP_DATA_UUID32:
SDP_GET32(value.uint32, start);
printf("uuid32 %#8.8x\n", value.uint32);
break;
case SDP_DATA_STR8:
SDP_GET8(value.uint8, start);
printf("str8 %*.*s\n", value.uint8, value.uint8, start);
start += value.uint8;
break;
case SDP_DATA_STR16:
SDP_GET16(value.uint16, start);
printf("str16 %*.*s\n", value.uint16, value.uint16, start);
start += value.uint16;
break;
case SDP_DATA_STR32:
SDP_GET32(value.uint32, start);
printf("str32 %*.*s\n", value.uint32, value.uint32, start);
start += value.uint32;
break;
case SDP_DATA_BOOL:
SDP_GET8(value.uint8, start);
printf("bool %d\n", value.uint8);
break;
case SDP_DATA_SEQ8:
SDP_GET8(value.uint8, start);
printf("seq8 %d\n", value.uint8);
sdp_print(level + 1, start, start + value.uint8);
start += value.uint8;
break;
case SDP_DATA_SEQ16:
SDP_GET16(value.uint16, start);
printf("seq16 %d\n", value.uint16);
sdp_print(level + 1, start, start + value.uint16);
start += value.uint16;
break;
case SDP_DATA_SEQ32:
SDP_GET32(value.uint32, start);
printf("seq32 %d\n", value.uint32);
sdp_print(level + 1, start, start + value.uint32);
start += value.uint32;
break;
case SDP_DATA_ALT8:
SDP_GET8(value.uint8, start);
printf("alt8 %d\n", value.uint8);
sdp_print(level + 1, start, start + value.uint8);
start += value.uint8;
break;
case SDP_DATA_ALT16:
SDP_GET16(value.uint16, start);
printf("alt16 %d\n", value.uint16);
sdp_print(level + 1, start, start + value.uint16);
start += value.uint16;
break;
case SDP_DATA_ALT32:
SDP_GET32(value.uint32, start);
printf("alt32 %d\n", value.uint32);
sdp_print(level + 1, start, start + value.uint32);
start += value.uint32;
break;
case SDP_DATA_URL8:
SDP_GET8(value.uint8, start);
printf("url8 %*.*s\n", value.uint8, value.uint8, start);
start += value.uint8;
break;
case SDP_DATA_URL16:
SDP_GET16(value.uint16, start);
printf("url16 %*.*s\n", value.uint16, value.uint16, start);
start += value.uint16;
break;
case SDP_DATA_URL32:
SDP_GET32(value.uint32, start);
printf("url32 %*.*s\n", value.uint32, value.uint32, start);
start += value.uint32;
break;
default:
printf("unknown data type: %#02x\n", *start ++);
break;
}
}
}

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_bluetooth.4,v 1.2 2003/04/26 22:38:25 max Exp $
.\" $Id: ng_bluetooth.4,v 1.3 2003/05/21 19:37:35 max Exp $
.\" $FreeBSD$
.\"
.Dd November 9, 2002

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_bt3c.4,v 1.1 2002/11/24 19:37:54 max Exp $
.\" $Id: ng_bt3c.4,v 1.3 2003/09/14 23:28:51 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_btsocket.4,v 1.6 2003/03/18 00:09:34 max Exp $
.\" $Id: ng_btsocket.4,v 1.7 2003/05/21 19:37:35 max Exp $
.\" $FreeBSD$
.\"
.Dd July 8, 2002
@ -186,6 +186,10 @@ Returns list of active baseband connections (i.e. ACL links) for the L2CAP
node.
.It Dv SIOC_L2CAP_NODE_GET_CHAN_LIST
Returns list of active channels for the L2CAP node.
.It Dv SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO
Returns current value of the auto disconnect timeout for the L2CAP node.
.It Dv SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO
Sets current value of the auto disconnect timeout for the L2CAP node.
.It Dv SIOC_L2CAP_L2CA_PING
Issues L2CAP
.Dv ECHO_REQUEST .

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_h4.4,v 1.1 2002/11/24 19:37:54 max Exp $
.\" $Id: ng_h4.4,v 1.2 2003/05/21 19:37:35 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_hci.4,v 1.2 2003/03/18 00:09:34 max Exp $
.\" $Id: ng_hci.4,v 1.3 2003/05/21 19:37:35 max Exp $
.\" $FreeBSD$
.\"
.Dd June 25, 2002

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_l2cap.4,v 1.2 2003/04/28 20:16:29 max Exp $
.\" $Id: ng_l2cap.4,v 1.4 2003/09/14 23:37:52 max Exp $
.\" $FreeBSD$
.\"
.Dd July 4, 2002
@ -58,7 +58,7 @@ The ACL link between two units is set up.
The Baseband provides orderly
delivery of data packets, although there might be individual packet corruption
and duplicates.
No more than 1 ACL link exists between any two devices.
No more than one ACL link exists between any two devices.
.It
The Baseband always provides the impression of full-duplex communication
channels.
@ -220,7 +220,7 @@ Upper layer protocol upstream hook.
Usually the Bluetooth L2CAP socket layer is connected to the hook.
.It Dv ctl
Control hook.
Usually Bluetooth raw L2CAP sockets layer is connected to the hook.
Usually the Bluetooth raw L2CAP sockets layer is connected to the hook.
.El
.Sh INTERFACE TO THE UPPER LAYER PROTOCOLS (L2CA CONTROL MESSAGES)
Bluetooth specification says that L2CA request must block until response

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ng_ubt.4,v 1.2 2003/03/22 23:44:32 max Exp $
.\" $Id: ng_ubt.4,v 1.3 2003/05/21 19:37:35 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: ubtbcmfw.4,v 1.1 2003/04/28 17:09:46 max Exp $
.\" $Id: ubtbcmfw.4,v 1.3 2003/05/21 19:37:35 max Exp $
.\" $FreeBSD$
.\"
.Dd April 28, 2003

View file

@ -2,7 +2,8 @@
# $FreeBSD$
#MISSING: dump.5 plot.5
MAN= a.out.5 acct.5 core.5 config.5 devfs.5 device.hints.5 \
MAN= a.out.5 acct.5 bluetooth.hosts.5 bluetooth.protocols.5 \
core.5 config.5 devfs.5 device.hints.5 \
dir.5 disktab.5 drivers.conf.5 \
elf.5 ethers.5 fbtab.5 fdescfs.5 forward.5 fs.5 fstab.5 group.5 \
hesiod.conf.5 \

View file

@ -0,0 +1,63 @@
.\" 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.hosts.5,v 1.5 2003/05/20 22:52:39 max Exp $
.\" $FreeBSD$
.\"
.Dd May 8, 2003
.Dt BLUETOOTH.HOSTS 5
.Os
.Sh NAME
.Nm /etc/bluetooth/hosts
.Nd Bluetooth host name database
.Sh DESCRIPTION
The
.Nm
file contains information regarding the known Bluetooth hosts.
For each Bluetooth host a single line should be present with the
following information:
.Bd -unfilled -offset indent
Bluetooth address
official host name
aliases
.Ed
.Pp
Items are separated by any number of blanks and/or tab characters.
A
.Dq #
indicates the beginning of a comment; characters up to the end of the line are
not interpreted by routines which search the file.
.Pp
Bluetooth addresses are specified as six hex bytes separated by columns
(BD_ADDR).
Host names may contain any printable character other than a field
delimiter, newline, or comment character.
.Sh FILES
.Bl -tag -width /etc/bluetooth/hosts -compact
.It Pa /etc/bluetooth/hosts
.El
.Sh SEE ALSO
.Xr bluetooth 3
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View file

@ -0,0 +1,62 @@
.\" 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.protocols.5,v 1.1 2003/05/20 22:52:39 max Exp $
.\" $FreeBSD$
.\"
.Dd May 8, 2003
.Dt BLUETOOTH.PROTOCOLS 5
.Os
.Sh NAME
.Nm /etc/bluetooth/protocols
.Nd Bluetooth Protocol Service Multiplexor database
.Sh DESCRIPTION
The
.Nm
file contains information regarding the known Bluetooth Protocol Service
Multiplexor values.
For each Bluetooth Protocol Service Multiplexor a single line should be
present with the following information:
.Bd -unfilled -offset indent
official Protocol Service Multiplexor name
official Protocol Service Multiplexor value
aliases
.Ed
.Pp
Items are separated by any number of blanks and/or tab characters.
A
.Dq #
indicates the beginning of a comment; characters up to the end of the line are
not interpreted by routines which search the file.
.Pp
Bluetooth Protocol Service Multiplexor names may contain any printable
character other than a field delimiter, newline, or comment character.
.Sh FILES
.Bl -tag -width /etc/bluetooth/hosts -compact
.It Pa /etc/bluetooth/protocols
.El
.Sh SEE ALSO
.Xr bluetooth 3
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View file

@ -14,6 +14,7 @@ LIBALIAS?= ${DESTDIR}${LIBDIR}/libalias.a
LIBASN1?= ${DESTDIR}${LIBDIR}/libasn1.a # XXX in secure dist, not base
LIBATM?= ${DESTDIR}${LIBDIR}/libatm.a
LIBBSDXML?= ${DESTDIR}${LIBDIR}/libbsdxml.a
LIBBLUETOOTH?= ${DESTDIR}${LIBDIR}/libbluetooth.a
LIBBZ2?= ${DESTDIR}${LIBDIR}/libbz2.a
LIBC?= ${DESTDIR}${LIBDIR}/libc.a
LIBC_PIC?= ${DESTDIR}${LIBDIR}/libc_pic.a
@ -100,6 +101,7 @@ LIBREADLINE?= ${DESTDIR}${LIBDIR}/libreadline.a
LIBRESOLV?= ${DESTDIR}${LIBDIR}/libresolv.a # XXX doesn't exist
LIBROKEN?= ${DESTDIR}${LIBDIR}/libroken.a # XXX in secure dist, not base
LIBRPCSVC?= ${DESTDIR}${LIBDIR}/librpcsvc.a
LIBSDP?= ${DESTDIR}${LIBDIR}/libsdp.a
LIBSBUF?= ${DESTDIR}${LIBDIR}/libsbuf.a
LIBSMB?= ${DESTDIR}${LIBDIR}/libsmb.a
LIBSSH?= ${DESTDIR}${LIBDIR}/libssh.a # XXX in secure dist, not base

View file

@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/common
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include
KMOD= ng_bluetooth
SRCS= ng_bluetooth.c

View file

@ -3,12 +3,9 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
KMOD= ng_bt3c
SRCS= ng_bt3c_pccard.c bus_if.h card_if.h device_if.h
MAN4= ng_bt3c.4

View file

@ -3,11 +3,9 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
KMOD= ng_h4
SRCS= ng_h4.c
MAN4= ng_h4.4

View file

@ -3,11 +3,9 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/hci
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \
-I${.CURDIR}/../../../../netgraph/bluetooth/hci
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
KMOD= ng_hci
SRCS= ng_hci_main.c ng_hci_cmds.c ng_hci_evnt.c \
ng_hci_ulpi.c ng_hci_misc.c

View file

@ -3,11 +3,9 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/l2cap
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \
-I${.CURDIR}/../../../../netgraph/bluetooth/l2cap
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
KMOD= ng_l2cap
SRCS= ng_l2cap_main.c ng_l2cap_cmds.c ng_l2cap_evnt.c \
ng_l2cap_ulpi.c ng_l2cap_llpi.c ng_l2cap_misc.c

View file

@ -3,10 +3,7 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/socket
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include
KMOD= ng_btsocket
SRCS= ng_btsocket.c \

View file

@ -3,12 +3,9 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
KMOD= ng_ubt
SRCS= ng_ubt.c bus_if.h device_if.h vnode_if.h opt_usb.h
MAN4= ng_ubt.4

View file

@ -3,12 +3,9 @@
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubtbcmfw
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include \
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubtbcmfw
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
KMOD= ubtbcmfw
SRCS= ubtbcmfw.c bus_if.h device_if.h vnode_if.h opt_usb.h
MAN4= ubtbcmfw.4

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_ubt.c,v 1.14 2003/04/14 23:00:50 max Exp $
* $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
* $FreeBSD$
*/
@ -2704,7 +2704,6 @@ ubt_create_device_nodes(ubt_softc_p sc)
Static void
ubt_destroy_device_nodes(ubt_softc_p sc)
{
/*
* Wait for processes to go away. This should be safe as we will not
* call ubt_destroy_device_nodes() from Netgraph unless all devices

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ubtbcmfw.c,v 1.1 2003/04/27 00:20:15 max Exp $
* $Id: ubtbcmfw.c,v 1.3 2003/10/10 19:15:08 max Exp $
* $FreeBSD$
*/

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_hci_cmds.c,v 1.3 2003/04/01 18:15:25 max Exp $
* $Id: ng_hci_cmds.c,v 1.4 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@ -355,11 +355,17 @@ complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
/*
* Now we can remove command timeout, dequeue completed command
* and return command parameters. Note: ng_hci_command_untimeout()
* will drop NG_HCI_UNIT_COMMAND_PENDING flag.
* and return command parameters. ng_hci_command_untimeout will
* drop NG_HCI_UNIT_COMMAND_PENDING flag.
* Note: if ng_hci_command_untimeout() fails (returns non-zero)
* then timeout aready happened and timeout message went info node
* queue. In this case we ignore command completion and pretend
* there is a timeout.
*/
ng_hci_command_untimeout(unit);
if (ng_hci_command_untimeout(unit) != 0)
return (ETIMEDOUT);
NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, *cp);
m_adj(*cp, sizeof(ng_hci_cmd_pkt_t));
@ -373,17 +379,24 @@ complete_command(ng_hci_unit_p unit, int opcode, struct mbuf **cp)
void
ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
{
ng_hci_unit_p unit = (ng_hci_unit_p) arg1;
ng_hci_unit_p unit = NULL;
struct mbuf *m = NULL;
u_int16_t opcode;
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
if (NG_NODE_NOT_VALID(node)) {
printf("%s: Netgraph node is not valid\n", __func__);
return;
}
unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
NG_BT_MBUFQ_DEQUEUE(&unit->cmdq, m);
if (m == NULL) {
KASSERT(0,
("%s: %s - command queue is out of sync!\n",
__func__, NG_NODE_NAME(unit->node)));
NG_HCI_ALERT(
"%s: %s - command queue is out of sync!\n", __func__, NG_NODE_NAME(unit->node));
return;
}
@ -396,18 +409,12 @@ ng_hci_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
__func__, NG_NODE_NAME(unit->node), NG_HCI_OGF(opcode),
NG_HCI_OCF(opcode));
/*
* Try to send more commands
*/
/* Try to send more commands */
NG_HCI_BUFF_CMD_SET(unit->buffer, 1);
unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
ng_hci_send_command(unit);
} else
KASSERT(0,
("%s: %s - no pending command, state=%#x\n",
__func__, NG_NODE_NAME(unit->node), unit->state));
NG_HCI_ALERT(
"%s: %s - no pending command\n", __func__, NG_NODE_NAME(unit->node));
} /* ng_hci_process_command_timeout */
/*
@ -616,6 +623,10 @@ process_hc_baseband_params(ng_hci_unit_p unit, u_int16_t ocf,
while (!LIST_EMPTY(&unit->con_list)) {
con = LIST_FIRST(&unit->con_list);
/* Remove all timeouts (if any) */
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
ng_hci_con_untimeout(con);
/* Connection terminated by local host */
ng_hci_lp_discon_ind(con, 0x16);
ng_hci_free_con(con);

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_hci_evnt.c,v 1.5 2003/04/01 18:15:25 max Exp $
* $Id: ng_hci_evnt.c,v 1.6 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@ -454,7 +454,10 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event)
* Two possible cases:
*
* 1) We have found connection descriptor. That means upper layer has
* requested this connection via LP_CON_REQ message
* requested this connection via LP_CON_REQ message. In this case
* connection must have timeout set. If ng_hci_con_untimeout() fails
* then timeout message already went into node's queue. In this case
* ignore Connection_Complete event and let timeout deal with it.
*
* 2) We do not have connection descriptor. That means upper layer
* nas not requested this connection or (less likely) we gave up
@ -474,8 +477,8 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event)
}
bcopy(&ep->bdaddr, &con->bdaddr, sizeof(con->bdaddr));
} else
ng_hci_con_untimeout(con);
} else if ((error = ng_hci_con_untimeout(con)) != 0)
goto out;
/*
* Update connection descriptor and send notification
@ -543,7 +546,7 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event)
NG_FREE_M(event);
return (error);
} /* com_compl */
} /* con_compl */
/* Connection request event */
static int
@ -617,8 +620,10 @@ con_req(ng_hci_unit_p unit, struct mbuf *event)
ng_hci_con_timeout(con);
error = ng_hci_lp_con_ind(con, ep->uclass);
if (error != 0)
if (error != 0) {
ng_hci_con_untimeout(con);
ng_hci_free_con(con);
}
} else
error = ENOMEM;
}
@ -655,6 +660,11 @@ discon_compl(ng_hci_unit_p unit, struct mbuf *event)
con = ng_hci_con_by_handle(unit, h);
if (con != NULL) {
error = ng_hci_lp_discon_ind(con, ep->reason);
/* Remove all timeouts (if any) */
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
ng_hci_con_untimeout(con);
ng_hci_free_con(con);
} else {
NG_HCI_ALERT(

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_hci_misc.c,v 1.4 2003/04/26 22:35:21 max Exp $
* $Id: ng_hci_misc.c,v 1.5 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@ -51,9 +51,6 @@
******************************************************************************
******************************************************************************/
static void ng_hci_command_queue_timeout (void *);
static void ng_hci_con_queue_timeout (void *);
/*
* Give packet to RAW hook
* Assumes input mbuf is read only.
@ -145,6 +142,10 @@ ng_hci_unit_clean(ng_hci_unit_p unit, int reason)
while (!LIST_EMPTY(&unit->con_list)) {
ng_hci_unit_con_p con = LIST_FIRST(&unit->con_list);
/* Remove all timeouts (if any) */
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
ng_hci_con_untimeout(con);
/*
* Notify upper layer protocol and destroy connection
* descriptor. Do not really care about the result.
@ -253,12 +254,32 @@ ng_hci_new_con(ng_hci_unit_p unit, int link_type)
{
ng_hci_unit_con_p con = NULL;
int num_pkts;
static int fake_con_handle = 0x0f00;
MALLOC(con, ng_hci_unit_con_p, sizeof(*con), M_NETGRAPH_HCI,
M_NOWAIT | M_ZERO);
if (con != NULL) {
con->unit = unit;
con->state = NG_HCI_CON_CLOSED;
/*
* XXX
*
* Assign fake connection handle to the connection descriptor.
* Bluetooth specification marks 0x0f00 - 0x0fff connection
* handles as reserved. We need this fake connection handles
* for timeouts. Connection handle will be passed as argument
* to timeout so when timeout happens we can find the right
* connection descriptor. We can not pass pointers, because
* timeouts are external (to Netgraph) events and there might
* be a race when node/hook goes down and timeout event already
* went into node's queue
*/
con->con_handle = fake_con_handle ++;
if (fake_con_handle > 0x0fff)
fake_con_handle = 0x0f00;
con->link_type = link_type;
if (con->link_type == NG_HCI_LINK_ACL)
@ -285,10 +306,6 @@ ng_hci_free_con(ng_hci_unit_con_p con)
{
LIST_REMOVE(con, next);
/* Remove all timeouts (if any) */
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
ng_hci_con_untimeout(con);
/*
* If we have pending packets then assume that Host Controller has
* flushed these packets and we can free them too
@ -340,103 +357,84 @@ ng_hci_con_by_bdaddr(ng_hci_unit_p unit, bdaddr_p bdaddr, int link_type)
/*
* Set HCI command timeout
* XXX FIXME: check unit->cmd_timo.callout != NULL
*/
void
int
ng_hci_command_timeout(ng_hci_unit_p unit)
{
if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING)) {
NG_NODE_REF(unit->node);
unit->state |= NG_HCI_UNIT_COMMAND_PENDING;
unit->cmd_timo = timeout(ng_hci_command_queue_timeout, unit,
bluetooth_hci_command_timeout());
} else
KASSERT(0,
("%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node)));
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING)
panic(
"%s: %s - Duplicated command timeout!\n", __func__, NG_NODE_NAME(unit->node));
unit->state |= NG_HCI_UNIT_COMMAND_PENDING;
unit->cmd_timo = ng_timeout(unit->node, NULL,
bluetooth_hci_command_timeout(),
ng_hci_process_command_timeout, NULL, 0);
return (0);
} /* ng_hci_command_timeout */
/*
* Unset HCI command timeout
*/
void
int
ng_hci_command_untimeout(ng_hci_unit_p unit)
{
if (unit->state & NG_HCI_UNIT_COMMAND_PENDING) {
unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
untimeout(ng_hci_command_queue_timeout, unit, unit->cmd_timo);
NG_NODE_UNREF(unit->node);
} else
KASSERT(0,
("%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node)));
if (!(unit->state & NG_HCI_UNIT_COMMAND_PENDING))
panic(
"%s: %s - No command timeout!\n", __func__, NG_NODE_NAME(unit->node));
if (ng_untimeout(unit->cmd_timo, unit->node) == 0)
return (ETIMEDOUT);
unit->state &= ~NG_HCI_UNIT_COMMAND_PENDING;
return (0);
} /* ng_hci_command_untimeout */
/*
* OK timeout has happend, so queue timeout processing function
*/
static void
ng_hci_command_queue_timeout(void *context)
{
ng_hci_unit_p unit = (ng_hci_unit_p) context;
node_p node = unit->node;
if (NG_NODE_IS_VALID(node))
ng_send_fn(node,NULL,&ng_hci_process_command_timeout,unit,0);
NG_NODE_UNREF(node);
} /* ng_hci_command_queue_timeout */
/*
* Set HCI connection timeout
* XXX FIXME: check unit->cmd_timo.callout != NULL
*/
void
int
ng_hci_con_timeout(ng_hci_unit_con_p con)
{
if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) {
NG_NODE_REF(con->unit->node);
con->flags |= NG_HCI_CON_TIMEOUT_PENDING;
con->con_timo = timeout(ng_hci_con_queue_timeout, con,
bluetooth_hci_connect_timeout());
} else
KASSERT(0,
("%s: %s - Duplicated connection timeout!\n",
__func__, NG_NODE_NAME(con->unit->node)));
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
panic(
"%s: %s - Duplicated connection timeout!\n",
__func__, NG_NODE_NAME(con->unit->node));
con->flags |= NG_HCI_CON_TIMEOUT_PENDING;
con->con_timo = ng_timeout(con->unit->node, NULL,
bluetooth_hci_connect_timeout(),
ng_hci_process_con_timeout, NULL,
con->con_handle);
return (0);
} /* ng_hci_con_timeout */
/*
* Unset HCI connection timeout
*/
void
int
ng_hci_con_untimeout(ng_hci_unit_con_p con)
{
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING) {
con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
untimeout(ng_hci_con_queue_timeout, con, con->con_timo);
NG_NODE_UNREF(con->unit->node);
} else
KASSERT(0,
("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node)));
if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING))
panic(
"%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(con->unit->node));
if (ng_untimeout(con->con_timo, con->unit->node) == 0)
return (ETIMEDOUT);
con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
return (0);
} /* ng_hci_con_untimeout */
/*
* OK timeout has happend, so queue timeout processing function
*/
static void
ng_hci_con_queue_timeout(void *context)
{
ng_hci_unit_con_p con = (ng_hci_unit_con_p) context;
node_p node = con->unit->node;
if (NG_NODE_IS_VALID(node))
ng_send_fn(node, NULL, &ng_hci_process_con_timeout, con, 0);
NG_NODE_UNREF(node);
} /* ng_hci_con_queue_timeout */
#if 0
/*
* Convert numeric error code/reason to a string

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_hci_misc.h,v 1.2 2003/04/26 22:35:21 max Exp $
* $Id: ng_hci_misc.h,v 1.3 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@ -47,10 +47,10 @@ void ng_hci_free_con (ng_hci_unit_con_p);
ng_hci_unit_con_p ng_hci_con_by_handle (ng_hci_unit_p, int);
ng_hci_unit_con_p ng_hci_con_by_bdaddr (ng_hci_unit_p, bdaddr_p, int);
void ng_hci_command_timeout (ng_hci_unit_p);
void ng_hci_command_untimeout (ng_hci_unit_p);
void ng_hci_con_timeout (ng_hci_unit_con_p);
void ng_hci_con_untimeout (ng_hci_unit_con_p);
int ng_hci_command_timeout (ng_hci_unit_p);
int ng_hci_command_untimeout (ng_hci_unit_p);
int ng_hci_con_timeout (ng_hci_unit_con_p);
int ng_hci_con_untimeout (ng_hci_unit_con_p);
#endif /* ndef _NETGRAPH_HCI_MISC_H_ */

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_hci_ulpi.c,v 1.6 2003/04/26 22:35:21 max Exp $
* $Id: ng_hci_ulpi.c,v 1.7 2003/09/08 18:57:51 max Exp $
* $FreeBSD$
*/
@ -195,11 +195,9 @@ ng_hci_lp_acl_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
} break;
default:
KASSERT(0,
("%s: %s - Invalid connection state=%d\n",
__func__, NG_NODE_NAME(unit->node),con->state));
error = EINVAL;
panic(
"%s: %s - Invalid connection state=%d\n",
__func__, NG_NODE_NAME(unit->node), con->state);
break;
}
@ -390,12 +388,10 @@ ng_hci_lp_sco_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
break;
default:
KASSERT(0,
("%s: %s - Inavalid connection state=%d\n",
panic(
"%s: %s - Inavalid connection state=%d\n",
__func__, NG_NODE_NAME(unit->node),
sco_con->state));
error = EINVAL;
sco_con->state);
break;
}
@ -763,10 +759,13 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook)
}
/*
* Remove connection timeout and check connection state
* Remove connection timeout and check connection state.
* Note: if ng_hci_con_untimeout() fails (returns non-zero value) then
* timeout already happened and event went into node's queue.
*/
ng_hci_con_untimeout(con);
if ((error = ng_hci_con_untimeout(con)) != 0)
goto out;
switch (con->state) {
case NG_HCI_CON_W4_LP_CON_RSP:
@ -856,11 +855,9 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook)
break;
default:
KASSERT(0,
("%s: %s - Invalid connection state=%d\n",
__func__, NG_NODE_NAME(unit->node), con->state));
error = EINVAL;
panic(
"%s: %s - Invalid connection state=%d\n",
__func__, NG_NODE_NAME(unit->node), con->state);
break;
}
out:
@ -1150,12 +1147,33 @@ ng_hci_lp_qos_ind(ng_hci_unit_con_p con)
*/
void
ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2)
ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int con_handle)
{
ng_hci_unit_con_p con = (ng_hci_unit_con_p) arg1;
ng_hci_unit_p unit = NULL;
ng_hci_unit_con_p con = NULL;
KASSERT((con->flags & NG_HCI_CON_TIMEOUT_PENDING),
("%s: %s - No connection timeout!\n", __func__, NG_NODE_NAME(node)));
if (NG_NODE_NOT_VALID(node)) {
printf("%s: Netgraph node is not valid\n", __func__);
return;
}
unit = (ng_hci_unit_p) NG_NODE_PRIVATE(node);
con = ng_hci_con_by_handle(unit, con_handle);
if (con == NULL) {
NG_HCI_ALERT(
"%s: %s - could not find connection, handle=%d\n",
__func__, NG_NODE_NAME(node), con_handle);
return;
}
if (!(con->flags & NG_HCI_CON_TIMEOUT_PENDING)) {
NG_HCI_ALERT(
"%s: %s - no pending connection timeout, handle=%d, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(node), con_handle, con->state,
con->flags);
return;
}
con->flags &= ~NG_HCI_CON_TIMEOUT_PENDING;
@ -1181,9 +1199,9 @@ ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2)
break;
default:
KASSERT(0,
("%s: %s - Invalid connection state=%d\n",
__func__, NG_NODE_NAME(node), con->state));
panic(
"%s: %s - Invalid connection state=%d\n",
__func__, NG_NODE_NAME(node), con->state);
break;
}

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_l2cap_cmds.c,v 1.1 2002/11/24 19:47:06 max Exp $
* $Id: ng_l2cap_cmds.c,v 1.2 2003/09/08 19:11:45 max Exp $
* $FreeBSD$
*/
@ -69,7 +69,7 @@ ng_l2cap_con_wakeup(ng_l2cap_con_p con)
TAILQ_FOREACH(cmd, &con->cmd_list, next) {
KASSERT((cmd->con == con),
("%s: %s - invalid connection pointer!\n",
__func__, NG_NODE_NAME(con->l2cap->node)));
__func__, NG_NODE_NAME(con->l2cap->node)));
if (!(cmd->flags & NG_L2CAP_CMD_PENDING))
break;
@ -200,12 +200,9 @@ ng_l2cap_con_wakeup(ng_l2cap_con_p con)
/* XXX FIXME add other commands */
default:
KASSERT(0,
("%s: %s - unknown command code=%d\n",
__func__, NG_NODE_NAME(con->l2cap->node), cmd->code));
ng_l2cap_unlink_cmd(cmd);
ng_l2cap_free_cmd(cmd);
panic(
"%s: %s - unknown command code=%d\n",
__func__, NG_NODE_NAME(con->l2cap->node), cmd->code);
break;
}
} /* ng_l2cap_con_wakeup */
@ -237,7 +234,7 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result)
KASSERT((cmd->con == con),
("%s: %s - invalid connection pointer!\n",
__func__, NG_NODE_NAME(con->l2cap->node)));
__func__, NG_NODE_NAME(l2cap->node)));
switch (cmd->code) {
case NG_L2CAP_CMD_REJ:
@ -280,10 +277,9 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result)
/* XXX FIXME add other commands */
default:
KASSERT(0,
("%s: %s - unexpected command code=%d\n",
__func__, NG_NODE_NAME(con->l2cap->node),
cmd->code));
panic(
"%s: %s - unexpected command code=%d\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->code);
break;
}
@ -314,11 +310,34 @@ ng_l2cap_con_fail(ng_l2cap_con_p con, u_int16_t result)
void
ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
{
ng_l2cap_cmd_p cmd = (ng_l2cap_cmd_p) arg1;
ng_l2cap_p l2cap = NULL;
ng_l2cap_con_p con = NULL;
ng_l2cap_cmd_p cmd = NULL;
u_int16_t con_handle = (arg2 & 0x0ffff);
u_int8_t ident = ((arg2 >> 16) & 0xff);
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command flags flags=%#x!\n",
__func__, NG_NODE_NAME(cmd->con->l2cap->node), cmd->flags));
if (NG_NODE_NOT_VALID(node)) {
printf("%s: Netgraph node is not valid\n", __func__);
return;
}
l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node);
con = ng_l2cap_con_by_handle(l2cap, con_handle);
if (con == NULL) {
NG_L2CAP_ALERT(
"%s: %s - could not find connection, con_handle=%d\n",
__func__, NG_NODE_NAME(node), con_handle);
return;
}
cmd = ng_l2cap_cmd_by_ident(con, ident);
if (cmd == NULL) {
NG_L2CAP_ALERT(
"%s: %s - could not find command, con_handle=%d, ident=%d\n",
__func__, NG_NODE_NAME(node), con_handle, ident);
return;
}
cmd->flags &= ~NG_L2CAP_CMD_PENDING;
ng_l2cap_unlink_cmd(cmd);
@ -340,7 +359,7 @@ ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
case NG_L2CAP_ECHO_REQ:
/* Echo request timed out. Let the upper layer know */
ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
NG_L2CAP_TIMEOUT, NULL);
break;
@ -353,10 +372,9 @@ ng_l2cap_process_command_timeout(node_p node, hook_p hook, void *arg1, int arg2)
/* XXX FIXME add other commands */
default:
KASSERT(0,
("%s: %s - unexpected command code=%d\n",
__func__, NG_NODE_NAME(cmd->con->l2cap->node),
cmd->code));
panic(
"%s: %s - unexpected command code=%d\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->code);
break;
}

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_l2cap_evnt.c,v 1.4 2003/04/01 18:15:26 max Exp $
* $Id: ng_l2cap_evnt.c,v 1.5 2003/09/08 19:11:45 max Exp $
* $FreeBSD$
*/
@ -285,14 +285,12 @@ ng_l2cap_process_cmd_rej(ng_l2cap_con_p con, u_int8_t ident)
/* Check if we have pending command descriptor */
cmd = ng_l2cap_cmd_by_ident(con, ident);
if (cmd != NULL) {
KASSERT((cmd->con == con),
("%s: %s - invalid connection pointer!\n",
__func__, NG_NODE_NAME(con->l2cap->node)));
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command state, flags=%#x\n",
__func__, NG_NODE_NAME(con->l2cap->node), cmd->flags));
/* If command timeout already happened then ignore reject */
if (ng_l2cap_command_untimeout(cmd) != 0) {
NG_FREE_M(con->rx_pkt);
return (ETIMEDOUT);
}
ng_l2cap_command_untimeout(cmd);
ng_l2cap_unlink_cmd(cmd);
switch (cmd->code) {
@ -432,10 +430,6 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident)
return (ENOENT);
}
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command state, flags=%#x\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->flags));
/* Verify channel state, if invalid - do nothing */
if (cmd->ch->state != NG_L2CAP_W4_L2CAP_CON_RSP) {
NG_L2CAP_ERR(
@ -458,10 +452,12 @@ ng_l2cap_process_con_rsp(ng_l2cap_con_p con, u_int8_t ident)
/*
* Looks good. We got confirmation from our peer. Now process
* it. First disable RTX timer. Then check the result and send
* notification to the upper layer.
* notification to the upper layer. If command timeout already
* happened then ignore response.
*/
ng_l2cap_command_untimeout(cmd);
if ((error = ng_l2cap_command_untimeout(cmd)) != 0)
return (error);
if (result == NG_L2CAP_PENDING) {
/*
@ -585,10 +581,7 @@ ng_l2cap_process_cfg_req(ng_l2cap_con_p con, u_int8_t ident)
bcopy(&val.flow, &ch->iflow, sizeof(ch->iflow));
break;
default:
KASSERT(0,
("%s: %s - unknown option: %d\n", __func__, NG_NODE_NAME(l2cap->node),
hdr.type));
default: /* Ignore unknown hint option */
break;
}
} else { /* Oops, something is wrong */
@ -692,10 +685,6 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident)
return (ENOENT);
}
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command state, flags=%#x\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->flags));
/* Verify CIDs and send reject if does not match */
if (cmd->ch->scid != scid) {
NG_L2CAP_ERR(
@ -721,10 +710,14 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident)
* then verify C flag. If it is set then we shall expect more
* configuration options from the peer and we will wait. Otherwise we
* have received all options and we will send L2CA_ConfigRsp event to
* the upper layer protocol.
* the upper layer protocol. If command timeout already happened then
* ignore response.
*/
ng_l2cap_command_untimeout(cmd);
if ((error = ng_l2cap_command_untimeout(cmd)) != 0) {
NG_FREE_M(m);
return (error);
}
for (off = 0; ; ) {
error = get_next_l2cap_opt(m, &off, &hdr, &val);
@ -745,19 +738,16 @@ ng_l2cap_process_cfg_rsp(ng_l2cap_con_p con, u_int8_t ident)
sizeof(cmd->ch->oflow));
break;
default:
KASSERT(0,
("%s: %s - unknown option: %d\n", __func__, NG_NODE_NAME(l2cap->node),
hdr.type));
default: /* Ignore unknown hint option */
break;
}
} else {
/*
* XXX FIXME What to do here?
*
* This is really BAD :( options packet was broken,
* so let upper layer know and do not wait for more
* options
* This is really BAD :( options packet was broken, or
* peer sent us option that we did not understand. Let
* upper layer know and do not wait for more options.
*/
NG_L2CAP_ALERT(
@ -934,10 +924,6 @@ ng_l2cap_process_discon_rsp(ng_l2cap_con_p con, u_int8_t ident)
goto out;
}
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command state, flags=%#x\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->flags));
/* Verify channel state, do nothing if invalid */
if (cmd->ch->state != NG_L2CAP_W4_L2CAP_DISCON_RSP) {
NG_L2CAP_ERR(
@ -959,11 +945,14 @@ ng_l2cap_process_discon_rsp(ng_l2cap_con_p con, u_int8_t ident)
}
/*
* Looks like we have successfuly disconnected channel,
* so notify upper layer.
* Looks like we have successfuly disconnected channel, so notify
* upper layer. If command timeout already happened then ignore
* response.
*/
ng_l2cap_command_untimeout(cmd);
if ((error = ng_l2cap_command_untimeout(cmd)) != 0)
goto out;
error = ng_l2cap_l2ca_discon_rsp(cmd->ch, cmd->token, NG_L2CAP_SUCCESS);
ng_l2cap_free_chan(cmd->ch); /* this will free commands too */
out:
@ -1025,14 +1014,12 @@ ng_l2cap_process_echo_rsp(ng_l2cap_con_p con, u_int8_t ident)
/* Check if we have this command */
cmd = ng_l2cap_cmd_by_ident(con, ident);
if (cmd != NULL) {
KASSERT((cmd->con == con),
("%s: %s - invalid connection pointer!\n",
__func__, NG_NODE_NAME(l2cap->node)));
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command state, flags=%#x\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->flags));
/* If command timeout already happened then ignore response */
if ((error = ng_l2cap_command_untimeout(cmd)) != 0) {
NG_FREE_M(con->rx_pkt);
return (error);
}
ng_l2cap_command_untimeout(cmd);
ng_l2cap_unlink_cmd(cmd);
error = ng_l2cap_l2ca_ping_rsp(cmd->con, cmd->token,
@ -1133,14 +1120,12 @@ ng_l2cap_process_info_rsp(ng_l2cap_con_p con, u_int8_t ident)
return (ENOENT);
}
KASSERT((cmd->con == con),
("%s: %s - invalid connection pointer!\n",
__func__, NG_NODE_NAME(l2cap->node)));
KASSERT((cmd->flags & NG_L2CAP_CMD_PENDING),
("%s: %s - invalid command state, flags=%#x\n",
__func__, NG_NODE_NAME(l2cap->node), cmd->flags));
/* If command timeout already happened then ignore response */
if ((error = ng_l2cap_command_untimeout(cmd)) != 0) {
NG_FREE_M(con->rx_pkt);
return (error);
}
ng_l2cap_command_untimeout(cmd);
ng_l2cap_unlink_cmd(cmd);
if (cp->result == NG_L2CAP_SUCCESS) {

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_l2cap_llpi.c,v 1.4 2003/04/28 21:44:59 max Exp $
* $Id: ng_l2cap_llpi.c,v 1.5 2003/09/08 19:11:45 max Exp $
* $FreeBSD$
*/
@ -114,7 +114,9 @@ ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr)
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, NULL);
if (error != 0) {
ng_l2cap_lp_untimeout(con);
if ((error = ng_l2cap_lp_untimeout(con)) != 0)
return (error);
ng_l2cap_free_con(con);
}
@ -168,10 +170,13 @@ ng_l2cap_lp_con_cfm(ng_l2cap_p l2cap, struct ng_mesg *msg)
/*
* Looks like it is our confirmation. It is safe now to cancel
* connection timer and notify upper layer.
* connection timer and notify upper layer. If timeout already
* happened then ignore connection confirmation and let timeout
* handle that.
*/
ng_l2cap_lp_untimeout(con);
if ((error = ng_l2cap_lp_untimeout(con)) != 0)
goto out;
if (ep->status == 0) {
con->state = NG_L2CAP_CON_OPEN;
@ -259,7 +264,9 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, struct ng_mesg *msg)
NG_SEND_MSG_HOOK(error, l2cap->node, rsp, l2cap->hci, NULL);
if (error != 0) {
ng_l2cap_lp_untimeout(con);
if ((error = ng_l2cap_lp_untimeout(con)) != 0)
goto out;
ng_l2cap_free_con(con);
}
out:
@ -311,9 +318,16 @@ ng_l2cap_lp_discon_ind(ng_l2cap_p l2cap, struct ng_mesg *msg)
goto out;
}
/* Notify upper layer and remove connection */
/*
* Notify upper layer and remove connection
* Note: The connection could have auto disconnect timeout set. Try
* to remove it. If auto disconnect timeout happened then ignore
* disconnect indication and let timeout handle that.
*/
if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
ng_l2cap_discon_untimeout(con);
if ((error = ng_l2cap_discon_untimeout(con)) != 0)
return (error);
ng_l2cap_con_fail(con, ep->reason);
out:
@ -791,13 +805,33 @@ ng_l2cap_lp_deliver(ng_l2cap_con_p con)
*/
void
ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2)
ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int con_handle)
{
ng_l2cap_con_p con = (ng_l2cap_con_p) arg1;
ng_l2cap_p l2cap = con->l2cap;
ng_l2cap_p l2cap = NULL;
ng_l2cap_con_p con = NULL;
NG_L2CAP_ERR(
"%s: %s - ACL connection timeout\n", __func__, NG_NODE_NAME(l2cap->node));
if (NG_NODE_NOT_VALID(node)) {
printf("%s: Netgraph node is not valid\n", __func__);
return;
}
l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node);
con = ng_l2cap_con_by_handle(l2cap, con_handle);
if (con == NULL) {
NG_L2CAP_ALERT(
"%s: %s - could not find connection, con_handle=%d\n",
__func__, NG_NODE_NAME(node), con_handle);
return;
}
if (!(con->flags & NG_L2CAP_CON_LP_TIMO)) {
NG_L2CAP_ALERT(
"%s: %s - no pending LP timeout, con_handle=%d, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(node), con_handle, con->state,
con->flags);
return;
}
/*
* Notify channels that connection has timed out. This will remove
@ -814,14 +848,37 @@ ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2)
*/
void
ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2)
ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int con_handle)
{
ng_l2cap_con_p con = (ng_l2cap_con_p) arg1;
ng_l2cap_p l2cap = con->l2cap;
ng_l2cap_p l2cap = NULL;
ng_l2cap_con_p con = NULL;
struct ng_mesg *msg = NULL;
ng_hci_lp_discon_req_ep *ep = NULL;
int error;
if (NG_NODE_NOT_VALID(node)) {
printf("%s: Netgraph node is not valid\n", __func__);
return;
}
l2cap = (ng_l2cap_p) NG_NODE_PRIVATE(node);
con = ng_l2cap_con_by_handle(l2cap, con_handle);
if (con == NULL) {
NG_L2CAP_ALERT(
"%s: %s - could not find connection, con_handle=%d\n",
__func__, NG_NODE_NAME(node), con_handle);
return;
}
if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)) {
NG_L2CAP_ALERT(
"%s: %s - no pending disconnect timeout, con_handle=%d, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(node), con_handle, con->state,
con->flags);
return;
}
con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
/* Check if lower layer protocol is still connected */
@ -829,7 +886,6 @@ ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2)
NG_L2CAP_ERR(
"%s: %s - hook \"%s\" is not connected or valid\n",
__func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI);
return;
}

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_l2cap_misc.c,v 1.4 2003/04/28 21:44:59 max Exp $
* $Id: ng_l2cap_misc.c,v 1.5 2003/09/08 19:11:45 max Exp $
* $FreeBSD$
*/
@ -47,10 +47,7 @@
#include "ng_l2cap_ulpi.h"
#include "ng_l2cap_misc.h"
static u_int16_t ng_l2cap_get_cid (ng_l2cap_p);
static void ng_l2cap_queue_discon_timeout (void *);
static void ng_l2cap_queue_lp_timeout (void *);
static void ng_l2cap_queue_command_timeout (void *);
static u_int16_t ng_l2cap_get_cid (ng_l2cap_p);
/******************************************************************************
******************************************************************************
@ -101,6 +98,7 @@ ng_l2cap_send_hook_info(node_p node, hook_p hook, void *arg1, int arg2)
ng_l2cap_con_p
ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr)
{
static int fake_con_handle = 0x0f00;
ng_l2cap_con_p con = NULL;
/* Create new connection descriptor */
@ -112,6 +110,24 @@ ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr)
con->l2cap = l2cap;
con->state = NG_L2CAP_CON_CLOSED;
/*
* XXX
*
* Assign fake connection handle to the connection descriptor.
* Bluetooth specification marks 0x0f00 - 0x0fff connection
* handles as reserved. We need this fake connection handles
* for timeouts. Connection handle will be passed as argument
* to timeout so when timeout happens we can find the right
* connection descriptor. We can not pass pointers, because
* timeouts are external (to Netgraph) events and there might
* be a race when node/hook goes down and timeout event already
* went into node's queue
*/
con->con_handle = fake_con_handle ++;
if (fake_con_handle > 0x0fff)
fake_con_handle = 0x0f00;
bcopy(bdaddr, &con->remote, sizeof(con->remote));
callout_handle_init(&con->con_timo);
@ -136,8 +152,10 @@ ng_l2cap_con_ref(ng_l2cap_con_p con)
if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) {
if ((con->state != NG_L2CAP_CON_OPEN) ||
(con->flags & NG_L2CAP_CON_OUTGOING) == 0)
panic("%s: %s - bad auto disconnect timeout\n",
__func__, NG_NODE_NAME(con->l2cap->node));
panic(
"%s: %s - bad auto disconnect timeout, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(con->l2cap->node),
con->state, con->flags);
ng_l2cap_discon_untimeout(con);
}
@ -153,8 +171,8 @@ ng_l2cap_con_unref(ng_l2cap_con_p con)
con->refcnt --;
if (con->refcnt < 0)
panic("%s: %s - con->refcnt < 0\n",
__func__, NG_NODE_NAME(con->l2cap->node));
panic(
"%s: %s - con->refcnt < 0\n", __func__, NG_NODE_NAME(con->l2cap->node));
/*
* Set auto disconnect timer only if the following conditions are met:
@ -167,61 +185,54 @@ ng_l2cap_con_unref(ng_l2cap_con_p con)
if ((con->refcnt == 0) &&
(con->state == NG_L2CAP_CON_OPEN) &&
(con->flags & NG_L2CAP_CON_OUTGOING) &&
(con->l2cap->discon_timo > 0)) {
if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
panic("%s: %s - duplicated auto disconnect timeout\n",
__func__, NG_NODE_NAME(con->l2cap->node));
(con->l2cap->discon_timo > 0))
ng_l2cap_discon_timeout(con);
}
} /* ng_l2cap_con_unref */
/*
* Set auto disconnect timeout
* XXX FIXME: check con->con_timo.callout != NULL
*/
void
int
ng_l2cap_discon_timeout(ng_l2cap_con_p con)
{
if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
panic("%s: %s - invalid timeout, state=%d, flags=%#x\n",
panic(
"%s: %s - invalid timeout, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(con->l2cap->node),
con->state, con->flags);
NG_NODE_REF(con->l2cap->node);
con->flags |= NG_L2CAP_CON_AUTO_DISCON_TIMO;
con->con_timo = timeout(ng_l2cap_queue_discon_timeout, con,
con->l2cap->discon_timo * hz);
con->con_timo = ng_timeout(con->l2cap->node, NULL,
con->l2cap->discon_timo * hz,
ng_l2cap_process_discon_timeout, NULL,
con->con_handle);
return (0);
} /* ng_l2cap_discon_timeout */
/*
* Unset auto disconnect timeout
*/
void
int
ng_l2cap_discon_untimeout(ng_l2cap_con_p con)
{
untimeout(ng_l2cap_queue_discon_timeout, con, con->con_timo);
if (!(con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO))
panic(
"%s: %s - no disconnect timeout, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(con->l2cap->node),
con->state, con->flags);
if (ng_untimeout(con->con_timo, con->l2cap->node) == 0)
return (ETIMEDOUT);
con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
NG_NODE_UNREF(con->l2cap->node);
return (0);
} /* ng_l2cap_discon_untimeout */
/*
* Queue auto disconnect timeout
*/
static void
ng_l2cap_queue_discon_timeout(void *context)
{
ng_l2cap_con_p con = (ng_l2cap_con_p) context;
node_p node = con->l2cap->node;
if (NG_NODE_IS_VALID(node))
ng_send_fn(node,NULL,&ng_l2cap_process_discon_timeout,con,0);
NG_NODE_UNREF(node);
} /* ng_l2cap_queue_discon_timeout */
/*
* Free connection descriptor. Will unlink connection and free everything.
*/
@ -231,20 +242,13 @@ ng_l2cap_free_con(ng_l2cap_con_p con)
{
ng_l2cap_chan_p f = NULL, n = NULL;
if (con->flags & NG_L2CAP_CON_LP_TIMO)
ng_l2cap_lp_untimeout(con);
else if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
ng_l2cap_discon_untimeout(con);
con->state = NG_L2CAP_CON_CLOSED;
if (con->tx_pkt != NULL) {
while (con->tx_pkt != NULL) {
struct mbuf *m = con->tx_pkt->m_nextpkt;
while (con->tx_pkt != NULL) {
struct mbuf *m = con->tx_pkt->m_nextpkt;
m_freem(con->tx_pkt);
con->tx_pkt = m;
}
m_freem(con->tx_pkt);
con->tx_pkt = m;
}
NG_FREE_M(con->rx_pkt);
@ -262,6 +266,8 @@ ng_l2cap_free_con(ng_l2cap_con_p con)
ng_l2cap_cmd_p cmd = TAILQ_FIRST(&con->cmd_list);
ng_l2cap_unlink_cmd(cmd);
if (cmd->flags & NG_L2CAP_CMD_PENDING)
ng_l2cap_command_untimeout(cmd);
ng_l2cap_free_cmd(cmd);
}
@ -378,6 +384,8 @@ ng_l2cap_free_chan(ng_l2cap_chan_p ch)
if (f->ch == ch) {
ng_l2cap_unlink_cmd(f);
if (f->flags & NG_L2CAP_CMD_PENDING)
ng_l2cap_command_untimeout(f);
ng_l2cap_free_cmd(f);
}
@ -422,7 +430,7 @@ ng_l2cap_new_cmd(ng_l2cap_con_p con, ng_l2cap_chan_p ch, u_int8_t ident,
} /* ng_l2cap_new_cmd */
/*
* Get L2CAP command descriptor by ident
* Get pending (i.e. initiated by local side) L2CAP command descriptor by ident
*/
ng_l2cap_cmd_p
@ -430,115 +438,108 @@ ng_l2cap_cmd_by_ident(ng_l2cap_con_p con, u_int8_t ident)
{
ng_l2cap_cmd_p cmd = NULL;
TAILQ_FOREACH(cmd, &con->cmd_list, next)
if (cmd->ident == ident)
TAILQ_FOREACH(cmd, &con->cmd_list, next) {
if ((cmd->flags & NG_L2CAP_CMD_PENDING) && cmd->ident == ident) {
KASSERT((cmd->con == con),
("%s: %s - invalid connection pointer!\n",
__func__, NG_NODE_NAME(con->l2cap->node)));
break;
}
}
return (cmd);
} /* ng_l2cap_cmd_by_ident */
/*
* Set LP timeout
* XXX FIXME: check con->con_timo.callout != NULL
*/
void
int
ng_l2cap_lp_timeout(ng_l2cap_con_p con)
{
if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
panic("%s: %s - invalid timeout, state=%d, flags=%#x\n",
panic(
"%s: %s - invalid timeout, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(con->l2cap->node),
con->state, con->flags);
NG_NODE_REF(con->l2cap->node);
con->flags |= NG_L2CAP_CON_LP_TIMO;
con->con_timo = timeout(ng_l2cap_queue_lp_timeout, con,
bluetooth_hci_connect_timeout());
con->con_timo = ng_timeout(con->l2cap->node, NULL,
bluetooth_hci_connect_timeout(),
ng_l2cap_process_lp_timeout, NULL,
con->con_handle);
return (0);
} /* ng_l2cap_lp_timeout */
/*
* Unset LP timeout
*/
void
int
ng_l2cap_lp_untimeout(ng_l2cap_con_p con)
{
untimeout(ng_l2cap_queue_lp_timeout, con, con->con_timo);
if (!(con->flags & NG_L2CAP_CON_LP_TIMO))
panic(
"%s: %s - no LP connection timeout, state=%d, flags=%#x\n",
__func__, NG_NODE_NAME(con->l2cap->node),
con->state, con->flags);
if (ng_untimeout(con->con_timo, con->l2cap->node) == 0)
return (ETIMEDOUT);
con->flags &= ~NG_L2CAP_CON_LP_TIMO;
NG_NODE_UNREF(con->l2cap->node);
return (0);
} /* ng_l2cap_lp_untimeout */
/*
* OK, timeout has happend so queue LP timeout processing function
*/
static void
ng_l2cap_queue_lp_timeout(void *context)
{
ng_l2cap_con_p con = (ng_l2cap_con_p) context;
node_p node = con->l2cap->node;
/*
* We need to save node pointer here, because ng_send_fn()
* can execute ng_l2cap_process_lp_timeout() without putting
* item into node's queue (if node can be locked). Once
* ng_l2cap_process_lp_timeout() executed the con pointer
* is no longer valid.
*/
if (NG_NODE_IS_VALID(node))
ng_send_fn(node, NULL, &ng_l2cap_process_lp_timeout, con, 0);
NG_NODE_UNREF(node);
} /* ng_l2cap_queue_lp_timeout */
/*
* Set L2CAP command timeout
* XXX FIXME: check cmd->timo.callout != NULL
*/
void
int
ng_l2cap_command_timeout(ng_l2cap_cmd_p cmd, int timo)
{
NG_NODE_REF(cmd->con->l2cap->node);
int arg;
if (cmd->flags & NG_L2CAP_CMD_PENDING)
panic(
"%s: %s - duplicated command timeout, code=%#x, flags=%#x\n",
__func__, NG_NODE_NAME(cmd->con->l2cap->node),
cmd->code, cmd->flags);
arg = ((cmd->ident << 16) | cmd->con->con_handle);
cmd->flags |= NG_L2CAP_CMD_PENDING;
cmd->timo = timeout(ng_l2cap_queue_command_timeout, cmd, timo);
cmd->timo = ng_timeout(cmd->con->l2cap->node, NULL, timo,
ng_l2cap_process_command_timeout, NULL, arg);
return (0);
} /* ng_l2cap_command_timeout */
/*
* Unset L2CAP command timeout
*/
void
int
ng_l2cap_command_untimeout(ng_l2cap_cmd_p cmd)
{
if (!(cmd->flags & NG_L2CAP_CMD_PENDING))
panic(
"%s: %s - no command timeout, code=%#x, flags=%#x\n",
__func__, NG_NODE_NAME(cmd->con->l2cap->node),
cmd->code, cmd->flags);
if (ng_untimeout(cmd->timo, cmd->con->l2cap->node) == 0)
return (ETIMEDOUT);
cmd->flags &= ~NG_L2CAP_CMD_PENDING;
untimeout(ng_l2cap_queue_command_timeout, cmd, cmd->timo);
NG_NODE_UNREF(cmd->con->l2cap->node);
return (0);
} /* ng_l2cap_command_untimeout */
/*
* OK, timeout has happend so queue L2CAP command timeout processing function
*/
static void
ng_l2cap_queue_command_timeout(void *context)
{
ng_l2cap_cmd_p cmd = (ng_l2cap_cmd_p) context;
node_p node = cmd->con->l2cap->node;
/*
* We need to save node pointer here, because ng_send_fn()
* can execute ng_l2cap_process_command_timeout() without
* putting item into node's queue (if node can be locked).
* Once ng_l2cap_process_command_timeout() executed the
* cmd pointer is no longer valid.
*/
if (NG_NODE_IS_VALID(node))
ng_send_fn(node,NULL,&ng_l2cap_process_command_timeout,cmd,0);
NG_NODE_UNREF(node);
} /* ng_l2cap_queue_command_timeout */
/*
* Prepend "m"buf with "size" bytes
*/

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_l2cap_misc.h,v 1.2 2003/04/28 21:44:59 max Exp $
* $Id: ng_l2cap_misc.h,v 1.3 2003/09/08 19:11:45 max Exp $
* $FreeBSD$
*/
@ -71,9 +71,6 @@ do { \
#define ng_l2cap_free_cmd(cmd) \
do { \
if ((cmd)->flags & NG_L2CAP_CMD_PENDING) \
ng_l2cap_command_untimeout((cmd)); \
\
NG_FREE_M((cmd)->aux); \
bzero((cmd), sizeof(*(cmd))); \
FREE((cmd), M_NETGRAPH_L2CAP); \
@ -88,12 +85,12 @@ u_int8_t ng_l2cap_get_ident (ng_l2cap_con_p);
* Timeout
*/
void ng_l2cap_discon_timeout (ng_l2cap_con_p);
void ng_l2cap_discon_untimeout (ng_l2cap_con_p);
void ng_l2cap_lp_timeout (ng_l2cap_con_p);
void ng_l2cap_lp_untimeout (ng_l2cap_con_p);
void ng_l2cap_command_timeout (ng_l2cap_cmd_p, int);
void ng_l2cap_command_untimeout (ng_l2cap_cmd_p);
int ng_l2cap_discon_timeout (ng_l2cap_con_p);
int ng_l2cap_discon_untimeout (ng_l2cap_con_p);
int ng_l2cap_lp_timeout (ng_l2cap_con_p);
int ng_l2cap_lp_untimeout (ng_l2cap_con_p);
int ng_l2cap_command_timeout (ng_l2cap_cmd_p, int);
int ng_l2cap_command_untimeout (ng_l2cap_cmd_p);
/*
* Other stuff

View file

@ -25,12 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_btsocket.c,v 1.3 2003/01/19 00:19:04 max Exp $
* $Id: ng_btsocket.c,v 1.4 2003/09/14 23:29:06 max Exp $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitstring.h>
#include <sys/errno.h>
#include <sys/domain.h>
#include <sys/kernel.h>
@ -41,7 +42,6 @@
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
#include <sys/bitstring.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include "ng_bluetooth.h"

View file

@ -25,12 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_btsocket_hci_raw.c,v 1.13 2003/04/01 18:15:27 max Exp $
* $Id: ng_btsocket_hci_raw.c,v 1.14 2003/09/14 23:29:06 max Exp $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitstring.h>
#include <sys/domain.h>
#include <sys/endian.h>
#include <sys/errno.h>
@ -49,7 +50,6 @@
#include <sys/taskqueue.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <sys/bitstring.h>
#include "ng_bluetooth.h"
#include "ng_hci.h"
#include "ng_l2cap.h"

View file

@ -25,12 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_btsocket_l2cap.c,v 1.14 2003/04/06 22:53:18 max Exp $
* $Id: ng_btsocket_l2cap.c,v 1.16 2003/09/14 23:29:06 max Exp $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitstring.h>
#include <sys/domain.h>
#include <sys/endian.h>
#include <sys/errno.h>
@ -49,7 +50,6 @@
#include <sys/taskqueue.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <sys/bitstring.h>
#include "ng_bluetooth.h"
#include "ng_hci.h"
#include "ng_l2cap.h"
@ -1411,7 +1411,7 @@ ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
rt->src.b[2], rt->src.b[1], rt->src.b[0],
hdr->dcid, hdr->length);
if (NG_L2CAP_FIRST_CID <= hdr->dcid && hdr->dcid <= NG_L2CAP_LAST_CID) {
if (hdr->dcid >= NG_L2CAP_FIRST_CID) {
mtx_lock(&ng_btsocket_l2cap_sockets_mtx);

View file

@ -25,12 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_btsocket_l2cap_raw.c,v 1.11 2003/04/27 19:52:14 max Exp $
* $Id: ng_btsocket_l2cap_raw.c,v 1.12 2003/09/14 23:29:06 max Exp $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitstring.h>
#include <sys/domain.h>
#include <sys/errno.h>
#include <sys/filedesc.h>
@ -48,7 +49,6 @@
#include <sys/taskqueue.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <sys/bitstring.h>
#include "ng_bluetooth.h"
#include "ng_hci.h"
#include "ng_l2cap.h"

View file

@ -25,12 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ng_btsocket_rfcomm.c,v 1.24 2003/04/07 01:37:05 max Exp $
* $Id: ng_btsocket_rfcomm.c,v 1.28 2003/09/14 23:29:06 max Exp $
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bitstring.h>
#include <sys/domain.h>
#include <sys/endian.h>
#include <sys/errno.h>
@ -51,7 +52,6 @@
#include <sys/uio.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <sys/bitstring.h>
#include "ng_bluetooth.h"
#include "ng_hci.h"
#include "ng_l2cap.h"
@ -2025,6 +2025,9 @@ ng_btsocket_rfcomm_receive_sabm(ng_btsocket_rfcomm_session_p s, int dlci)
pcb->dlci = dlci;
error = ng_btsocket_rfcomm_send_command(s,RFCOMM_FRAME_UA,dlci);
if (error == 0)
error = ng_btsocket_rfcomm_send_msc(pcb);
if (error == 0) {
pcb->state = NG_BTSOCKET_RFCOMM_DLC_CONNECTED;
soisconnected(pcb->so);
@ -3139,7 +3142,13 @@ ng_btsocket_rfcomm_send_pn(ng_btsocket_rfcomm_pcb_p pcb)
hdr->length = RFCOMM_MKLEN8(sizeof(*pn));
pn->dlci = pcb->dlci;
pn->priority = 0;
/*
* Set default DLCI priority as described in GSM 07.10
* (ETSI TS 101 369) clause 5.6 page 42
*/
pn->priority = (pcb->dlci < 56)? (((pcb->dlci >> 3) << 3) + 7) : 61;
pn->ack_timer = 0;
pn->mtu = htole16(pcb->mtu);
pn->max_retrans = 0;

View file

@ -244,7 +244,8 @@ SUBDIR+=usbhidaction \
.if ${MACHINE_ARCH} == "i386"
# Things that don't compile on alpha or are aout specific:
SUBDIR+=doscmd \
SUBDIR+=bluetooth \
doscmd \
ncplist \
ncplogin \
sasc \

View file

@ -1,7 +1,9 @@
# $Id $
# $FreeBSD$
SUBDIR= btsockstat \
SUBDIR= \
bthost \
btsockstat \
rfcomm_sppd
.include <bsd.subdir.mk>

View file

@ -0,0 +1,4 @@
# $FreeBSD$
.include "${.CURDIR}/../../Makefile.inc"

View file

@ -0,0 +1,12 @@
# $Id: Makefile,v 1.4 2003/08/14 20:07:13 max Exp $
# $FreeBSD$
PROG= bthost
MAN= bthost.1
SRCS= bthost.c
WARNS?= 2
DPADD= ${LIBBLUETOOTH}
LDADD= -lbluetooth
.include <bsd.prog.mk>

View file

@ -0,0 +1,111 @@
.\" 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: bthost.1,v 1.7 2003/05/21 22:19:00 max Exp $
.\" $FreeBSD$
.\"
.Dd May 8, 2003
.Dt BTHOST 1
.Os
.Sh NAME
.Nm bthost
.Nd look up Bluetooth host names and Protocol Service Multiplexor values
.Sh SYNOPSIS
.Nm bthost
.Op Fl bhp
.Ar host_or_protocol
.Sh DESCRIPTION
The
.Nm
utility looks for information about Bluetooth hosts and
Protocol Service Multiplexor (PSM) values.
It gets this information from the
.Pa /etc/bluetooth/hosts
and
.Pa /etc/bluetooth/protocols
files.
.Pp
In host mode it simply converts between host names and Bluetooth addresses.
The argument can be either host name or Bluetooth address.
The program first attempts to interpret it as Bluetooth address.
If this fails, it will treat it as host name.
A Bluetooth address consists of six hex bytes sparated by column,
e.g. 01:02:03:04:05:06.
A host name consists of names separated by dots, e.g. my.cell.phone.
.Pp
In protocol mode it simply converts between Protocol Service Multiplexor names
and assigned numbers.
The argument can be either Protocol Service Multiplexor name or assigned number.
The program first attempts to interpret it as assigned number.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl b
Produce brief output.
.It Fl h
Display usage message and exit.
.It Fl p
Activate protocol mode.
.El
.Pp
The
.Nm
utility will print results to the standard output and error messages to the
standard error.
You may see output of different kinds.
Here is an example that shows all of them:
.Pp
.D1 Ic % bthost localhost
.Dl Host localhost has address FF:FF:FF:00:00:00
.D1 Ic % bthost ff:ff:ff:00:00:00
.Dl Host FF:FF:FF:00:00:00 has name localhost
.D1 Ic % bthost -b localhost
.Dl FF:FF:FF:00:00:00
.D1 Ic % bthost -b ff:ff:ff:00:00:00
.Dl localhost
.D1 Ic % bthost do.not.exists
.Dl do.not.exists: Unknown host
.D1 Ic % bthost 0:0:0:0:0:0
.Dl 00:00:00:00:00:00: Unknown host
.D1 Ic % bthost -p sdp
.Dl Protocol/Service Multiplexor sdp has number 1
.D1 Ic % bthost -p 3
.Dl Protocol/Service Multiplexor rfcomm has number 3
.D1 Ic % bthost -bp HID-Control
.Dl 17
.D1 Ic % bthost -p foo
.Dl foo: Unknown Protocol/Service Multiplexor
.Sh FILES
.Bl -tag -width "/etc/bluetooth/hosts" -compact
.It Pa /etc/bluetooth/hosts
.It Pa /etc/bluetooth/protocols
.El
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO
.Xr bluetooth 3 ,
.Xr bluetooth.hosts 5 ,
.Xr bluetooth.protocols 5
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View file

@ -0,0 +1,142 @@
/*
* bthost.c
*
* 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: bthost.c,v 1.5 2003/05/21 20:30:01 max Exp $
* $FreeBSD$
*/
#include <bluetooth.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int hostmode (char const *arg, int brief);
static int protomode (char const *arg, int brief);
static void usage (void);
int
main(int argc, char **argv)
{
int opt, brief = 0, proto = 0;
while ((opt = getopt(argc, argv, "bhp")) != -1) {
switch (opt) {
case 'b':
brief = 1;
break;
case 'p':
proto = 1;
break;
case 'h':
default:
usage();
/* NOT REACHED */
}
}
argc -= optind;
argv += optind;
if (argc < 1)
usage();
exit(proto? protomode(*argv, brief) : hostmode(*argv, brief));
}
static int
hostmode(char const *arg, int brief)
{
struct hostent *he = NULL;
bdaddr_t ba;
char bastr[32];
int reverse;
if (bt_aton(arg, &ba) == 1) {
reverse = 1;
he = bt_gethostbyaddr((char const *) &ba, sizeof(ba),
AF_BLUETOOTH);
} else {
reverse = 0;
he = bt_gethostbyname(arg);
}
if (he == NULL) {
herror(reverse? bt_ntoa(&ba, bastr) : arg);
return (1);
}
if (brief)
printf("%s", reverse? he->h_name :
bt_ntoa((bdaddr_t *)(he->h_addr), bastr));
else
printf("Host %s has %s %s\n",
reverse? bt_ntoa(&ba, bastr) : arg,
reverse? "name" : "address",
reverse? he->h_name :
bt_ntoa((bdaddr_t *)(he->h_addr), bastr));
return (0);
}
static int
protomode(char const *arg, int brief)
{
struct protoent *pe = NULL;
int proto;
if ((proto = atoi(arg)) != 0)
pe = bt_getprotobynumber(proto);
else
pe = bt_getprotobyname(arg);
if (pe == NULL) {
fprintf(stderr, "%s: Unknown Protocol/Service Multiplexor\n", arg);
return (1);
}
if (brief) {
if (proto)
printf("%s", pe->p_name);
else
printf("%d", pe->p_proto);
} else {
printf("Protocol/Service Multiplexor %s has number %d\n",
pe->p_name, pe->p_proto);
}
return (0);
}
static void
usage(void)
{
fprintf(stdout, "Usage: bthost [-b -h -p] host_or_protocol\n");
exit(255);
}

View file

@ -1,19 +1,14 @@
# $Id: Makefile,v 1.3 2003/03/24 23:59:49 max Exp $
# $Id: Makefile,v 1.7 2003/08/14 20:07:14 max Exp $
# $FreeBSD$
PROG= btsockstat
MAN= btsockstat.1
SRCS= btsockstat.c
WARNS?= 2
BINGRP= kmem
BINMODE= 2555
MAN1= btsockstat.1
DESTDIR= /usr/bin/
MANDIR= ../share/man/man
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include/
SRCS= btsockstat.c
DPADD= ${LIBKVM}
LDADD= -lkvm
DPADD= ${LIBBLUETOOTH} ${LIBKVM}
LDADD= -lbluetooth -lkvm
.include <bsd.prog.mk>

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: btsockstat.1,v 1.4 2003/04/27 19:25:15 max Exp $
.\" $Id: btsockstat.1,v 1.6 2003/05/21 00:09:45 max Exp $
.\" $FreeBSD$
.\"
.Dd August 31, 2002
@ -33,7 +33,7 @@
.Nd show Bluetooth sockets information
.Sh SYNOPSIS
.Nm
.Op Fl rh
.Op Fl nrh
.Op Fl M Ar core
.Op Fl p Ar protocol
.Sh DESCRIPTION
@ -57,6 +57,10 @@ Display usage message and exit.
Extract values associated with the name list from the specified core
instead of the default
.Pa /dev/kmem .
.It Fl n
Show Bluetooth addresses as numbers. Normally
.Nm
attempts to resolve Bluetooth addresses, and display them symbolically.
.It Fl p Ar protocol
Display a list of active sockets (protocol control blocks) for each
specified protocol.

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: btsockstat.c,v 1.4 2003/03/29 22:28:18 max Exp $
* $Id: btsockstat.c,v 1.8 2003/05/21 22:40:25 max Exp $
* $FreeBSD$
*/
@ -39,19 +39,16 @@
#include <net/if.h>
#include <net/if_var.h>
#include <bitstring.h>
#include <bluetooth.h>
#include <err.h>
#include <fcntl.h>
#include <kvm.h>
#include <limits.h>
#include <ng_bluetooth.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <ng_btsocket_hci_raw.h>
#include <ng_btsocket_l2cap.h>
#include <ng_btsocket_rfcomm.h>
#include <netgraph/bluetooth/include/ng_bluetooth.h>
#include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h>
#include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
#include <netgraph/bluetooth/include/ng_btsocket_rfcomm.h>
#include <stdio.h>
#include <stdlib.h>
@ -65,6 +62,8 @@ static void l2caprtpr (kvm_t *kvmd, u_long addr);
static void rfcommpr (kvm_t *kvmd, u_long addr);
static void rfcommpr_s (kvm_t *kvmd, u_long addr);
static char * bdaddrpr (bdaddr_p const ba, char *str, int len);
static kvm_t * kopen (char const *memf);
static int kread (kvm_t *kvmd, u_long addr, char *buffer, int size);
@ -99,6 +98,8 @@ static struct nlist nl[] = {
* Main
*/
static int numeric_bdaddr = 0;
int
main(int argc, char *argv[])
{
@ -106,8 +107,12 @@ main(int argc, char *argv[])
kvm_t *kvmd = NULL;
char *memf = NULL;
while ((opt = getopt(argc, argv, "hM:p:r")) != -1) {
while ((opt = getopt(argc, argv, "hnM:p:r")) != -1) {
switch (opt) {
case 'n':
numeric_bdaddr = 1;
break;
case 'M':
memf = optarg;
break;
@ -265,7 +270,6 @@ l2caprawpr(kvm_t *kvmd, u_long addr)
ng_btsocket_l2cap_raw_pcb_t pcb;
struct socket so;
int first = 1;
char bdaddr[32];
if (addr == 0)
return;
@ -293,22 +297,13 @@ l2caprawpr(kvm_t *kvmd, u_long addr)
"Local address");
}
if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) {
bdaddr[0] = '*';
bdaddr[1] = 0;
} else
snprintf(bdaddr, sizeof(bdaddr),
"%02x:%02x:%02x:%02x:%02x:%02x",
pcb.src.b[5], pcb.src.b[4], pcb.src.b[3],
pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]);
fprintf(stdout,
"%-8.8x %-8.8x %6d %6d %-17.17s\n",
(int) pcb.so,
(int) this,
so.so_rcv.sb_cc,
so.so_snd.sb_cc,
bdaddr);
bdaddrpr(&pcb.src, NULL, 0));
}
} /* l2caprawpr */
@ -331,7 +326,7 @@ l2cappr(kvm_t *kvmd, u_long addr)
ng_btsocket_l2cap_pcb_t pcb;
struct socket so;
int first = 1;
char local[32], remote[32];
char local[24], remote[24];
if (addr == 0)
return;
@ -361,31 +356,14 @@ l2cappr(kvm_t *kvmd, u_long addr)
"State");
}
if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0)
snprintf(local, sizeof(local), "*/%d", pcb.psm);
else
snprintf(local, sizeof(local),
"%02x:%02x:%02x:%02x:%02x:%02x/%d",
pcb.src.b[5], pcb.src.b[4], pcb.src.b[3],
pcb.src.b[2], pcb.src.b[1], pcb.src.b[0],
pcb.psm);
if (memcmp(&pcb.dst, NG_HCI_BDADDR_ANY, sizeof(pcb.dst)) == 0) {
remote[0] = '*';
remote[1] = 0;
} else
snprintf(remote, sizeof(remote),
"%02x:%02x:%02x:%02x:%02x:%02x",
pcb.dst.b[5], pcb.dst.b[4], pcb.dst.b[3],
pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]);
fprintf(stdout,
"%-8.8x %6d %6d %-23.23s %-17.17s %-5d %s\n",
"%-8.8x %6d %6d %-17.17s/%-5d %-17.17s %-5d %s\n",
(int) this,
so.so_rcv.sb_cc,
so.so_snd.sb_cc,
local,
remote,
bdaddrpr(&pcb.src, local, sizeof(local)),
pcb.psm,
bdaddrpr(&pcb.dst, remote, sizeof(remote)),
pcb.cid,
(so.so_options & SO_ACCEPTCONN)?
"LISTEN" : state2str(pcb.state));
@ -402,7 +380,6 @@ l2caprtpr(kvm_t *kvmd, u_long addr)
ng_btsocket_l2cap_rtentry_p this = NULL, next = NULL;
ng_btsocket_l2cap_rtentry_t rt;
int first = 1;
char bdaddr[32];
if (addr == 0)
return;
@ -426,19 +403,11 @@ l2caprtpr(kvm_t *kvmd, u_long addr)
"BD_ADDR");
}
if (memcmp(&rt.src, NG_HCI_BDADDR_ANY, sizeof(rt.src)) == 0) {
bdaddr[0] = '-';
bdaddr[1] = 0;
} else
snprintf(bdaddr, sizeof(bdaddr),
"%02x:%02x:%02x:%02x:%02x:%02x", rt.src.b[5], rt.src.b[4], rt.src.b[3],
rt.src.b[2], rt.src.b[1], rt.src.b[0]);
fprintf(stdout,
"%-8.8x %-8.8x %-17.17s\n",
(int) this,
(int) rt.hook,
bdaddr);
bdaddrpr(&rt.src, NULL, 0));
}
} /* l2caprtpr */
@ -462,7 +431,7 @@ rfcommpr(kvm_t *kvmd, u_long addr)
ng_btsocket_rfcomm_pcb_t pcb;
struct socket so;
int first = 1;
char local[32], remote[32];
char local[24], remote[24];
if (addr == 0)
return;
@ -493,31 +462,13 @@ rfcommpr(kvm_t *kvmd, u_long addr)
"State");
}
if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) {
local[0] = '*';
local[1] = 0;
} else
snprintf(local, sizeof(local),
"%02x:%02x:%02x:%02x:%02x:%02x",
pcb.src.b[5], pcb.src.b[4], pcb.src.b[3],
pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]);
if (memcmp(&pcb.dst, NG_HCI_BDADDR_ANY, sizeof(pcb.dst)) == 0) {
remote[0] = '*';
remote[1] = 0;
} else
snprintf(remote, sizeof(remote),
"%02x:%02x:%02x:%02x:%02x:%02x",
pcb.dst.b[5], pcb.dst.b[4], pcb.dst.b[3],
pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]);
fprintf(stdout,
"%-8.8x %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n",
(int) this,
so.so_rcv.sb_cc,
so.so_snd.sb_cc,
local,
remote,
bdaddrpr(&pcb.src, local, sizeof(local)),
bdaddrpr(&pcb.dst, remote, sizeof(remote)),
pcb.channel,
pcb.dlci,
(so.so_options & SO_ACCEPTCONN)?
@ -586,6 +537,40 @@ rfcommpr_s(kvm_t *kvmd, u_long addr)
}
} /* rfcommpr_s */
/*
* Return BD_ADDR as string
*/
static char *
bdaddrpr(bdaddr_p const ba, char *str, int len)
{
static char buffer[MAXHOSTNAMELEN];
struct hostent *he = NULL;
if (str == NULL) {
str = buffer;
len = sizeof(buffer);
}
if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {
str[0] = '*';
str[1] = 0;
return (str);
}
if (!numeric_bdaddr &&
(he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {
strlcpy(str, he->h_name, len);
return (str);
}
bt_ntoa(ba, str);
return (str);
} /* bdaddrpr */
/*
* Open kvm
*/
@ -652,7 +637,7 @@ kread(kvm_t *kvmd, u_long addr, char *buffer, int size)
static void
usage(void)
{
fprintf(stdout, "Usage: btsockstat [-M core ] [-p proto] [-r]\n");
fprintf(stdout, "Usage: btsockstat [-M core ] [-n] [-p proto] [-r]\n");
exit(255);
} /* usage */

View file

@ -1,15 +1,12 @@
# $Id: Makefile,v 1.2 2003/04/26 23:55:34 max Exp $
# $Id: Makefile,v 1.7 2003/09/07 18:15:55 max Exp $
# $FreeBSD$
PROG= rfcomm_sppd
MAN1= rfcomm_sppd.1
DESTDIR= /usr/bin/
MANDIR= ../share/man/man
MAN= rfcomm_sppd.1
SRCS= rfcomm_sppd.c rfcomm_sdp.c
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include/
SRCS= rfcomm_sppd.c
DPADD= ${LIBBLUETOOTH} ${LIBSDP}
LDADD= -lbluetooth -lsdp
.include <bsd.prog.mk>

View file

@ -0,0 +1,266 @@
/*
* rfcomm_sdp.c
*
* 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: rfcomm_sdp.c,v 1.1 2003/09/07 18:15:55 max Exp $
* $FreeBSD$
*/
#include <bluetooth.h>
#include <errno.h>
#include <sdp.h>
#include <stdio.h>
#undef PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE
#define PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE 256
#undef PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE
#define PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE 12
static int rfcomm_proto_list_parse (u_int8_t const *start, u_int8_t const *end,
int *channel, int *error);
/*
* Lookup RFCOMM channel number in the Protocol Descriptor List
*/
#undef rfcomm_channel_lookup_exit
#define rfcomm_channel_lookup_exit(e) { \
if (error != NULL) \
*error = (e); \
if (ss != NULL) { \
sdp_close(ss); \
ss = NULL; \
} \
return (((e) == 0)? 0 : -1); \
}
int
rfcomm_channel_lookup(bdaddr_t const *local, bdaddr_t const *remote,
int service, int *channel, int *error)
{
u_int8_t buffer[PROTOCOL_DESCRIPTOR_LIST_BUFFER_SIZE];
void *ss = NULL;
u_int16_t serv = (u_int16_t) service;
u_int32_t attr = SDP_ATTR_RANGE(
SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer };
u_int32_t type, len;
if (local == NULL)
local = NG_HCI_BDADDR_ANY;
if (remote == NULL || channel == NULL)
rfcomm_channel_lookup_exit(EINVAL);
if ((ss = sdp_open(local, remote)) == NULL)
rfcomm_channel_lookup_exit(ENOMEM);
if (sdp_error(ss) != 0)
rfcomm_channel_lookup_exit(sdp_error(ss));
if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0)
rfcomm_channel_lookup_exit(sdp_error(ss));
if (proto.flags != SDP_ATTR_OK)
rfcomm_channel_lookup_exit(ENOATTR);
sdp_close(ss);
ss = NULL;
/*
* If it is possible for more than one kind of protocol stack to be
* used to gain access to the service, the ProtocolDescriptorList
* takes the form of a data element alternative. We always use the
* first protocol stack.
*
* A minimal Protocol Descriptor List for RFCOMM based service would
* look like
*
* seq8 len8 - 2 bytes
* seq8 len8 - 2 bytes
* uuid16 value16 - 3 bytes L2CAP
* seq8 len8 - 2 bytes
* uuid16 value16 - 3 bytes RFCOMM
* uint8 value8 - 2 bytes RFCOMM param #1
* =========
* 14 bytes
*
* Lets not count first [seq8 len8] wrapper, so the minimal size of
* the Protocol Descriptor List (the data we are actually interested
* in) for RFCOMM based service would be 12 bytes.
*/
if (proto.vlen < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE)
rfcomm_channel_lookup_exit(EINVAL);
SDP_GET8(type, proto.value);
if (type == SDP_DATA_ALT8) {
SDP_GET8(len, proto.value);
} else if (type == SDP_DATA_ALT16) {
SDP_GET16(len, proto.value);
} else if (type == SDP_DATA_ALT32) {
SDP_GET32(len, proto.value);
} else
len = 0;
if (len > 0)
SDP_GET8(type, proto.value);
switch (type) {
case SDP_DATA_SEQ8:
SDP_GET8(len, proto.value);
break;
case SDP_DATA_SEQ16:
SDP_GET16(len, proto.value);
break;
case SDP_DATA_SEQ32:
SDP_GET32(len, proto.value);
break;
default:
rfcomm_channel_lookup_exit(ENOATTR);
/* NOT REACHED */
}
if (len < PROTOCOL_DESCRIPTOR_LIST_MINIMAL_SIZE)
rfcomm_channel_lookup_exit(EINVAL);
return (rfcomm_proto_list_parse(proto.value,
buffer + proto.vlen, channel, error));
}
/*
* Parse protocol descriptor list
*
* The ProtocolDescriptorList attribute describes one or more protocol
* stacks that may be used to gain access to the service described by
* the service record. If the ProtocolDescriptorList describes a single
* stack, it takes the form of a data element sequence in which each
* element of the sequence is a protocol descriptor.
*/
#undef rfcomm_proto_list_parse_exit
#define rfcomm_proto_list_parse_exit(e) { \
if (error != NULL) \
*error = (e); \
return (((e) == 0)? 0 : -1); \
}
static int
rfcomm_proto_list_parse(u_int8_t const *start, u_int8_t const *end,
int *channel, int *error)
{
int type, len, value;
while (start < end) {
/*
* Parse protocol descriptor
*
* A protocol descriptor identifies a communications protocol
* and provides protocol specific parameters. A protocol
* descriptor is represented as a data element sequence. The
* first data element in the sequence must be the UUID that
* identifies the protocol. Additional data elements optionally
* provide protocol specific information, such as the L2CAP
* protocol/service multiplexer (PSM) and the RFCOMM server
* channel number (CN).
*/
/* We must have at least one byte (type) */
if (end - start < 1)
rfcomm_proto_list_parse_exit(EINVAL)
SDP_GET8(type, start);
switch (type) {
case SDP_DATA_SEQ8:
SDP_GET8(len, start);
break;
case SDP_DATA_SEQ16:
SDP_GET16(len, start);
break;
case SDP_DATA_SEQ32:
SDP_GET32(len, start);
break;
default:
rfcomm_proto_list_parse_exit(ENOATTR)
/* NOT REACHED */
}
/* We must have at least 3 bytes (type + UUID16) */
if (end - start < 3)
rfcomm_proto_list_parse_exit(EINVAL);
/* Get protocol UUID */
SDP_GET8(type, start); len -= sizeof(u_int8_t);
switch (type) {
case SDP_DATA_UUID16:
SDP_GET16(value, start); len -= sizeof(u_int16_t);
if (value != SDP_UUID_PROTOCOL_RFCOMM)
goto next_protocol;
break;
case SDP_DATA_UUID32: /* XXX FIXME can we have 32-bit UUID */
case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */
default:
rfcomm_proto_list_parse_exit(ENOATTR);
/* NOT REACHED */
}
/*
* First protocol specific parameter for RFCOMM procotol must
* be uint8 that represents RFCOMM channel number. So we must
* have at least two bytes.
*/
if (end - start < 2)
rfcomm_proto_list_parse_exit(EINVAL);
SDP_GET8(type, start);
if (type != SDP_DATA_UINT8)
rfcomm_proto_list_parse_exit(ENOATTR);
SDP_GET8(*channel, start);
rfcomm_proto_list_parse_exit(0);
/* NOT REACHED */
next_protocol:
start += len;
}
/*
* If we got here then it means we could not find RFCOMM protocol
* descriptor, but the reply format was actually valid.
*/
rfcomm_proto_list_parse_exit(ENOATTR);
}

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: rfcomm_sppd.1,v 1.1 2003/04/26 23:55:34 max Exp $
.\" $Id: rfcomm_sppd.1,v 1.3 2003/09/07 18:15:55 max Exp $
.\" $FreeBSD$
.\"
.Dd April 26, 2003
@ -72,8 +72,12 @@ This required option specifies the remote BD_ADDR of the RFCOMM server.
.It Fl b
Detach from the controlling terminal, i.e., run in background.
.It Fl c Ar channel
This required option specifies RFCOMM channel to connect to.
This channel must provide Serial Port service.
This option specifies RFCOMM channel to connect to.
The channel must provide Serial Port service.
If channel was not specified then
.Nm
utility will try to obtain RFCOMM channel via Service Discovery Protocol from
the server.
.It Fl h
Display usage message and exit.
.It Fl t Ar tty
@ -101,9 +105,7 @@ slave pseudo terminals
.Sh DIAGNOSTICS
.Ex -std
.Sh BUGS
The
.Nm
utility is not currently integrated with SDP (Service Discovery Protocol).
Please report if found.
.Sh SEE ALSO
.Xr ng_btsocket 4 ,
.Xr pty 4 ,

View file

@ -25,22 +25,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: rfcomm_sppd.c,v 1.2 2003/04/27 19:22:30 max Exp $
* $Id: rfcomm_sppd.c,v 1.4 2003/09/07 18:15:55 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <bitstring.h>
#include <bluetooth.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <limits.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <sdp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@ -54,6 +50,10 @@
#define SPPD_BUFFER_SIZE 1024
#define max(a, b) (((a) > (b))? (a) : (b))
int rfcomm_channel_lookup (bdaddr_t const *local,
bdaddr_t const *remote,
int service, int *channel, int *error);
static int sppd_ttys_open (char const *tty, int *amaster, int *aslave);
static int sppd_read (int fd, char *buffer, int size);
static int sppd_write (int fd, char *buffer, int size);
@ -79,21 +79,16 @@ main(int argc, char *argv[])
/* Parse command line options */
while ((n = getopt(argc, argv, "a:bc:t:h")) != -1) {
switch (n) {
case 'a': { /* BDADDR */
int a0, a1, a2, a3, a4, a5;
case 'a': /* BDADDR */
if (!bt_aton(optarg, &addr)) {
struct hostent *he = NULL;
if (sscanf(optarg, "%x:%x:%x:%x:%x:%x",
&a5, &a4, &a3, &a2, &a1, &a0) != 6)
usage();
/* NOT REACHED */
if ((he = bt_gethostbyname(optarg)) == NULL)
errx(1, "%s: %s", optarg, hstrerror(h_errno));
addr.b[0] = a0 & 0xff;
addr.b[1] = a1 & 0xff;
addr.b[2] = a2 & 0xff;
addr.b[3] = a3 & 0xff;
addr.b[4] = a4 & 0xff;
addr.b[5] = a5 & 0xff;
} break;
memcpy(&addr, he->h_addr, sizeof(addr));
}
break;
case 'c': /* RFCOMM channel */
channel = atoi(optarg);
@ -115,8 +110,7 @@ main(int argc, char *argv[])
}
/* Check if we have everything we need */
if (channel == 0 || tty == NULL ||
memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)
if (tty == NULL || memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)
usage();
/* NOT REACHED */
@ -139,6 +133,14 @@ main(int argc, char *argv[])
if (sigaction(SIGCHLD, &sa, NULL) < 0)
err(1, "Could not sigaction(SIGCHLD)");
/* Check channel, if was not set then obtain it via SDP */
if (channel == 0)
if (rfcomm_channel_lookup(NULL, &addr,
SDP_SERVICE_CLASS_SERIAL_PORT, &channel, &n) != 0)
errc(1, n, "Could not obtain RFCOMM channel");
if (channel <= 0 || channel > 30)
errx(1, "Invalid RFCOMM channel number %d", channel);
/* Open TTYs */
if (sppd_ttys_open(tty, &amaster, &aslave) < 0)
exit(1);
@ -374,7 +376,7 @@ usage(void)
"Where options are:\n" \
"\t-a bdaddr BDADDR to connect to (required)\n" \
"\t-b Run in background\n" \
"\t-c channel RFCOMM channel to connect to (required)\n" \
"\t-c channel RFCOMM channel to connect to\n" \
"\t-t tty TTY name\n" \
"\t-h Display this message\n", SPPD_IDENT);

View file

@ -184,6 +184,7 @@ SUBDIR+=elf2exe \
SUBDIR+=apm \
apmd \
asf \
bluetooth \
btxld \
kgmon \
kgzip \

View file

@ -1,14 +1,16 @@
# $Id: Makefile,v 1.3 2003/04/01 02:06:47 max Exp $
# $Id: Makefile,v 1.5 2003/09/08 02:28:35 max Exp $
# $FreeBSD$
SUBDIR= \
bt3cfw \
bcmfw \
hccontrol \
hcsecd \
hcseriald \
l2control \
l2ping \
rfcomm_pppd
SUBDIR= \
bcmfw \
bt3cfw \
hccontrol \
hcsecd \
hcseriald \
l2control \
l2ping \
rfcomm_pppd \
sdpcontrol
.include <bsd.subdir.mk>

View file

@ -0,0 +1,4 @@
# $FreeBSD$
.include "${.CURDIR}/../../Makefile.inc"

View file

@ -1,23 +1,9 @@
# $Id: Makefile,v 1.2 2003/04/27 00:44:54 max Exp $
# $Id: Makefile,v 1.6 2003/08/14 20:05:58 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= bcmfw
MAN8= bcmfw.8
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
MAN= bcmfw.8
SRCS= bcmfw.c
WARNS?= 2
#FILESDIR= ../local/etc/
#FILES+= BCM2033-FW.bin BCM2033-MD.hex
#CLEANFILES+= BCM2033-FW.bin BCM2033-MD.hex
#
#BCM2033-FW.bin: BCM2033-FW.bin.uue
# uudecode BCM2033-FW.bin.uue
#
#BCM2033-MD.hex: BCM2033-MD.hex.uue
# uudecode BCM2033-MD.hex.uue
#
.include <bsd.prog.mk>
#.include <bsd.files.mk>

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: bcmfw.8,v 1.4 2003/04/28 17:10:56 max Exp $
.\" $Id: bcmfw.8,v 1.7 2003/05/21 00:33:40 max Exp $
.\" $FreeBSD$
.\"
.Dd March 31, 2003
@ -51,6 +51,17 @@ The vendor ID should be 0x0a5c
.Pq Dv USB_VENDOR_BROADCOM
and the product ID should be 0x2033.
.Pp
Due to copyright issues I will no longer provide mini-driver and firmware
files for the device. These files can be obtained from the Linux BlueZ BlueFW
package.
.Pp
Visit http://bluez.sourceforge.net/download/download.html for details.
.Pp
I am using the following files:
.Pp
.Dl "MD5 (BCM2033-MD.hex) = 5580317158d07fc4ace90af04f8e1c73"
.Dl "MD5 (BCM2033-FW.bin) = a3a0edfcb85029f4a5d0b1c9649b127d"
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl f Ar firmware_file_name

View file

@ -1,13 +1,10 @@
# $Id: Makefile,v 1.2 2003/03/15 03:06:53 max Exp $
# $Id: Makefile,v 1.5 2003/08/14 20:06:00 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= bt3cfw
MAN8= bt3cfw.8
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
MAN= bt3cfw.8
SRCS= bt3cfw.c
WARNS?= 2
DPADD= ${LIBNETGRAPH}
LDADD= -lnetgraph

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: bt3cfw.8,v 1.3 2003/04/27 19:45:22 max Exp $
.\" $Id: bt3cfw.8,v 1.4 2003/05/21 00:34:51 max Exp $
.\" $FreeBSD$
.\"
.Dd November 11, 2002

View file

@ -25,20 +25,20 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bt3cfw.c,v 1.1 2002/11/24 20:22:37 max Exp $
* $Id: bt3cfw.c,v 1.2 2003/05/21 22:40:29 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <errno.h>
#include <netgraph.h>
#include <netgraph/bluetooth/include/ng_bt3c.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "ng_bt3c.h"
#define BT3CFW_IDENT "bt3cfw"
#define BT3CFW_MAX_FIRMWARE_SIZE 0xffff

View file

@ -1,14 +1,14 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:39 max Exp $
# $Id: Makefile,v 1.7 2003/08/14 20:06:17 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= hccontrol
MAN8= hccontrol.8
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
MAN= hccontrol.8
SRCS= send_recv.c link_policy.c link_control.c \
host_controller_baseband.c info.c status.c node.c hccontrol.c \
util.c
WARNS?= 2
DPADD= ${LIBBLUETOOTH}
LDADD= -lbluetooth
.include <bsd.prog.mk>

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: hccontrol.8,v 1.3 2003/04/27 19:45:23 max Exp $
.\" $Id: hccontrol.8,v 1.6 2003/08/06 21:26:38 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002
@ -33,7 +33,7 @@
.Nd HCI configuration utility
.Sh SYNOPSIS
.Nm
.Op Fl h
.Op Fl hN
.Fl n Ar HCI_node_name
.Ar command
.Op Ar parameters ...
@ -53,6 +53,11 @@ The options are as follows:
.Bl -tag -width indent
.It Fl h
Display usage message and exit.
.It Fl N
Show Bluetooth addresses as numbers.
Normally
.Nm
attempts to resolve Bluetooth addresses, and display them symbolically.
.It Fl n Ar HCI_node_name
Connect to the specified HCI Netgraph node.
.It Ar command
@ -118,6 +123,10 @@ are:
.It Cm Write_SCO_Flow_Control_Enable
.It Cm Read_Link_Supervision_Timeout
.It Cm Write_Link_Supervision_Timeout
.It Cm Read_Page_Scan_Period_Mode
.It Cm Write_Page_Scan_Period_Mode
.It Cm Read_Page_Scan_Mode
.It Cm Write_Page_Scan_Mode
.It Cm Read_Local_Version_Information
.It Cm Read_Local_Supported_Features
.It Cm Read_Buffer_Size

View file

@ -25,20 +25,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hccontrol.c,v 1.2 2003/04/27 19:45:24 max Exp $
* $Id: hccontrol.c,v 1.5 2003/09/05 00:38:24 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <bluetooth.h>
#include <sys/sysctl.h>
#include <assert.h>
#include <bitstring.h>
#include <err.h>
#include <errno.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -54,6 +49,7 @@ static void usage (void);
/* Globals */
int verbose = 0;
int timeout;
int numeric_bdaddr = 0;
/* Main */
int
@ -63,12 +59,16 @@ main(int argc, char *argv[])
int n;
/* Process command line arguments */
while ((n = getopt(argc, argv, "n:vh")) != -1) {
while ((n = getopt(argc, argv, "n:Nvh")) != -1) {
switch (n) {
case 'n':
node = optarg;
break;
case 'N':
numeric_bdaddr = 1;
break;
case 'v':
verbose = 1;
break;
@ -254,7 +254,7 @@ find_hci_command(char const *command, struct hci_command *category)
return (NULL);
} /* find_hci_command */
/* Try to find command in specified category */
/* Print commands in specified category */
static void
print_hci_command(struct hci_command *category)
{

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hccontrol.h,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: hccontrol.h,v 1.2 2003/05/19 17:29:29 max Exp $
* $FreeBSD$
*/
@ -70,6 +70,7 @@ char const * const hci_features2str (u_int8_t *, char *, int);
char const * const hci_cc2str (int);
char const * const hci_con_state2str (int);
char const * const hci_status2str (int);
char const * const hci_bdaddr2str (bdaddr_t const *);
#endif /* _HCCONTROL_H_ */

View file

@ -25,14 +25,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: host_controller_baseband.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: host_controller_baseband.c,v 1.4 2003/08/18 19:19:53 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <stdio.h>
#include <string.h>
#include "hccontrol.h"
@ -189,7 +187,7 @@ hci_read_stored_link_key(int s, int argc, char **argv)
} ep;
} __attribute__ ((packed)) event;
int n,a0,a1,a2,a3,a4,a5;
int n, n1;
/* Send command */
memset(&cmd, 0, sizeof(cmd));
@ -201,16 +199,14 @@ hci_read_stored_link_key(int s, int argc, char **argv)
switch (argc) {
case 1:
/* parse BD_ADDR */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", &a5, &a4, &a3, &a2,
&a1, &a0) != 6)
return (USAGE);
if (!bt_aton(argv[0], &cmd.cp.bdaddr)) {
struct hostent *he = NULL;
cmd.cp.bdaddr.b[0] = (a0 & 0xff);
cmd.cp.bdaddr.b[1] = (a1 & 0xff);
cmd.cp.bdaddr.b[2] = (a2 & 0xff);
cmd.cp.bdaddr.b[3] = (a3 & 0xff);
cmd.cp.bdaddr.b[4] = (a4 & 0xff);
cmd.cp.bdaddr.b[5] = (a5 & 0xff);
if ((he = bt_gethostbyname(argv[0])) == NULL)
return (USAGE);
memcpy(&cmd.cp.bdaddr, he->h_addr, sizeof(cmd.cp.bdaddr));
}
break;
default:
@ -269,13 +265,11 @@ hci_read_stored_link_key(int s, int argc, char **argv)
k = (struct _key *)(event.ep.b + sizeof(event.ep.key));
for (n = 0; n < event.ep.key.num_keys; n++) {
fprintf(stdout, "\t%d: %02x:%02x:%02x:%02x:%02x:%02x ",
n + 1,
k->bdaddr.b[5], k->bdaddr.b[4], k->bdaddr.b[3],
k->bdaddr.b[2], k->bdaddr.b[1], k->bdaddr.b[0]);
fprintf(stdout, "\t%d: %s ",
n + 1, hci_bdaddr2str(&k->bdaddr));
for (a0 = 0; a0 < sizeof(k->key); a0++)
fprintf(stdout, "%02x", k->key[a0]);
for (n1 = 0; n1 < sizeof(k->key); n1++)
fprintf(stdout, "%02x", k->key[n1]);
fprintf(stdout, "\n");
k ++;
@ -302,7 +296,7 @@ hci_write_stored_link_key(int s, int argc, char **argv)
u_int8_t key[NG_HCI_KEY_SIZE];
} cp;
ng_hci_write_stored_link_key_rp rp;
int32_t n, a0, a1, a2, a3, a4, a5;
int32_t n;
memset(&cp, 0, sizeof(cp));
@ -311,16 +305,14 @@ hci_write_stored_link_key(int s, int argc, char **argv)
cp.p.num_keys_write = 1;
/* parse BD_ADDR */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
&a5, &a4, &a3, &a2, &a1, &a0) != 6)
return (USAGE);
if (!bt_aton(argv[0], &cp.bdaddr)) {
struct hostent *he = NULL;
cp.bdaddr.b[0] = (a0 & 0xff);
cp.bdaddr.b[1] = (a1 & 0xff);
cp.bdaddr.b[2] = (a2 & 0xff);
cp.bdaddr.b[3] = (a3 & 0xff);
cp.bdaddr.b[4] = (a4 & 0xff);
cp.bdaddr.b[5] = (a5 & 0xff);
if ((he = bt_gethostbyname(argv[0])) == NULL)
return (USAGE);
memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
}
/* parse key */
if (hci_hexstring2array(argv[1], cp.key, sizeof(cp.key)) < 0)
@ -357,23 +349,21 @@ hci_delete_stored_link_key(int s, int argc, char **argv)
{
ng_hci_delete_stored_link_key_cp cp;
ng_hci_delete_stored_link_key_rp rp;
int32_t n, a0, a1, a2, a3, a4, a5;
int32_t n;
memset(&cp, 0, sizeof(cp));
switch (argc) {
case 1:
/* parse BD_ADDR */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
&a5, &a4, &a3, &a2, &a1, &a0) != 6)
return (USAGE);
if (!bt_aton(argv[0], &cp.bdaddr)) {
struct hostent *he = NULL;
cp.bdaddr.b[0] = (a0 & 0xff);
cp.bdaddr.b[1] = (a1 & 0xff);
cp.bdaddr.b[2] = (a2 & 0xff);
cp.bdaddr.b[3] = (a3 & 0xff);
cp.bdaddr.b[4] = (a4 & 0xff);
cp.bdaddr.b[5] = (a5 & 0xff);
if ((he = bt_gethostbyname(argv[0])) == NULL)
return (USAGE);
memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
}
break;
default:
@ -1372,6 +1362,131 @@ hci_write_link_supervision_timeout(int s, int argc, char **argv)
return (OK);
} /* hci_write_link_supervision_timeout */
/* Send Read_Page_Scan_Period_Mode command to the unit */
static int
hci_read_page_scan_period_mode(int s, int argc, char **argv)
{
ng_hci_read_page_scan_period_rp rp;
int n;
n = sizeof(rp);
if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
NG_HCI_OCF_READ_PAGE_SCAN_PERIOD),
(char *) &rp, &n) == ERROR)
return (ERROR);
if (rp.status != 0x00) {
fprintf(stdout, "Status: %s [%#02x]\n",
hci_status2str(rp.status), rp.status);
return (FAILED);
}
fprintf(stdout, "Page scan period mode: %#02x\n",
rp.page_scan_period_mode);
return (OK);
} /* hci_read_page_scan_period_mode */
/* Send Write_Page_Scan_Period_Mode command to the unit */
static int
hci_write_page_scan_period_mode(int s, int argc, char **argv)
{
ng_hci_write_page_scan_period_cp cp;
ng_hci_write_page_scan_period_rp rp;
int n;
/* parse command arguments */
switch (argc) {
case 1:
if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 2)
return (USAGE);
cp.page_scan_period_mode = (n & 0xff);
break;
default:
return (USAGE);
}
/* send command */
n = sizeof(rp);
if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD),
(char const *) &cp, sizeof(cp),
(char *) &rp, &n) == ERROR)
return (ERROR);
if (rp.status != 0x00) {
fprintf(stdout, "Status: %s [%#02x]\n",
hci_status2str(rp.status), rp.status);
return (FAILED);
}
return (OK);
} /* hci_write_page_scan_period_mode */
/* Send Read_Page_Scan_Mode command to the unit */
static int
hci_read_page_scan_mode(int s, int argc, char **argv)
{
ng_hci_read_page_scan_rp rp;
int n;
n = sizeof(rp);
if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
NG_HCI_OCF_READ_PAGE_SCAN),
(char *) &rp, &n) == ERROR)
return (ERROR);
if (rp.status != 0x00) {
fprintf(stdout, "Status: %s [%#02x]\n",
hci_status2str(rp.status), rp.status);
return (FAILED);
}
fprintf(stdout, "Page scan mode: %#02x\n", rp.page_scan_mode);
return (OK);
} /* hci_read_page_scan_mode */
/* Send Write_Page_Scan_Mode command to the unit */
static int
hci_write_page_scan_mode(int s, int argc, char **argv)
{
ng_hci_write_page_scan_cp cp;
ng_hci_write_page_scan_rp rp;
int n;
/* parse command arguments */
switch (argc) {
case 1:
if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 3)
return (USAGE);
cp.page_scan_mode = (n & 0xff);
break;
default:
return (USAGE);
}
/* send command */
n = sizeof(rp);
if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
NG_HCI_OCF_WRITE_PAGE_SCAN),
(char const *) &cp, sizeof(cp),
(char *) &rp, &n) == ERROR)
return (ERROR);
if (rp.status != 0x00) {
fprintf(stdout, "Status: %s [%#02x]\n",
hci_status2str(rp.status), rp.status);
return (FAILED);
}
return (OK);
} /* hci_write_page_scan_mode */
struct hci_command host_controller_baseband_commands[] = {
{
"reset",
@ -1708,6 +1823,55 @@ struct hci_command host_controller_baseband_commands[] = {
"\t<timeout> - dddd; timeout measured in number of baseband slots\n",
&hci_write_link_supervision_timeout
},
{
"read_page_scan_period_mode",
"\nThis command is used to read the mandatory Page_Scan_Period_Mode of the\n" \
"local Bluetooth device. Every time an inquiry response message is sent, the\n"\
"Bluetooth device will start a timer (T_mandatory_pscan), the value of which\n"\
"is dependent on the Page_Scan_Period_Mode. As long as this timer has not\n" \
"expired, the Bluetooth device will use the Page_Scan_Period_Mode for all\n" \
"following page scans.",
&hci_read_page_scan_period_mode
},
{
"write_page_scan_period_mode <page_scan_period_mode>",
"\nThis command is used to write the mandatory Page_Scan_Period_Mode of the\n" \
"local Bluetooth device. Every time an inquiry response message is sent, the\n"\
"Bluetooth device will start a timer (T_mandatory_pscan), the value of which\n"\
"is dependent on the Page_Scan_Period_Mode. As long as this timer has not\n" \
"expired, the Bluetooth device will use the Page_Scan_Period_Mode for all\n" \
"following page scans.\n\n" \
"\t<page_scan_period_mode> - dd; page scan period mode:\n" \
"\t0x00 - P0 (Default)\n" \
"\t0x01 - P1\n" \
"\t0x02 - P2",
&hci_write_page_scan_period_mode
},
{
"read_page_scan_mode",
"\nThis command is used to read the default page scan mode of the local\n" \
"Bluetooth device. The Page_Scan_Mode parameter indicates the page scan mode\n"\
"that is used for the default page scan. Currently one mandatory page scan\n"\
"mode and three optional page scan modes are defined. Following an inquiry\n" \
"response, if the Baseband timer T_mandatory_pscan has not expired, the\n" \
"mandatory page scan mode must be applied.",
&hci_read_page_scan_mode
},
{
"write_page_scan_mode <page_scan_mode>",
"\nThis command is used to write the default page scan mode of the local\n" \
"Bluetooth device. The Page_Scan_Mode parameter indicates the page scan mode\n"\
"that is used for the default page scan. Currently, one mandatory page scan\n"\
"mode and three optional page scan modes are defined. Following an inquiry\n"\
"response, if the Baseband timer T_mandatory_pscan has not expired, the\n" \
"mandatory page scan mode must be applied.\n\n" \
"\t<page_scan_mode> - dd; page scan mode:\n" \
"\t0x00 - Mandatory Page Scan Mode (Default)\n" \
"\t0x01 - Optional Page Scan Mode I\n" \
"\t0x02 - Optional Page Scan Mode II\n" \
"\t0x03 - Optional Page Scan Mode III",
&hci_write_page_scan_mode
},
{ NULL, }
};

View file

@ -25,14 +25,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: info.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: info.c,v 1.3 2003/08/18 19:19:54 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <stdio.h>
#include <string.h>
#include "hccontrol.h"
@ -173,9 +171,7 @@ hci_read_bd_addr(int s, int argc, char **argv)
return (FAILED);
}
fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
rp.bdaddr.b[5], rp.bdaddr.b[4], rp.bdaddr.b[3],
rp.bdaddr.b[2], rp.bdaddr.b[1], rp.bdaddr.b[0]);
fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&rp.bdaddr, NULL));
return (OK);
} /* hci_read_bd_addr */

View file

@ -25,14 +25,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: link_control.c,v 1.2 2003/03/15 03:07:39 max Exp $
* $Id: link_control.c,v 1.4 2003/08/18 19:19:54 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <stdio.h>
#include <string.h>
#include "hccontrol.h"
@ -158,9 +156,7 @@ hci_inquiry_response(int n, u_int8_t **b)
} *ir = (struct inquiry_response *)(*b);
fprintf(stdout, "Inquiry result #%d\n", n);
fprintf(stdout, "\tBD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
ir->bdaddr.b[5], ir->bdaddr.b[4], ir->bdaddr.b[3],
ir->bdaddr.b[2], ir->bdaddr.b[1], ir->bdaddr.b[0]);
fprintf(stdout, "\tBD_ADDR: %s\n", hci_bdaddr2str(&ir->bdaddr));
fprintf(stdout, "\tPage Scan Rep. Mode: %#02x\n",
ir->page_scan_rep_mode);
fprintf(stdout, "\tPage Scan Period Mode: %#02x\n",
@ -179,7 +175,7 @@ hci_inquiry_response(int n, u_int8_t **b)
static int
hci_create_connection(int s, int argc, char **argv)
{
int n0, n1, n2, n3, n4, n5;
int n0;
char b[512];
ng_hci_create_con_cp cp;
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b;
@ -241,16 +237,14 @@ hci_create_connection(int s, int argc, char **argv)
case 1:
/* BD_ADDR */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
&n5, &n4, &n3, &n2, &n1, &n0) != 6)
return (USAGE);
if (!bt_aton(argv[0], &cp.bdaddr)) {
struct hostent *he = NULL;
cp.bdaddr.b[0] = (n0 & 0xff);
cp.bdaddr.b[1] = (n1 & 0xff);
cp.bdaddr.b[2] = (n2 & 0xff);
cp.bdaddr.b[3] = (n3 & 0xff);
cp.bdaddr.b[4] = (n4 & 0xff);
cp.bdaddr.b[5] = (n5 & 0xff);
if ((he = bt_gethostbyname(argv[0])) == NULL)
return (USAGE);
memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
}
break;
default:
@ -286,9 +280,7 @@ hci_create_connection(int s, int argc, char **argv)
return (FAILED);
}
fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3],
ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]);
fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
fprintf(stdout, "Connection handle: %d\n",
le16toh(ep->con_handle));
fprintf(stdout, "Encryption mode: %s [%d]\n",
@ -443,9 +435,7 @@ hci_add_sco_connection(int s, int argc, char **argv)
return (FAILED);
}
fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3],
ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]);
fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
fprintf(stdout, "Connection handle: %d\n",
le16toh(ep->con_handle));
fprintf(stdout, "Encryption mode: %s [%d]\n",
@ -531,7 +521,7 @@ hci_change_connection_packet_type(int s, int argc, char **argv)
static int
hci_remote_name_request(int s, int argc, char **argv)
{
int n0, n1, n2, n3, n4, n5;
int n0;
char b[512];
ng_hci_remote_name_req_cp cp;
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b;
@ -566,16 +556,14 @@ hci_remote_name_request(int s, int argc, char **argv)
case 1:
/* BD_ADDR */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
&n5, &n4, &n3, &n2, &n1, &n0) != 6)
return (USAGE);
if (!bt_aton(argv[0], &cp.bdaddr)) {
struct hostent *he = NULL;
cp.bdaddr.b[0] = (n0 & 0xff);
cp.bdaddr.b[1] = (n1 & 0xff);
cp.bdaddr.b[2] = (n2 & 0xff);
cp.bdaddr.b[3] = (n3 & 0xff);
cp.bdaddr.b[4] = (n4 & 0xff);
cp.bdaddr.b[5] = (n5 & 0xff);
if ((he = bt_gethostbyname(argv[0])) == NULL)
return (USAGE);
memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
}
break;
default:
@ -612,9 +600,7 @@ hci_remote_name_request(int s, int argc, char **argv)
return (FAILED);
}
fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3],
ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]);
fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
fprintf(stdout, "Name: %s\n", ep->name);
} else
goto again;

View file

@ -25,15 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: link_policy.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: link_policy.c,v 1.3 2003/08/18 19:19:54 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <stdio.h>
#include <string.h>
#include "hccontrol.h"
/* Send Role Discovery to the unit */
@ -84,7 +83,7 @@ hci_role_discovery(int s, int argc, char **argv)
static int
hci_switch_role(int s, int argc, char **argv)
{
int n0, n1, n2, n3, n4, n5;
int n0;
char b[512];
ng_hci_switch_role_cp cp;
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b;
@ -93,16 +92,14 @@ hci_switch_role(int s, int argc, char **argv)
switch (argc) {
case 2:
/* bdaddr */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
&n5, &n4, &n3, &n2, &n1, &n0) != 6)
return (USAGE);
if (!bt_aton(argv[0], &cp.bdaddr)) {
struct hostent *he = NULL;
cp.bdaddr.b[0] = n0 & 0xff;
cp.bdaddr.b[1] = n1 & 0xff;
cp.bdaddr.b[2] = n2 & 0xff;
cp.bdaddr.b[3] = n3 & 0xff;
cp.bdaddr.b[4] = n4 & 0xff;
cp.bdaddr.b[5] = n5 & 0xff;
if ((he = bt_gethostbyname(argv[0])) == NULL)
return (USAGE);
memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr));
}
/* role */
if (sscanf(argv[1], "%d", &n0) != 1)
@ -144,9 +141,7 @@ hci_switch_role(int s, int argc, char **argv)
return (FAILED);
}
fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3],
ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]);
fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr));
fprintf(stdout, "Role: %s [%#x]\n",
(ep->role == NG_HCI_ROLE_MASTER)? "Master" : "Slave",
ep->role);

View file

@ -25,18 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: node.c,v 1.4 2003/03/23 21:28:17 max Exp $
* $Id: node.c,v 1.6 2003/07/22 21:14:02 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <bitstring.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -142,9 +137,7 @@ hci_read_node_bd_addr(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
r.bdaddr.b[5], r.bdaddr.b[4], r.bdaddr.b[3],
r.bdaddr.b[2], r.bdaddr.b[1], r.bdaddr.b[0]);
fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&r.bdaddr, NULL));
return (OK);
} /* hci_read_node_bd_addr */
@ -243,14 +236,12 @@ hci_read_neighbor_cache(int s, int argc, char **argv)
for (n = 0; n < r.num_entries; n++) {
fprintf(stdout,
"%02x:%02x:%02x:%02x:%02x:%02x " \
"%-17.17s " \
"%02x %02x %02x %02x %02x %02x %02x %02x " \
"%#12x " \
"%#9x " \
"%#9x\n",
r.entries[n].bdaddr.b[5], r.entries[n].bdaddr.b[4],
r.entries[n].bdaddr.b[3], r.entries[n].bdaddr.b[2],
r.entries[n].bdaddr.b[1], r.entries[n].bdaddr.b[0],
hci_bdaddr2str(&r.entries[n].bdaddr),
r.entries[n].features[0], r.entries[n].features[1],
r.entries[n].features[2], r.entries[n].features[3],
r.entries[n].features[4], r.entries[n].features[5],
@ -297,7 +288,7 @@ hci_read_connection_list(int s, int argc, char **argv)
for (n = 0; n < r.num_connections; n++) {
fprintf(stdout,
"%02x:%02x:%02x:%02x:%02x:%02x " \
"%-17.17s " \
"%6d " \
"%4.4s " \
"%4d " \
@ -306,12 +297,7 @@ hci_read_connection_list(int s, int argc, char **argv)
"%7d " \
"%5d " \
"%s\n",
r.connections[n].bdaddr.b[5],
r.connections[n].bdaddr.b[4],
r.connections[n].bdaddr.b[3],
r.connections[n].bdaddr.b[2],
r.connections[n].bdaddr.b[1],
r.connections[n].bdaddr.b[0],
hci_bdaddr2str(&r.connections[n].bdaddr),
r.connections[n].con_handle,
(r.connections[n].link_type == NG_HCI_LINK_ACL)?
"ACL" : "SCO",

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: send_recv.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: send_recv.c,v 1.2 2003/05/21 22:40:30 max Exp $
* $FreeBSD$
*/
@ -35,7 +35,7 @@
#include <sys/endian.h>
#include <assert.h>
#include <errno.h>
#include <ng_hci.h>
#include <netgraph/bluetooth/include/ng_hci.h>
#include <string.h>
#include <unistd.h>
#include "hccontrol.h"

View file

@ -25,14 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: status.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: status.c,v 1.2 2003/05/21 22:40:30 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <errno.h>
#include <ng_hci.h>
#include <netgraph/bluetooth/include/ng_hci.h>
#include <stdio.h>
#include "hccontrol.h"

View file

@ -25,11 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: util.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $Id: util.c,v 1.2 2003/05/19 17:29:29 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/param.h>
#include <bluetooth.h>
#include <stdio.h>
#include <string.h>
#define SIZE(x) (sizeof((x))/sizeof((x)[0]))
@ -348,3 +350,29 @@ hci_status2str(int status)
return (status >= SIZE(t)? "Unknown error" : t[status]);
} /* hci_status2str */
char const * const
hci_bdaddr2str(bdaddr_t const *ba)
{
extern int numeric_bdaddr;
static char buffer[MAXHOSTNAMELEN];
struct hostent *he = NULL;
if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {
buffer[0] = '*';
buffer[1] = 0;
return (buffer);
}
if (!numeric_bdaddr &&
(he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {
strlcpy(buffer, he->h_name, sizeof(buffer));
return (buffer);
}
bt_ntoa(ba, buffer);
return (buffer);
} /* hci_bdaddr2str */

View file

@ -1,12 +1,13 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:42 max Exp $
# $Id: Makefile,v 1.8 2003/08/14 20:06:20 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= hcsecd
MAN8= hcsecd.8
WARNS?= 1
CFLAGS+= -g -I${.CURDIR} -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
MAN= hcsecd.8 hcsecd.conf.5
SRCS= hcsecd.c lexer.l parser.y
WARNS?= 1
CFLAGS+= -I${.CURDIR}
DPADD= ${LIBBLUETOOTH}
LDADD= -lbluetooth
.include <bsd.prog.mk>

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: hcsecd.8,v 1.3 2003/04/27 19:45:32 max Exp $
.\" $Id: hcsecd.8,v 1.8 2003/09/08 18:54:20 max Exp $
.\" $FreeBSD$
.\"
.Dd November 16, 2002
@ -38,22 +38,28 @@
.Sh DESCRIPTION
The
.Nm
daemon controls link keys and PIN code for Bluetooth devices.
daemon controls link keys and PIN codes for Bluetooth devices.
It opens raw HCI socket and listens for the
.Dv Link_Key_Request
and
.Dv Link_Key_Request ,
.Dv PIN_Code_Request
and
.Dv Link_Key_Notification
HCI events.
Once appropriate HCI event has been received, the daemon will
.Pp
Once
.Dv Link_Key_Request
or
.Dv PIN_Code_Request
HCI event is received, the daemon will
scan configuration file for matching entry.
The remove device BD_ADDR is used as a key.
The remote device BD_ADDR is used as a key.
If no matching entry was found, the default entry will be used.
If no default entry was found then it is assumed that no link key and no PIN code
exist.
If no default entry was found then it is assumed that no link key and no
PIN code exists.
For any given entry, link key takes precedence over PIN code.
If link key was not specified, it means device must generate link key from
PIN code.
If entry was found and has the link key (or PIN code) then the
If entry was found and the link key (or PIN code) exists then the
.Dv Link_Key_Request_Reply
(or
.Dv PIN_Code_Request_Reply )
@ -66,12 +72,28 @@ command will be sent back to the device.
.Pp
The
.Nm
daemon currently does not handle HCI
daemon also handles HCI
.Dv Link_Key_Notification
event and does not cache link keys created from the PIN codes.
It means that the link key only exists while connection is opened.
After the connection has been terminated, the user will have to enter PIN code
again.
event and caches link keys created from the PIN codes in the memory.
To preserve link keys between restarts the
.Nm
daemon dumps link keys for all entries in the
.Pa /var/db/hcsecd.keys
link keys file.
If exists, the link keys file gets processed by
.Nm
daemon after it processes its main configuration file.
The link keys file gets written every time
.Nm
daemon is gracefully shutdown.
It is possible to force
.Nm
daemon to re-read its main configuration file and dump link keys file by sending
.Dv HUP
signal to the
.Nm
process.
User is not expected to modify link keys file by hand.
.Pp
The command line options are as follows:
.Bl -tag -width indent
@ -80,7 +102,7 @@ Do not detach from the controlling terminal.
.It Fl f Ar configfile
Specify name of the configuration file.
The default is
.Pa /usr/local/etc/hcsecd.conf .
.Pa /etc/bluetooth/hcsecd.conf .
.It Fl h
Display usage message and exit.
.El
@ -91,15 +113,15 @@ Everything is based on remote device BD_ADDR.
Also might implement interface for external helpers to obtain link keys and
PIN codes.
.Sh FILES
.Bl -tag -width ".Pa /usr/local/etc/hcsecd.conf" -compact
.It Pa /usr/local/etc/hcsecd.conf
.It Pa /var/run/hcsecd.pid
.Bl -tag -width ".Pa /etc/bluetooth/hcsecd.conf" -compact
.It Pa /etc/bluetooth/hcsecd.conf
.It Pa /var/db/hcsecd.pid
.It Pa /var/run/hcsecd.keys
.El
.Sh SEE ALSO
.Xr netgraph 3 ,
.Xr netgraph 4 ,
.Xr ng_btsocket 4 ,
.Xr ng_hci 4 ,
.Xr hcsecd.conf 5 ,
.Xr hccontrol 8 ,
.Xr hcseriald 8
.Sh AUTHORS

View file

@ -25,20 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hcsecd.c,v 1.3 2003/04/27 19:45:32 max Exp $
* $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <bitstring.h>
#include <bluetooth.h>
#include <err.h>
#include <errno.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@ -48,10 +42,6 @@
#include <unistd.h>
#include "hcsecd.h"
#define HCSECD_BUFFER_SIZE 512
#define HCSECD_IDENT "hcsecd"
#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid"
static int done = 0;
static int process_pin_code_request_event
@ -62,6 +52,10 @@ static int send_pin_code_reply
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
static int send_link_key_reply
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, u_int8_t *key);
static int process_link_key_notification_event
(int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep);
static void sighup
(int s);
static void sigint
(int s);
static void usage
@ -115,7 +109,7 @@ main(int argc, char *argv[])
err(1, "Could not sigaction(SIGINT)");
memset(&sa, 0, sizeof(sa));
sa.sa_handler = read_config_file;
sa.sa_handler = sighup;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err(1, "Could not sigaction(SIGHUP)");
@ -127,6 +121,7 @@ main(int argc, char *argv[])
memset(&filter, 0, sizeof(filter));
bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
(void * const) &filter, sizeof(filter)) < 0)
@ -138,7 +133,8 @@ main(int argc, char *argv[])
openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
read_config_file(0);
read_config_file();
read_keys_file();
if (detach) {
FILE *pid = NULL;
@ -184,6 +180,11 @@ main(int argc, char *argv[])
(bdaddr_p)(event + 1));
break;
case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
process_link_key_notification_event(sock, &addr,
(ng_hci_link_key_notification_ep *)(event + 1));
break;
default:
syslog(LOG_ERR, "Received unexpected HCI event, " \
"event=%#x", event->event);
@ -196,6 +197,7 @@ main(int argc, char *argv[])
syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
HCSECD_PIDFILE, strerror(errno), errno);
dump_keys_file();
clean_config();
closelog();
close(sock);
@ -211,27 +213,21 @@ process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
link_key_p key = NULL;
syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \
"remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
"remote bdaddr %s", addr->hci_node,
bt_ntoa(bdaddr, NULL));
if ((key = get_key(bdaddr, 0)) != NULL) {
syslog(LOG_DEBUG, "Found matching entry, " \
"remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \
"PIN code %s",
key->bdaddr.b[5], key->bdaddr.b[4],
key->bdaddr.b[3], key->bdaddr.b[2],
key->bdaddr.b[1], key->bdaddr.b[0],
"remote bdaddr %s, name '%s', PIN code %s",
bt_ntoa(&key->bdaddr, NULL),
(key->name != NULL)? key->name : "No name",
(key->pin != NULL)? "exists" : "doesn't exist");
return (send_pin_code_reply(sock, addr, bdaddr, key->pin));
}
syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr " \
"%x:%x:%x:%x:%x:%x",
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s",
bt_ntoa(bdaddr, NULL));
return (send_pin_code_reply(sock, addr, bdaddr, NULL));
}
@ -244,27 +240,21 @@ process_link_key_request_event(int sock, struct sockaddr_hci *addr,
link_key_p key = NULL;
syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \
"remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
"remote bdaddr %s", addr->hci_node,
bt_ntoa(bdaddr, NULL));
if ((key = get_key(bdaddr, 0)) != NULL) {
syslog(LOG_DEBUG, "Found matching entry, " \
"remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \
"link key %s",
key->bdaddr.b[5], key->bdaddr.b[4],
key->bdaddr.b[3], key->bdaddr.b[2],
key->bdaddr.b[1], key->bdaddr.b[0],
"remote bdaddr %s, name '%s', link key %s",
bt_ntoa(&key->bdaddr, NULL),
(key->name != NULL)? key->name : "No name",
(key->key != NULL)? "exists" : "doesn't exist");
return (send_link_key_reply(sock, addr, bdaddr, key->key));
}
syslog(LOG_DEBUG, "Could not find link key for remote bdaddr " \
"%x:%x:%x:%x:%x:%x",
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s",
bt_ntoa(bdaddr, NULL));
return (send_link_key_reply(sock, addr, bdaddr, NULL));
}
@ -295,10 +285,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr,
cp->pin_size = strlen(cp->pin);
syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \
"for remote bdaddr %x:%x:%x:%x:%x:%x",
addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
"for remote bdaddr %s",
addr->hci_node, bt_ntoa(bdaddr, NULL));
} else {
ng_hci_pin_code_neg_rep_cp *cp = NULL;
@ -310,10 +298,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr,
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \
"for remote bdaddr %x:%x:%x:%x:%x:%x",
addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
"for remote bdaddr %s",
addr->hci_node, bt_ntoa(bdaddr, NULL));
}
again:
@ -323,10 +309,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr,
goto again;
syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \
"for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)",
addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0],
"for remote bdaddr %s. %s (%d)",
addr->hci_node, bt_ntoa(bdaddr, NULL),
strerror(errno), errno);
return (-1);
}
@ -359,10 +343,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr,
memcpy(&cp->key, key, sizeof(cp->key));
syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \
"for remote bdaddr %x:%x:%x:%x:%x:%x",
addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
"for remote bdaddr %s",
addr->hci_node, bt_ntoa(bdaddr, NULL));
} else {
ng_hci_link_key_neg_rep_cp *cp = NULL;
@ -374,10 +356,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr,
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \
"for remote bdaddr %x:%x:%x:%x:%x:%x",
addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
"for remote bdaddr %s",
addr->hci_node, bt_ntoa(bdaddr, NULL));
}
again:
@ -387,10 +367,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr,
goto again;
syslog(LOG_ERR, "Could not send link key reply to '%s' " \
"for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)",
addr->hci_node,
bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
bdaddr->b[2], bdaddr->b[1], bdaddr->b[0],
"for remote bdaddr %s. %s (%d)",
addr->hci_node, bt_ntoa(bdaddr, NULL),
strerror(errno), errno);
return (-1);
}
@ -398,7 +376,53 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr,
return (0);
}
/* Signal handler */
/* Process Link_Key_Notification event */
static int
process_link_key_notification_event(int sock, struct sockaddr_hci *addr,
ng_hci_link_key_notification_ep *ep)
{
link_key_p key = NULL;
syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \
"remote bdaddr %s", addr->hci_node,
bt_ntoa(&ep->bdaddr, NULL));
if ((key = get_key(&ep->bdaddr, 1)) == NULL) {
syslog(LOG_ERR, "Could not find entry for remote bdaddr %s",
bt_ntoa(&ep->bdaddr, NULL));
return (-1);
}
syslog(LOG_DEBUG, "Updating link key for the entry, " \
"remote bdaddr %s, name '%s', link key %s",
bt_ntoa(&key->bdaddr, NULL),
(key->name != NULL)? key->name : "No name",
(key->key != NULL)? "exists" : "doesn't exist");
if (key->key == NULL) {
key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE);
if (key->key == NULL) {
syslog(LOG_ERR, "Could not allocate link key");
exit(1);
}
}
memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE);
return (0);
}
/* Signal handlers */
static void
sighup(int s)
{
syslog(LOG_DEBUG, "Got SIGHUP (%d)", s);
dump_keys_file();
read_config_file();
read_keys_file();
}
static void
sigint(int s)
{

View file

@ -0,0 +1,129 @@
.\" 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: hcsecd.conf.5,v 1.1 2003/05/26 22:49:23 max Exp $
.\" $FreeBSD$
.\"
.Dd May 26, 2003
.Dt HCSECD.CONF 5
.Os
.Sh NAME
.Nm hcsecd.conf
.Nd
.Xr hcsecd 8
configuration file
.Sh DESCRIPTION
The
.Nm
file is the configuration file for the
.Xr hcsecd 8
Bluetooth link keys/PIN codes management daemon.
.Pp
The
.Nm
file is a free-form ASCII text file.
It is parsed by the recursive-descent parser built into
.Xr hcsecd 8 .
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
.Dq #
character and end at the end of the line.
.Sh FILE FORMAT
The
.Nm
file consists of a list of
.Cm device
entries.
Each
.Cm device
entry defines a link key or PIN code for a remote Bluetooth device.
Each remote Bluetooth device is identified by its unique BD_ADDR.
.Pp
The
.Cm device
entry
.Pp
.Cm device
{
.Cm option Ar argument ;
.Oo
.Cm option Ar argument ;
.Oc
}
.Pp
The following section describes all supported options and arguments
.Bl -tag -width indent
.It Cm bdaddr Ar BD_ADDR
Specify remote device BD_ADDR for the entry.
.It Cm name Ar device_name
Specify user friendly name for the entry.
Name is a string in a straight double quotes.
.It Cm key Ar link_key
Specify link key for the entry.
Link key is hexadecimal string upto 32 characters in length starting with
.Dq 0x .
.It Cm key nokey
Specify no link key for the entry.
.It Cm pin Ar PIN_code
Specify PIN code for the entry.
PIN code is a string upto 16 characters in length in a straight double quotes.
.It Cm pin nopin
Specify no PIN code for the entry.
.El
.Sh EXAMPLES
A sample
.Nm
file
.Bd -literal
# Default entry is applied if no better match found
# It MUST have 00:00:00:00:00:00 as bdaddr
device {
bdaddr 00:00:00:00:00:00;
name "Default entry";
key nokey;
pin nopin;
}
# Ericsson T68 phone
device {
bdaddr 00:80:37:5e:4d:d4;
name "Ericsson T68 phone";
key nokey;
pin "0000"; # PIN code
}
# Dummy device
device {
bdaddr 00:11:22:33:44:55;
name "Dummy";
key 0x00112233445566778899aabbccddeeff; # 16 bytes key
pin nopin;
}
.Ed
.Sh SEE ALSO
.Xr hcsecd 8
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View file

@ -25,13 +25,18 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hcsecd.h,v 1.1 2002/11/24 20:22:39 max Exp $
* $Id: hcsecd.h,v 1.3 2003/09/08 18:54:21 max Exp $
* $FreeBSD$
*/
#ifndef _HCSECD_H_
#define _HCSECD_H_ 1
#define HCSECD_BUFFER_SIZE 512
#define HCSECD_IDENT "hcsecd"
#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid"
#define HCSECD_KEYSFILE "/var/db/" HCSECD_IDENT ".keys"
struct link_key
{
bdaddr_t bdaddr; /* remote device BDADDR */
@ -49,9 +54,12 @@ extern char *config_file;
void dump_config (void);
#endif
void read_config_file(int s);
void read_config_file(void);
void clean_config (void);
link_key_p get_key (bdaddr_p bdaddr, int exact_match);
int read_keys_file (void);
int dump_keys_file (void);
#endif /* ndef _HCSECD_H_ */

View file

@ -26,14 +26,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: parser.y,v 1.1 2002/11/24 20:22:39 max Exp $
* $Id: parser.y,v 1.5 2003/06/07 21:22:30 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/queue.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@ -49,7 +50,7 @@ static int hexa2int8(char *a);
extern int yylineno;
static LIST_HEAD(, link_key) link_keys;
char *config_file = "/usr/local/etc/hcsecd.conf";
char *config_file = "/etc/bluetooth/hcsecd.conf";
static link_key_p key = NULL;
%}
@ -82,13 +83,8 @@ line: T_DEVICE
{
if (get_key(&key->bdaddr, 1) != NULL) {
syslog(LOG_ERR, "Ignoring duplicated entry " \
"for bdaddr %x:%x:%x:%x:%x:%x",
key->bdaddr.b[5],
key->bdaddr.b[4],
key->bdaddr.b[3],
key->bdaddr.b[2],
key->bdaddr.b[1],
key->bdaddr.b[0]);
"for bdaddr %s",
bt_ntoa(&key->bdaddr, NULL));
free_key(key);
} else
LIST_INSERT_HEAD(&link_keys, key, next);
@ -109,21 +105,11 @@ option: bdaddr
bdaddr: T_BDADDR T_BDADDRSTRING
{
int a0, a1, a2, a3, a4, a5;
if (sscanf($2, "%x:%x:%x:%x:%x:%x",
&a5, &a4, &a3, &a2, &a1, &a0) != 6) {
if (!bt_aton($2, &key->bdaddr)) {
syslog(LOG_ERR, "Cound not parse BDADDR " \
"'%s'", $2);
exit(1);
}
key->bdaddr.b[0] = (a0 & 0xff);
key->bdaddr.b[1] = (a1 & 0xff);
key->bdaddr.b[2] = (a2 & 0xff);
key->bdaddr.b[3] = (a3 & 0xff);
key->bdaddr.b[4] = (a4 & 0xff);
key->bdaddr.b[5] = (a5 & 0xff);
}
;
@ -205,7 +191,7 @@ yyerror(char const *message)
/* Re-read config file */
void
read_config_file(int s)
read_config_file(void)
{
extern FILE *yyin;
@ -286,18 +272,125 @@ dump_config(void)
syslog(LOG_DEBUG,
"device %s " \
"bdaddr %x:%x:%x:%x:%x:%x " \
"bdaddr %s " \
"pin %s " \
"key %s",
(key->name != NULL)? key->name : "noname",
key->bdaddr.b[5], key->bdaddr.b[4], key->bdaddr.b[3],
key->bdaddr.b[2], key->bdaddr.b[1], key->bdaddr.b[0],
bt_ntoa(&key->bdaddr, NULL),
(key->pin != NULL)? key->pin : "nopin",
(key->key != NULL)? buffer : "nokey");
}
}
#endif
/* Read keys file */
int
read_keys_file(void)
{
FILE *f = NULL;
link_key_t *key = NULL;
char buf[HCSECD_BUFFER_SIZE], *p = NULL, *cp = NULL;
bdaddr_t bdaddr;
int i, len;
if ((f = fopen(HCSECD_KEYSFILE, "r")) == NULL) {
if (errno == ENOENT)
return (0);
syslog(LOG_ERR, "Could not open keys file %s. %s (%d)\n",
HCSECD_KEYSFILE, strerror(errno), errno);
return (-1);
}
while ((p = fgets(buf, sizeof(buf), f)) != NULL) {
if (*p == '#')
continue;
if ((cp = strpbrk(p, " ")) == NULL)
continue;
*cp++ = '\0';
if (!bt_aton(p, &bdaddr))
continue;
if ((key = get_key(&bdaddr, 1)) == NULL)
continue;
if (key->key == NULL) {
key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE);
if (key->key == NULL) {
syslog(LOG_ERR, "Could not allocate link key");
exit(1);
}
}
memset(key->key, 0, NG_HCI_KEY_SIZE);
len = strlen(cp) / 2;
if (len > NG_HCI_KEY_SIZE)
len = NG_HCI_KEY_SIZE;
for (i = 0; i < len; i ++)
key->key[i] = hexa2int8(cp + 2*i);
syslog(LOG_DEBUG, "Restored link key for the entry, " \
"remote bdaddr %s, name '%s'",
bt_ntoa(&key->bdaddr, NULL),
(key->name != NULL)? key->name : "No name");
}
fclose(f);
return (0);
}
/* Dump keys file */
int
dump_keys_file(void)
{
link_key_p key = NULL;
char tmp[PATH_MAX], buf[HCSECD_BUFFER_SIZE];
int f;
snprintf(tmp, sizeof(tmp), "%s.tmp", HCSECD_KEYSFILE);
if ((f = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) {
syslog(LOG_ERR, "Could not create temp keys file %s. %s (%d)\n",
tmp, strerror(errno), errno);
return (-1);
}
LIST_FOREACH(key, &link_keys, next) {
if (key->key == NULL)
continue;
snprintf(buf, sizeof(buf),
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
bt_ntoa(&key->bdaddr, NULL),
key->key[0], key->key[1], key->key[2], key->key[3],
key->key[4], key->key[5], key->key[6], key->key[7],
key->key[8], key->key[9], key->key[10], key->key[11],
key->key[12], key->key[13], key->key[14], key->key[15]);
if (write(f, buf, strlen(buf)) < 0) {
syslog(LOG_ERR, "Could not write temp keys file. " \
"%s (%d)\n", strerror(errno), errno);
break;
}
}
close(f);
if (rename(tmp, HCSECD_KEYSFILE) < 0) {
syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n",
tmp, HCSECD_KEYSFILE, strerror(errno), errno);
unlink(tmp);
return (-1);
}
return (0);
}
/* Free key entry */
static void
free_key(link_key_p key)

View file

@ -1,15 +1,10 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:45 max Exp $
# $Id: Makefile,v 1.5 2003/08/14 20:06:21 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= hcseriald
MAN8= hcseriald.8
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
MAN= hcseriald.8
SRCS= hcseriald.c
WARNS?= 2
DPADD= ${LIBNETGRAPH}
LDADD= -lnetgraph

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: hcseriald.8,v 1.2 2003/04/27 19:45:33 max Exp $
.\" $Id: hcseriald.8,v 1.3 2003/05/21 00:47:26 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002

View file

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hcseriald.c,v 1.2 2003/04/27 19:45:33 max Exp $
* $Id: hcseriald.c,v 1.3 2003/05/21 22:40:32 max Exp $
* $FreeBSD$
*/
@ -34,7 +34,7 @@
#include <netgraph/ng_message.h>
#include <netgraph.h>
#include <ng_h4.h>
#include <netgraph/bluetooth/include/ng_h4.h>
#include <errno.h>
#include <fcntl.h>

View file

@ -1,12 +1,12 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:47 max Exp $
# $Id: Makefile,v 1.7 2003/08/14 20:06:22 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= l2control
MAN8= l2control.8
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
MAN= l2control.8
SRCS= l2cap.c l2control.c
WARNS?= 2
DPADD= ${LIBBLUETOOTH}
LDADD= -lbluetooth
.include <bsd.prog.mk>

View file

@ -25,17 +25,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: l2cap.c,v 1.4 2003/04/26 23:11:25 max Exp $
* $Id: l2cap.c,v 1.5 2003/05/16 19:52:37 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <bitstring.h>
#include <bluetooth.h>
#include <errno.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -43,6 +39,33 @@
#define SIZE(x) (sizeof((x))/sizeof((x)[0]))
/* Print BDADDR */
static char *
bdaddrpr(bdaddr_t const *ba)
{
extern int numeric_bdaddr;
static char str[24];
struct hostent *he = NULL;
if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {
str[0] = '*';
str[1] = 0;
return (str);
}
if (!numeric_bdaddr &&
(he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {
strlcpy(str, he->h_name, sizeof(str));
return (str);
}
bt_ntoa(ba, str);
return (str);
} /* bdaddrpr */
/* Send read_node_flags command to the node */
static int
l2cap_read_node_flags(int s, int argc, char **argv)
@ -134,17 +157,12 @@ l2cap_read_connection_list(int s, int argc, char **argv)
"Remote BD_ADDR Handle Flags Pending State\n");
for (n = 0; n < r.num_connections; n++) {
fprintf(stdout,
"%02x:%02x:%02x:%02x:%02x:%02x " \
"%-17.17s " \
"%6d " \
"%c%c%c%c%c " \
"%7d " \
"%s\n",
r.connections[n].remote.b[5],
r.connections[n].remote.b[4],
r.connections[n].remote.b[3],
r.connections[n].remote.b[2],
r.connections[n].remote.b[1],
r.connections[n].remote.b[0],
bdaddrpr(&r.connections[n].remote),
r.connections[n].con_handle,
((r.connections[n].flags & NG_L2CAP_CON_OUTGOING)? 'O' : 'I'),
((r.connections[n].flags & NG_L2CAP_CON_LP_TIMO)? 'L' : ' '),
@ -197,13 +215,11 @@ l2cap_read_channel_list(int s, int argc, char **argv)
"Remote BD_ADDR SCID/ DCID PSM IMTU/ OMTU State\n");
for (n = 0; n < r.num_channels; n++) {
fprintf(stdout,
"%02x:%02x:%02x:%02x:%02x:%02x " \
"%-17.17s " \
"%5d/%5d %5d " \
"%5d/%5d " \
"%s\n",
r.channels[n].remote.b[5], r.channels[n].remote.b[4],
r.channels[n].remote.b[3], r.channels[n].remote.b[2],
r.channels[n].remote.b[1], r.channels[n].remote.b[0],
bdaddrpr(&r.channels[n].remote),
r.channels[n].scid, r.channels[n].dcid,
r.channels[n].psm, r.channels[n].imtu,
r.channels[n].omtu,

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: l2control.8,v 1.3 2003/04/27 19:45:34 max Exp $
.\" $Id: l2control.8,v 1.5 2003/05/21 00:53:00 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002
@ -33,7 +33,7 @@
.Nd L2CAP configuration utility
.Sh SYNOPSIS
.Nm
.Op Fl h
.Op Fl hn
.Fl a Ar BD_ADDR
.Ar command
.Op Ar parameters ...
@ -55,6 +55,11 @@ Example:
.Fl a Li 00:01:02:03:04:05 .
.It Fl h
Display usage message and exit.
.It Fl n
Show Bluetooth addresses as numbers.
Normally
.Nm
attempts to resolve Bluetooth addresses, and display them symbolically.
.It Ar command
One of the supported commands (see below).
Special command

View file

@ -25,19 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: l2control.c,v 1.3 2003/04/27 19:45:34 max Exp $
* $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <bitstring.h>
#include <assert.h>
#include <bluetooth.h>
#include <err.h>
#include <errno.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -52,6 +47,9 @@ static void print_l2cap_command (struct l2cap_command *);
static void usage (void);
/* Main */
int numeric_bdaddr = 0;
int
main(int argc, char *argv[])
{
@ -61,24 +59,22 @@ main(int argc, char *argv[])
memset(&bdaddr, 0, sizeof(bdaddr));
/* Process command line arguments */
while ((n = getopt(argc, argv, "a:h")) != -1) {
while ((n = getopt(argc, argv, "a:nh")) != -1) {
switch (n) {
case 'a': {
int a0, a1, a2, a3, a4, a5;
case 'a':
if (!bt_aton(optarg, &bdaddr)) {
struct hostent *he = NULL;
if (sscanf(optarg, "%x:%x:%x:%x:%x:%x",
&a5, &a4, &a3, &a2, &a1, &a0) != 6) {
usage();
break;
if ((he = bt_gethostbyname(optarg)) == NULL)
errx(1, "%s: %s", optarg, hstrerror(h_errno));
memcpy(&bdaddr, he->h_addr, sizeof(bdaddr));
}
break;
bdaddr.b[0] = (a0 & 0xff);
bdaddr.b[1] = (a1 & 0xff);
bdaddr.b[2] = (a2 & 0xff);
bdaddr.b[3] = (a3 & 0xff);
bdaddr.b[4] = (a4 & 0xff);
bdaddr.b[5] = (a5 & 0xff);
} break;
case 'n':
numeric_bdaddr = 1;
break;
case 'h':
default:
@ -144,10 +140,7 @@ do_l2cap_command(bdaddr_p bdaddr, int argc, char **argv)
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
err(2,
"Could not bind socket, bdaddr=%x:%x:%x:%x:%x:%x",
sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4],
sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2],
sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]);
"Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL));
e = 0x0ffff;
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0)
@ -200,7 +193,7 @@ find_l2cap_command(char const *command, struct l2cap_command *category)
return (NULL);
} /* find_l2cap_command */
/* Try to find command in specified category */
/* Print commands in specified category */
static void
print_l2cap_command(struct l2cap_command *category)
{
@ -214,7 +207,7 @@ print_l2cap_command(struct l2cap_command *category)
static void
usage(void)
{
fprintf(stdout, "Usage: l2control -a BD_ADDR [-h] cmd [p1] [..]]\n");
fprintf(stdout, "Usage: l2control -a BD_ADDR [-n] [-h] cmd [p1] [..]]\n");
exit(255);
} /* usage */

View file

@ -1,12 +1,12 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:49 max Exp $
# $Id: Makefile,v 1.6 2003/08/14 20:06:24 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= l2ping
MAN8= l2ping.8
MAN= l2ping.8
SRCS= l2ping.c
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
DPADD= ${LIBBLUETOOTH}
LDADD= -lbluetooth
.include <bsd.prog.mk>

View file

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: l2ping.8,v 1.2 2003/04/27 19:45:35 max Exp $
.\" $Id: l2ping.8,v 1.3 2003/05/21 01:00:19 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002

Some files were not shown because too many files have changed in this diff Show more