bluetooth(3): Add helper functions that performs Bluetooth Remote Name Request

procedure to obtain the user-friendly name of another Bluetooth unit.

Reviewed by:	emax, wblock (docs)
Differential Revision:	https://reviews.freebsd.org/D13456
This commit is contained in:
Vladimir Kondratyev 2018-04-30 10:24:50 +00:00
parent 515bb54c9f
commit 3ee5c55415
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=333110
3 changed files with 145 additions and 2 deletions

View file

@ -25,7 +25,7 @@
.\" $Id: bluetooth.3,v 1.5 2003/05/20 23:04:30 max Exp $
.\" $FreeBSD$
.\"
.Dd April 9, 2009
.Dd April 30, 2018
.Dt BLUETOOTH 3
.Os
.Sh NAME
@ -58,6 +58,8 @@
.Nm bt_devfilter_evt_clr ,
.Nm bt_devfilter_evt_tst ,
.Nm bt_devinquiry ,
.Nm bt_devremote_name ,
.Nm bt_devremote_name_gen ,
.Nm bdaddr_same ,
.Nm bdaddr_any ,
.Nm bdaddr_copy
@ -126,6 +128,11 @@
.Fn bt_devfilter_evt_tst "struct bt_devfilter const *filter" "uint8_t event"
.Ft int
.Fn bt_devinquiry "char const *devname" "time_t length" "int num_rsp" "struct bt_devinquiry **ii"
.Ft char *
.Fn bt_devremote_name "char const *devname" "const bdaddr_t *remote" \
"time_t to" "uint16_t clk_off" "uint8_t ps_rep_mode" "uint8_t ps_mode"
.Ft char *
.Fn bt_devremote_name_gen "char const *devname" "const bdaddr_t *remote"
.Ft int
.Fn bdaddr_same "const bdaddr_t *a" "const bdaddr_t *b"
.Ft int
@ -589,8 +596,54 @@ struct bt_devinquiry {
.Ed
.Pp
The
.Fn bt_devremote_name
function performs Bluetooth Remote Name Request procedure to obtain the
user-friendly name of another Bluetooth unit.
The
.Fa devname
parameter specifies which local Bluetooth device should perform the request.
If not specified
.Dv ( NULL ) ,
the first available device is used.
The
.Fa remote
parameter specifies the Bluetooth BD_ADDR of the remote device to query.
The
.Fa to
parameter specifies response timeout in seconds.
If not specified (0), the default value is taken from the
net.bluetooth.hci.command_timeout
.Xr sysctl 8
value.
The
.Fa clk_off ,
.Fa ps_rep_mode ,
and
.Fa ps_mode
parameters specify Clock_Offset, Page_Scan_Repetition_Mode, and Page_Scan_Mode
fields of HCI_Remote_Name_Request respectively.
On success, the function returns a pointer to dynamically allocated
NUL-terminated string or
.Dv NULL
if an error occurred.
It is up to the caller to release returned string using
.Xr free 3 .
.Pp
The
.Fn bt_devremote_name_gen
function is a shortcut to
.Fn bt_devremote_name
that passes generic defaults for
.Fa to ,
.Fa clk_off ,
.Fa ps_rep_mode ,
and
.Fa ps_mode
parameters.
.Pp
The
.Fn bdaddr_same ,
.Fn bdaddr_any
.Fn bdaddr_any ,
and
.Fn bdaddr_copy
are handy shorthand Bluetooth address utility functions.

View file

@ -182,9 +182,19 @@ void bt_devfilter_evt_clr(struct bt_devfilter *filter, uint8_t event);
int bt_devfilter_evt_tst(struct bt_devfilter const *filter, uint8_t event);
int bt_devinquiry(char const *devname, time_t length, int num_rsp,
struct bt_devinquiry **ii);
char * bt_devremote_name(char const *devname, const bdaddr_t *remote,
time_t to, uint16_t clk_off,
uint8_t ps_rep_mode, uint8_t ps_mode);
int bt_devinfo (struct bt_devinfo *di);
int bt_devenum (bt_devenum_cb_t cb, void *arg);
static __inline char *
bt_devremote_name_gen(char const *devname, const bdaddr_t *remote)
{
return (bt_devremote_name(devname, remote, 0, 0x0000,
NG_HCI_SCAN_REP_MODE0, NG_HCI_MANDATORY_PAGE_SCAN_MODE));
}
/*
* bdaddr utility functions (from NetBSD)
*/

View file

@ -32,6 +32,9 @@
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <assert.h>
#define L2CAP_SOCKET_CHECKED
#include <bluetooth.h>
@ -39,6 +42,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#undef MIN
@ -46,6 +50,7 @@
static int bt_devany_cb(int s, struct bt_devinfo const *di, void *xdevname);
static char * bt_dev2node (char const *devname, char *nodename, int nnlen);
static time_t bt_get_default_hci_command_timeout(void);
int
bt_devopen(char const *devname)
@ -534,6 +539,63 @@ bt_devinquiry(char const *devname, time_t length, int num_rsp,
return (i - *ii);
}
char *
bt_devremote_name(char const *devname, const bdaddr_t *remote, time_t to,
uint16_t clk_off, uint8_t ps_rep_mode, uint8_t ps_mode)
{
char _devname[HCI_DEVNAME_SIZE];
struct bt_devreq r;
ng_hci_remote_name_req_cp cp;
ng_hci_remote_name_req_compl_ep ep;
int s;
char *remote_name = NULL;
if (remote == NULL || to < 0) {
errno = EINVAL;
goto out;
}
if (to == 0) {
to = bt_get_default_hci_command_timeout();
if (to < 0)
goto out;
}
to++;
if (devname == NULL) {
memset(_devname, 0, sizeof(_devname));
devname = _devname;
if (bt_devenum(bt_devany_cb, _devname) <= 0)
goto out;
}
memset(&r, 0, sizeof(r));
memset(&cp, 0, sizeof(cp));
memset(&ep, 0, sizeof(ep));
cp.clock_offset = htole16(clk_off);
cp.page_scan_rep_mode = ps_rep_mode;
cp.page_scan_mode = ps_mode;
bdaddr_copy(&cp.bdaddr, remote);
r.opcode = NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
NG_HCI_OCF_REMOTE_NAME_REQ);
r.event = NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL;
r.cparam = &cp;
r.clen = sizeof(cp);
r.rparam = &ep;
r.rlen = sizeof(ep);
s = bt_devopen(devname);
if (s < 0)
goto out;
if (bt_devreq(s, &r, to) == 0 || ep.status == 0x00)
remote_name = strndup((const char *)&ep.name, sizeof(ep.name));
bt_devclose(s);
out:
return (remote_name);
}
int
bt_devinfo(struct bt_devinfo *di)
{
@ -735,3 +797,21 @@ bt_dev2node(char const *devname, char *nodename, int nnlen)
return (NULL);
}
static time_t
bt_get_default_hci_command_timeout(void)
{
int to;
size_t to_size = sizeof(to);
if (sysctlbyname("net.bluetooth.hci.command_timeout",
&to, &to_size, NULL, 0) < 0)
return (-1);
/* Should not happen */
if (to <= 0) {
errno = ERANGE;
return (-1);
}
return ((time_t)to);
}