mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
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:
parent
907d866750
commit
0986ab12e4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121054
56
etc/bluetooth/hcsecd.conf
Normal file
56
etc/bluetooth/hcsecd.conf
Normal 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
11
etc/bluetooth/hosts
Normal 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
21
etc/bluetooth/protocols
Normal 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
|
||||
|
|
@ -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
30
lib/libbluetooth/Makefile
Normal 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>
|
293
lib/libbluetooth/bluetooth.3
Normal file
293
lib/libbluetooth/bluetooth.3
Normal 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
|
369
lib/libbluetooth/bluetooth.c
Normal file
369
lib/libbluetooth/bluetooth.c
Normal 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);
|
||||
}
|
||||
|
78
lib/libbluetooth/bluetooth.h
Normal file
78
lib/libbluetooth/bluetooth.h
Normal 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
33
lib/libsdp/Makefile
Normal 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
65
lib/libsdp/sdp-int.h
Normal 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
309
lib/libsdp/sdp.3
Normal 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
477
lib/libsdp/sdp.h
Normal 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
383
lib/libsdp/search.c
Normal 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
174
lib/libsdp/session.c
Normal 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
439
lib/libsdp/util.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 .
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
63
share/man/man5/bluetooth.hosts.5
Normal file
63
share/man/man5/bluetooth.hosts.5
Normal 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
|
62
share/man/man5/bluetooth.protocols.5
Normal file
62
share/man/man5/bluetooth.protocols.5
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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$
|
||||
*/
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
# $Id $
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= btsockstat \
|
||||
SUBDIR= \
|
||||
bthost \
|
||||
btsockstat \
|
||||
rfcomm_sppd
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
4
usr.bin/bluetooth/Makefile.inc
Normal file
4
usr.bin/bluetooth/Makefile.inc
Normal file
|
@ -0,0 +1,4 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.include "${.CURDIR}/../../Makefile.inc"
|
||||
|
12
usr.bin/bluetooth/bthost/Makefile
Normal file
12
usr.bin/bluetooth/bthost/Makefile
Normal 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>
|
111
usr.bin/bluetooth/bthost/bthost.1
Normal file
111
usr.bin/bluetooth/bthost/bthost.1
Normal 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
|
142
usr.bin/bluetooth/bthost/bthost.c
Normal file
142
usr.bin/bluetooth/bthost/bthost.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
266
usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c
Normal file
266
usr.bin/bluetooth/rfcomm_sppd/rfcomm_sdp.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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 ,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@ SUBDIR+=elf2exe \
|
|||
SUBDIR+=apm \
|
||||
apmd \
|
||||
asf \
|
||||
bluetooth \
|
||||
btxld \
|
||||
kgmon \
|
||||
kgzip \
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
4
usr.sbin/bluetooth/Makefile.inc
Normal file
4
usr.sbin/bluetooth/Makefile.inc
Normal file
|
@ -0,0 +1,4 @@
|
|||
# $FreeBSD$
|
||||
|
||||
.include "${.CURDIR}/../../Makefile.inc"
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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, }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
129
usr.sbin/bluetooth/hcsecd/hcsecd.conf.5
Normal file
129
usr.sbin/bluetooth/hcsecd/hcsecd.conf.5
Normal 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
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue