Add Bluetooth compatibility shims. Inspired by Linux BlueZ and NetBSD.
Discussed with: Iain Hibbert plunky -at- rya-online -dot- net of NetBSD MFC after: 1 month
This commit is contained in:
parent
280ce52aab
commit
791c327405
@ -9,7 +9,7 @@ CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys
|
||||
|
||||
SHLIB_MAJOR= 3
|
||||
|
||||
SRCS= bluetooth.c
|
||||
SRCS= bluetooth.c dev.c hci.c
|
||||
INCS= bluetooth.h
|
||||
|
||||
MLINKS+= bluetooth.3 bt_gethostbyname.3
|
||||
@ -27,6 +27,12 @@ MLINKS+= bluetooth.3 bt_endprotoent.3
|
||||
MLINKS+= bluetooth.3 bt_ntoa.3
|
||||
MLINKS+= bluetooth.3 bt_aton.3
|
||||
|
||||
MLINKS+= bluetooth.3 bt_devaddr.3
|
||||
MLINKS+= bluetooth.3 bt_devname.3
|
||||
|
||||
MLINKS+= bluetooth.3 bt_devinfo.3
|
||||
MLINKS+= bluetooth.3 bt_devenum.3
|
||||
|
||||
MLINKS+= bluetooth.3 bdaddr_same.3
|
||||
MLINKS+= bluetooth.3 bdaddr_any.3
|
||||
MLINKS+= bluetooth.3 bdaddr_copy.3
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" Copyright (c) 2003-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -25,7 +25,7 @@
|
||||
.\" $Id: bluetooth.3,v 1.5 2003/05/20 23:04:30 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 13, 2008
|
||||
.Dd February 13, 2009
|
||||
.Dt BLUETOOTH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -74,6 +74,16 @@
|
||||
.Ft const char *
|
||||
.Fn bt_ntoa "const bdaddr_t *ba" "char *str"
|
||||
.Ft int
|
||||
.Fn bt_devaddr "const char *devname" "bdaddr_t *addr"
|
||||
.Ft int
|
||||
.Fn bt_devname "char *devname" "const bdaddr_t *addr"
|
||||
.Ft int
|
||||
.Fn (bt_devenum_cb_t) "int s" "struct bt_devinfo const *di" "void *arg"
|
||||
.Ft int
|
||||
.Fn bt_devinfo "struct bt_devinfo *di"
|
||||
.Ft int
|
||||
.Fn bt_devenum "bt_devenum_cb_t *cb" "void *arg"
|
||||
.Ft int
|
||||
.Fn bdaddr_same "const bdaddr_t *a" "const bdaddr_t *b"
|
||||
.Ft int
|
||||
.Fn bdaddr_any "const bdaddr_t *a"
|
||||
@ -197,6 +207,110 @@ 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.
|
||||
.Pp
|
||||
The
|
||||
.Fn bt_devaddr
|
||||
function interprets the specified
|
||||
.Fa devname
|
||||
string as the address or device name of a Bluetooth device on the local system,
|
||||
and places the device address in the provided
|
||||
.Fa bdaddr ,
|
||||
if any.
|
||||
The function returns 1 if the string was successfully interpreted,
|
||||
or 0 if the string did not match any local device.
|
||||
The
|
||||
.Fn bt_devname
|
||||
function takes a Bluetooth device address and copies the local device
|
||||
name associated with that address into the buffer provided,
|
||||
if any.
|
||||
Caller must ensure that provided buffer is at least
|
||||
.Dv HCI_DEVNAME_SIZE
|
||||
characters in size.
|
||||
The function returns 1 when the device was found,
|
||||
otherwise 0.
|
||||
.Pp
|
||||
The
|
||||
.Fn bt_devinfo
|
||||
function populates prodivded
|
||||
.Vt bt_devinfo
|
||||
structure with the information about given Bluetooth device.
|
||||
The caller is expected to pass Bluetooth device name in the
|
||||
.Fa devname
|
||||
field of the passed
|
||||
.Vt bt_devinfo
|
||||
structure.
|
||||
The function returns 0 when successful,
|
||||
otherwise -1.
|
||||
The
|
||||
.Vt bt_devinfo
|
||||
structure is defined as follows
|
||||
.Bd -literal -offset indent
|
||||
struct bt_devinfo
|
||||
{
|
||||
char devname[HCI_DEVNAME_SIZE];
|
||||
|
||||
uint32_t state;
|
||||
|
||||
bdaddr_t bdaddr;
|
||||
uint16_t _reserved0;
|
||||
|
||||
uint8_t features[HCI_DEVFEATURES_SIZE];
|
||||
|
||||
/* buffer info */
|
||||
uint16_t _reserved1;
|
||||
uint16_t cmd_free;
|
||||
uint16_t sco_size;
|
||||
uint16_t sco_pkts;
|
||||
uint16_t sco_free;
|
||||
uint16_t acl_size;
|
||||
uint16_t acl_pkts;
|
||||
uint16_t acl_free;
|
||||
|
||||
/* stats */
|
||||
uint32_t cmd_sent;
|
||||
uint32_t evnt_recv;
|
||||
uint32_t acl_recv;
|
||||
uint32_t acl_sent;
|
||||
uint32_t sco_recv;
|
||||
uint32_t sco_sent;
|
||||
uint32_t bytes_recv;
|
||||
uint32_t bytes_sent;
|
||||
|
||||
/* misc/specific */
|
||||
uint16_t link_policy_info;
|
||||
uint16_t packet_type_info;
|
||||
uint16_t role_switch_info;
|
||||
uint16_t debug;
|
||||
|
||||
uint8_t _padding[20];
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Fn bt_devenum
|
||||
function enumerates Bluetooth devices present in the system.
|
||||
For every device found,
|
||||
the function will call provided
|
||||
.Fa cb
|
||||
callback function which should be of
|
||||
.Vt bt_devenum_cb_t
|
||||
type.
|
||||
The callback function is passed a
|
||||
.Dv HCI
|
||||
socket
|
||||
.Fa s ,
|
||||
fully populated
|
||||
.Vt bt_devinfo
|
||||
structure
|
||||
.Fa di
|
||||
and
|
||||
.Fa arg
|
||||
argument provided to the
|
||||
.Fn bt_devenum .
|
||||
The callback function can stop enumeration by returning a value
|
||||
that is greater than zero.
|
||||
The function returns number of successfully enumerated devices,
|
||||
or -1 if an error occurred.
|
||||
.Pp
|
||||
The
|
||||
.Fn bdaddr_same ,
|
||||
.Fn bdaddr_any
|
||||
and
|
||||
@ -287,7 +401,8 @@ on EOF or error.
|
||||
.Xr getprotobynumber 3 ,
|
||||
.Xr herror 3 ,
|
||||
.Xr inet_aton 3 ,
|
||||
.Xr inet_ntoa 3
|
||||
.Xr inet_ntoa 3 ,
|
||||
.Xr ng_hci 4
|
||||
.Sh CAVEAT
|
||||
The
|
||||
.Fn bt_gethostent
|
||||
@ -312,6 +427,20 @@ The
|
||||
function opens and/or rewinds the
|
||||
.Pa /etc/bluetooth/protocols
|
||||
file.
|
||||
.Pp
|
||||
The
|
||||
.Fn bt_devenum
|
||||
function enumerates up to
|
||||
.Dv HCI_DEVMAX
|
||||
Bluetooth devices.
|
||||
During enumeration the
|
||||
.Fn bt_devenum
|
||||
function uses the same
|
||||
.Dv HCI
|
||||
socket.
|
||||
The function guarantees that the socket,
|
||||
passed to the callback function,
|
||||
will be bound and connected to the Bluetooth device being enumerated.
|
||||
.Sh AUTHORS
|
||||
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
|
||||
.Sh BUGS
|
||||
|
@ -1,7 +1,9 @@
|
||||
/*
|
||||
* bluetooth.c
|
||||
*
|
||||
* Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,7 +1,9 @@
|
||||
/*
|
||||
* bluetooth.h
|
||||
*
|
||||
* Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -35,9 +37,12 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <netgraph/ng_message.h>
|
||||
#include <netgraph/bluetooth/include/ng_hci.h>
|
||||
#include <netgraph/bluetooth/include/ng_l2cap.h>
|
||||
#include <netgraph/bluetooth/include/ng_btsocket.h>
|
||||
@ -72,6 +77,63 @@ void bt_endprotoent (void);
|
||||
char const * bt_ntoa (bdaddr_t const *ba, char *str);
|
||||
int bt_aton (char const *str, bdaddr_t *ba);
|
||||
|
||||
/* bt_devXXXX() functions (inspired by NetBSD) */
|
||||
int bt_devaddr (char const *devname, bdaddr_t *addr);
|
||||
int bt_devname (char *devname, bdaddr_t const *addr);
|
||||
|
||||
/*
|
||||
* Bluetooth HCI functions
|
||||
*/
|
||||
|
||||
#define HCI_DEVMAX 32 /* arbitrary */
|
||||
#define HCI_DEVNAME_SIZE NG_NODESIZ
|
||||
#define HCI_DEVFEATURES_SIZE NG_HCI_FEATURES_SIZE
|
||||
|
||||
struct bt_devinfo
|
||||
{
|
||||
char devname[HCI_DEVNAME_SIZE];
|
||||
|
||||
uint32_t state; /* device/implementation specific */
|
||||
|
||||
bdaddr_t bdaddr;
|
||||
uint16_t _reserved0;
|
||||
|
||||
uint8_t features[HCI_DEVFEATURES_SIZE];
|
||||
|
||||
/* buffer info */
|
||||
uint16_t _reserved1;
|
||||
uint16_t cmd_free;
|
||||
uint16_t sco_size;
|
||||
uint16_t sco_pkts;
|
||||
uint16_t sco_free;
|
||||
uint16_t acl_size;
|
||||
uint16_t acl_pkts;
|
||||
uint16_t acl_free;
|
||||
|
||||
/* stats */
|
||||
uint32_t cmd_sent;
|
||||
uint32_t evnt_recv;
|
||||
uint32_t acl_recv;
|
||||
uint32_t acl_sent;
|
||||
uint32_t sco_recv;
|
||||
uint32_t sco_sent;
|
||||
uint32_t bytes_recv;
|
||||
uint32_t bytes_sent;
|
||||
|
||||
/* misc/specific */
|
||||
uint16_t link_policy_info;
|
||||
uint16_t packet_type_info;
|
||||
uint16_t role_switch_info;
|
||||
uint16_t debug;
|
||||
|
||||
uint8_t _padding[20]; /* leave space for future additions */
|
||||
};
|
||||
|
||||
typedef int (bt_devenum_cb_t)(int, struct bt_devinfo const *, void *);
|
||||
|
||||
int bt_devinfo (struct bt_devinfo *di);
|
||||
int bt_devenum (bt_devenum_cb_t *cb, void *arg);
|
||||
|
||||
/*
|
||||
* bdaddr utility functions (from NetBSD)
|
||||
*/
|
||||
|
95
lib/libbluetooth/dev.c
Normal file
95
lib/libbluetooth/dev.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* dev.c
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <bluetooth.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct bt_devaddr_match_arg
|
||||
{
|
||||
char devname[HCI_DEVNAME_SIZE];
|
||||
bdaddr_t const *bdaddr;
|
||||
};
|
||||
|
||||
static bt_devenum_cb_t bt_devaddr_match;
|
||||
|
||||
int
|
||||
bt_devaddr(char const *devname, bdaddr_t *addr)
|
||||
{
|
||||
struct bt_devinfo di;
|
||||
|
||||
strlcpy(di.devname, devname, sizeof(di.devname));
|
||||
|
||||
if (bt_devinfo(&di) < 0)
|
||||
return (0);
|
||||
|
||||
if (addr != NULL)
|
||||
bdaddr_copy(addr, &di.bdaddr);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
bt_devname(char *devname, bdaddr_t const *addr)
|
||||
{
|
||||
struct bt_devaddr_match_arg arg;
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
arg.bdaddr = addr;
|
||||
|
||||
if (bt_devenum(&bt_devaddr_match, &arg) < 0)
|
||||
return (0);
|
||||
|
||||
if (arg.devname[0] == '\0') {
|
||||
errno = ENXIO;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (devname != NULL)
|
||||
strlcpy(devname, arg.devname, HCI_DEVNAME_SIZE);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
bt_devaddr_match(int s, struct bt_devinfo const *di, void *arg)
|
||||
{
|
||||
struct bt_devaddr_match_arg *m = (struct bt_devaddr_match_arg *)arg;
|
||||
|
||||
if (!bdaddr_same(&di->bdaddr, m->bdaddr))
|
||||
return (0);
|
||||
|
||||
strlcpy(m->devname, di->devname, sizeof(m->devname));
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
246
lib/libbluetooth/hci.c
Normal file
246
lib/libbluetooth/hci.c
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* hci.c
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <bluetooth.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char * bt_dev2node (char const *devname, char *nodename, int nnlen);
|
||||
|
||||
int
|
||||
bt_devinfo(struct bt_devinfo *di)
|
||||
{
|
||||
union {
|
||||
struct ng_btsocket_hci_raw_node_state r0;
|
||||
struct ng_btsocket_hci_raw_node_bdaddr r1;
|
||||
struct ng_btsocket_hci_raw_node_features r2;
|
||||
struct ng_btsocket_hci_raw_node_buffer r3;
|
||||
struct ng_btsocket_hci_raw_node_stat r4;
|
||||
struct ng_btsocket_hci_raw_node_link_policy_mask r5;
|
||||
struct ng_btsocket_hci_raw_node_packet_mask r6;
|
||||
struct ng_btsocket_hci_raw_node_role_switch r7;
|
||||
struct ng_btsocket_hci_raw_node_debug r8;
|
||||
} rp;
|
||||
struct sockaddr_hci ha;
|
||||
int s, rval;
|
||||
|
||||
if (di == NULL) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset(&ha, 0, sizeof(ha));
|
||||
ha.hci_len = sizeof(ha);
|
||||
ha.hci_family = AF_BLUETOOTH;
|
||||
|
||||
if (bt_aton(di->devname, &rp.r1.bdaddr)) {
|
||||
if (!bt_devname(ha.hci_node, &rp.r1.bdaddr))
|
||||
return (-1);
|
||||
} else if (bt_dev2node(di->devname, ha.hci_node,
|
||||
sizeof(ha.hci_node)) == NULL) {
|
||||
errno = ENXIO;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
|
||||
if (s < 0)
|
||||
return (-1);
|
||||
|
||||
rval = -1;
|
||||
|
||||
if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
|
||||
connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0)
|
||||
goto bad;
|
||||
strlcpy(di->devname, ha.hci_node, sizeof(di->devname));
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STATE, &rp.r0, sizeof(rp.r0)) < 0)
|
||||
goto bad;
|
||||
di->state = rp.r0.state;
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &rp.r1, sizeof(rp.r1)) < 0)
|
||||
goto bad;
|
||||
bdaddr_copy(&di->bdaddr, &rp.r1.bdaddr);
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &rp.r2, sizeof(rp.r2)) < 0)
|
||||
goto bad;
|
||||
memcpy(di->features, rp.r2.features, sizeof(di->features));
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &rp.r3, sizeof(rp.r3)) < 0)
|
||||
goto bad;
|
||||
di->cmd_free = rp.r3.buffer.cmd_free;
|
||||
di->sco_size = rp.r3.buffer.sco_size;
|
||||
di->sco_pkts = rp.r3.buffer.sco_pkts;
|
||||
di->sco_free = rp.r3.buffer.sco_free;
|
||||
di->acl_size = rp.r3.buffer.acl_size;
|
||||
di->acl_pkts = rp.r3.buffer.acl_pkts;
|
||||
di->acl_free = rp.r3.buffer.acl_free;
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &rp.r4, sizeof(rp.r4)) < 0)
|
||||
goto bad;
|
||||
di->cmd_sent = rp.r4.stat.cmd_sent;
|
||||
di->evnt_recv = rp.r4.stat.evnt_recv;
|
||||
di->acl_recv = rp.r4.stat.acl_recv;
|
||||
di->acl_sent = rp.r4.stat.acl_sent;
|
||||
di->sco_recv = rp.r4.stat.sco_recv;
|
||||
di->sco_sent = rp.r4.stat.sco_sent;
|
||||
di->bytes_recv = rp.r4.stat.bytes_recv;
|
||||
di->bytes_sent = rp.r4.stat.bytes_sent;
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK,
|
||||
&rp.r5, sizeof(rp.r5)) < 0)
|
||||
goto bad;
|
||||
di->link_policy_info = rp.r5.policy_mask;
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK,
|
||||
&rp.r6, sizeof(rp.r6)) < 0)
|
||||
goto bad;
|
||||
di->packet_type_info = rp.r6.packet_mask;
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH,
|
||||
&rp.r7, sizeof(rp.r7)) < 0)
|
||||
goto bad;
|
||||
di->role_switch_info = rp.r7.role_switch;
|
||||
|
||||
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &rp.r8, sizeof(rp.r8)) < 0)
|
||||
goto bad;
|
||||
di->debug = rp.r8.debug;
|
||||
|
||||
rval = 0;
|
||||
bad:
|
||||
close(s);
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
int
|
||||
bt_devenum(bt_devenum_cb_t cb, void *arg)
|
||||
{
|
||||
struct ng_btsocket_hci_raw_node_list_names rp;
|
||||
struct bt_devinfo di;
|
||||
struct sockaddr_hci ha;
|
||||
int s, i, count;
|
||||
|
||||
rp.num_names = HCI_DEVMAX;
|
||||
rp.names = (struct nodeinfo *) calloc(rp.num_names,
|
||||
sizeof(struct nodeinfo));
|
||||
if (rp.names == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset(&ha, 0, sizeof(ha));
|
||||
ha.hci_len = sizeof(ha);
|
||||
ha.hci_family = AF_BLUETOOTH;
|
||||
ha.hci_node[0] = 'x';
|
||||
|
||||
s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
|
||||
if (s < 0) {
|
||||
free(rp.names);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
|
||||
connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
|
||||
ioctl(s, SIOC_HCI_RAW_NODE_LIST_NAMES, &rp, sizeof(rp)) < 0) {
|
||||
close(s);
|
||||
free(rp.names);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (count = 0, i = 0; i < rp.num_names; i ++) {
|
||||
strlcpy(di.devname, rp.names[i].name, sizeof(di.devname));
|
||||
if (bt_devinfo(&di) < 0)
|
||||
continue;
|
||||
|
||||
count ++;
|
||||
|
||||
if (cb == NULL)
|
||||
continue;
|
||||
|
||||
strlcpy(ha.hci_node, rp.names[i].name, sizeof(ha.hci_node));
|
||||
if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
|
||||
connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0)
|
||||
continue;
|
||||
|
||||
if ((*cb)(s, &di, arg) > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
close (s);
|
||||
free(rp.names);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
static char *
|
||||
bt_dev2node(char const *devname, char *nodename, int nnlen)
|
||||
{
|
||||
static char const * bt_dev_prefix[] = {
|
||||
"btccc", /* 3Com Bluetooth PC-CARD */
|
||||
"h4", /* UART/serial Bluetooth devices */
|
||||
"ubt", /* Bluetooth USB devices */
|
||||
NULL /* should be last */
|
||||
};
|
||||
|
||||
static char _nodename[HCI_DEVNAME_SIZE];
|
||||
char const **p;
|
||||
char *ep;
|
||||
int plen, unit;
|
||||
|
||||
if (nodename == NULL) {
|
||||
nodename = _nodename;
|
||||
nnlen = HCI_DEVNAME_SIZE;
|
||||
}
|
||||
|
||||
for (p = bt_dev_prefix; *p != NULL; p ++) {
|
||||
plen = strlen(*p);
|
||||
if (strncmp(devname, *p, plen) != 0)
|
||||
continue;
|
||||
|
||||
unit = strtoul(devname + plen, &ep, 10);
|
||||
if (*ep != '\0' &&
|
||||
strcmp(ep, "hci") != 0 &&
|
||||
strcmp(ep, "l2cap") != 0)
|
||||
return (NULL); /* can't make sense of device name */
|
||||
|
||||
snprintf(nodename, nnlen, "%s%uhci", *p, unit);
|
||||
|
||||
return (nodename);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user