libhci update
Maksim Yevmenkin
maksim.yevmenkin at gmail.com
Mon Apr 20 17:53:27 UTC 2009
>> thanks for the feedback. i'm attaching revisited patch. please take a
>> look and let me know if this is something you happy with.
>
> (pls ignore typos & bad formatting, am on mobile device :)
>
> Bt_devrecv() should probably take void * for buffer? Also manpage suggests it
> will only receive hci events. Do you think its worth doing some validation of received
> data? (eg return EIO for truncated reads?)
i will change uint8_t * to void *, no problem. i also updated man page
and removed 'event' word :)
> Bt_devinquiry() should probably restore the filter after use? Also needs to ensure hci
> event packets are enabled?
its an implementation detail :) bt_devinqury() opens completely new
socket. in freebsd, filter is attached to the socket and is already
set to "sensible" defaults. so, all we need to do is to enable events
that we care about, i.e. inquiry result and inquiry complete. also
since bt_devinqury() is closing the socket after its done, there is no
need to restore original filter.
> Bt_devreq() needs to set/restore a filter too
well, maybe. bt_devreq() operates on already opened socket. the
assumption i'm making here is that application will set appropriate
filter before calling bt_devreq(). otherwise, application would have
to always set 'event' field to acceptable value (or zero). i could go
either way here. just need to document implemented behavior better.
> In bt_devreq structure event should be uint8_t? Also clen and rlen should be size_t
ok :) i was trying to get rid of hole with uint16_t event, but it does
not matter. also clen/rlen are size_t in bluetooth.h, its just i did
not update man page :)
> Do you think its worth to cook dev_class into a normalised host numeric value rather than 3 bytes ?
right, hmm, i guess we could turn dev_class into uint32_t in le16 byte
order (since everything else in bluetooth hci is in le16 order), but
maybe its too much? spec breaks out dev_class as 3 bytes array and
talks about bytes and bits within each byte. i'm kinda leaning towards
leaving it as is, because otherwise application would have to
translate byte/bit into uint32_t mask. it could be somewhat
convenient, i guess. again, no strong feeling about it. could go
either way.
> Probably need to specifically mention that the inquiry response to be released using free() in manpage?
it says so, i.e.
The
.Fa ii
parameter specifies where to place inquiry results.
On success, the function will return total number of inquiry results,
will allocate buffer to store all the inquiry results and
will return pointer to the allocated buffer in the
.Fa ii
parameter.
It is up to the caller of the function to dispose of the buffer.
> Something i thought about on the train yesterday but can't visualise on the small
> screen. For device inquiry did you consider using a callback method (as per devenum)
> in stead of returning the structure array? At least i recall my nokia would show the
> list building (but perhaps that was when it got the names) and this windows mobile
> device does show the raw list in progress (though stupidly just displays a list of
> 'unknown device' until it gets the names :)
yes, i thought about it. the only difference is that it would be not
so close to linux/bluez api. i guess, we could provide another
function?
i'm attaching revised diff for your review.
thanks,
max
-------------- next part --------------
Index: hci.c
===================================================================
--- hci.c (revision 191328)
+++ hci.c (working copy)
@@ -30,15 +30,445 @@
* $FreeBSD$
*/
+#include <assert.h>
#include <bluetooth.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+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);
int
+bt_devopen(char const *devname)
+{
+ struct sockaddr_hci ha;
+ bdaddr_t ba;
+ int s;
+
+ if (devname == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ memset(&ha, 0, sizeof(ha));
+ ha.hci_len = sizeof(ha);
+ ha.hci_family = AF_BLUETOOTH;
+
+ if (bt_aton(devname, &ba)) {
+ if (!bt_devname(ha.hci_node, &ba))
+ return (-1);
+ } else if (bt_dev2node(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);
+
+ if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
+ connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0) {
+ close(s);
+ return (-1);
+ }
+
+ return (s);
+}
+
+int
+bt_devclose(int s)
+{
+ return (close(s));
+}
+
+int
+bt_devsend(int s, uint16_t opcode, void *param, size_t plen)
+{
+ ng_hci_cmd_pkt_t h;
+ struct iovec iv[2];
+ int ivn;
+
+ if (plen < 0 || (plen > 0 && param == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ iv[0].iov_base = &h;
+ iv[0].iov_len = sizeof(h);
+ ivn = 1;
+
+ h.type = NG_HCI_CMD_PKT;
+ h.opcode = htole16(opcode);
+ if (plen > 0) {
+ h.length = plen;
+
+ iv[1].iov_base = param;
+ iv[1].iov_len = plen;
+ ivn = 2;
+ } else
+ h.length = 0;
+
+ while (writev(s, iv, ivn) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+bt_devrecv(int s, void *buf, size_t size, time_t to)
+{
+ fd_set rfd;
+ struct timeval tv;
+ int n;
+
+ if (buf == NULL || size <= 0 || to < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ FD_ZERO(&rfd);
+ FD_SET(s, &rfd);
+
+ tv.tv_sec = to;
+ tv.tv_usec = 0;
+
+ while ((n = select(s + 1, &rfd, NULL, NULL, &tv)) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ return (-1);
+ }
+
+ if (n == 0) {
+ errno = ETIMEDOUT;
+ return (-1);
+ }
+
+ assert(FD_ISSET(s, &rfd));
+
+ while ((n = read(s, buf, size)) < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+
+ return (-1);
+ }
+
+ return (n);
+}
+
+int
+bt_devreq(int s, struct bt_devreq *r, time_t to)
+{
+ uint8_t buf[320]; /* more than enough */
+ ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) buf;
+ ng_hci_command_compl_ep *cc = (ng_hci_command_compl_ep *)(e+1);
+ ng_hci_command_status_ep *cs = (ng_hci_command_status_ep*)(e+1);
+ time_t t_end;
+ uint16_t opcode;
+ int n;
+
+ if (s < 0 || r == NULL || to < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (r->rlen < 0 || (r->rlen > 0 && r->rparam == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ n = bt_devsend(s, r->opcode, r->cparam, r->clen);
+ if (n < 0)
+ return (-1);
+
+ opcode = htole16(r->opcode);
+ t_end = time(NULL) + to;
+
+ do {
+ to = t_end - time(NULL);
+ if (to < 0)
+ to = 0;
+
+ n = bt_devrecv(s, buf, sizeof(buf), to);
+ if (n < 0)
+ return (-1);
+
+ if (n < sizeof(*e)) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+
+ if (e->type != NG_HCI_EVENT_PKT) {
+ errno = EIO;
+ return (-1);
+ }
+
+ n -= sizeof(*e);
+
+ switch (e->event) {
+ case NG_HCI_EVENT_COMMAND_COMPL:
+ if (cc->opcode == opcode) {
+ n -= sizeof(*cc);
+
+ if (r->rlen >= n) {
+ r->rlen = n;
+ memcpy(r->rparam, cc + 1, r->rlen);
+ }
+
+ return (0);
+ }
+ break;
+
+ case NG_HCI_EVENT_COMMAND_STATUS:
+ if (cs->opcode == opcode) {
+ if (r->event != NG_HCI_EVENT_COMMAND_STATUS) {
+ if (cs->status != 0) {
+ errno = EIO;
+ return (-1);
+ }
+ } else {
+ if (r->rlen >= n) {
+ r->rlen = n;
+ memcpy(r->rparam, cs, r->rlen);
+ }
+
+ return (0);
+ }
+ }
+ break;
+
+ default:
+ if (e->event == r->event) {
+ if (r->rlen >= n) {
+ r->rlen = n;
+ memcpy(r->rparam, e + 1, r->rlen);
+ }
+
+ return (0);
+ }
+ break;
+ }
+ } while (to > 0);
+
+ errno = ETIMEDOUT;
+
+ return (-1);
+}
+
+int
+bt_devfilter(int s, struct bt_devfilter const *new, struct bt_devfilter *old)
+{
+ struct ng_btsocket_hci_raw_filter f;
+ socklen_t len;
+
+ if (new == NULL && old == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (old != NULL) {
+ len = sizeof(f);
+ if (getsockopt(s, SOL_HCI_RAW, SO_HCI_RAW_FILTER, &f, &len) < 0)
+ return (-1);
+
+ memset(old, 0, sizeof(*old));
+ memcpy(old->packet_mask, &f.packet_mask,
+ sizeof(old->packet_mask));
+ memcpy(old->event_mask, &f.event_mask,
+ sizeof(old->event_mask));
+ }
+
+ if (new != NULL) {
+ memset(&f, 0, sizeof(f));
+ memcpy(&f.packet_mask, new->packet_mask, sizeof(f.packet_mask));
+ memcpy(&f.event_mask, new->event_mask, sizeof(f.event_mask));
+
+ len = sizeof(f);
+ if (setsockopt(s, SOL_HCI_RAW, SO_HCI_RAW_FILTER, &f, len) < 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+bt_devfilter_pkt_set(struct bt_devfilter *filter, int type)
+{
+ bit_set(filter->packet_mask, type - 1);
+}
+
+void
+bt_devfilter_pkt_clr(struct bt_devfilter *filter, int type)
+{
+ bit_clear(filter->packet_mask, type - 1);
+}
+
+int
+bt_devfilter_pkt_tst(struct bt_devfilter const *filter, int type)
+{
+ return (bit_test(filter->packet_mask, type - 1));
+}
+
+void
+bt_devfilter_evt_set(struct bt_devfilter *filter, int event)
+{
+ bit_set(filter->event_mask, event - 1);
+}
+
+void
+bt_devfilter_evt_clr(struct bt_devfilter *filter, int event)
+{
+ bit_clear(filter->event_mask, event - 1);
+}
+
+int
+bt_devfilter_evt_tst(struct bt_devfilter const *filter, int event)
+{
+ return (bit_test(filter->event_mask, event - 1));
+}
+
+int
+bt_devinquiry(char const *devname, time_t length, int num_rsp,
+ struct bt_devinquiry **ii)
+{
+ uint8_t buf[320];
+ char _devname[HCI_DEVNAME_SIZE];
+ struct bt_devfilter f;
+ ng_hci_inquiry_cp *cp = (ng_hci_inquiry_cp *) buf;
+ ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) buf;
+ ng_hci_inquiry_result_ep *ep = (ng_hci_inquiry_result_ep *)(e+1);
+ ng_hci_inquiry_response *ir;
+ struct bt_devinquiry *i;
+ int s, n;
+ time_t to;
+
+ if (ii == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (devname == NULL) {
+ memset(_devname, 0, sizeof(_devname));
+ devname = _devname;
+
+ n = bt_devenum(bt_devany_cb, _devname);
+ if (n <= 0) {
+ if (n == 0)
+ *ii = NULL;
+
+ return (n);
+ }
+ }
+
+ s = bt_devopen(devname);
+ if (s < 0)
+ return (-1);
+
+ if (bt_devfilter(s, NULL, &f) < 0) {
+ bt_devclose(s);
+ return (-1);
+ }
+
+ bt_devfilter_evt_set(&f, NG_HCI_EVENT_INQUIRY_COMPL);
+ bt_devfilter_evt_set(&f, NG_HCI_EVENT_INQUIRY_RESULT);
+
+ if (bt_devfilter(s, &f, NULL) < 0) {
+ bt_devclose(s);
+ return (-1);
+ }
+
+ /* Always use GIAC LAP */
+ cp->lap[0] = 0x33;
+ cp->lap[1] = 0x8b;
+ cp->lap[2] = 0x9e;
+
+ /* Calculate inquire length in 1.28 second units */
+ to = (time_t) ((double) length / 1.28);
+ if (to <= 0)
+ cp->inquiry_length = 4; /* 5.12 seconds */
+ else if (to > 254)
+ cp->inquiry_length = 255; /* 326.40 seconds */
+ else
+ cp->inquiry_length = to + 1;
+
+ to = (time_t)((double) cp->inquiry_length * 1.28) + 1;
+
+ if (num_rsp <= 0 || num_rsp > 255)
+ num_rsp = 8;
+ cp->num_responses = (uint8_t) num_rsp;
+
+ i = *ii = calloc(num_rsp, sizeof(struct bt_devinquiry));
+ if (i == NULL) {
+ bt_devclose(s);
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ if (bt_devsend(s,
+ NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_INQUIRY),
+ cp, sizeof(*cp)) < 0) {
+ free(i);
+ bt_devclose(s);
+ return (-1);
+ }
+
+wait_for_more:
+
+ n = bt_devrecv(s, buf, sizeof(buf), to);
+ if (n < 0) {
+ free(i);
+ bt_devclose(s);
+ return (-1);
+ }
+
+ if (n < sizeof(ng_hci_event_pkt_t)) {
+ free(i);
+ bt_devclose(s);
+ errno = EIO;
+ return (-1);
+ }
+
+ switch (e->event) {
+ case NG_HCI_EVENT_INQUIRY_COMPL:
+ break;
+
+ case NG_HCI_EVENT_INQUIRY_RESULT:
+ ir = (ng_hci_inquiry_response *)(ep + 1);
+
+#undef MIN
+#define MIN(a, b) (((a) < (b))? (a) : (b))
+
+ for (n = 0; n < MIN(ep->num_responses, num_rsp); n ++) {
+ bdaddr_copy(&i->bdaddr, &ir->bdaddr);
+ i->pscan_rep_mode = ir->page_scan_rep_mode;
+ i->pscan_period_mode = ir->page_scan_period_mode;
+ memcpy(i->dev_class, ir->uclass, sizeof(i->dev_class));
+ i->clock_offset = le16toh(ir->clock_offset);
+
+ ir ++;
+ i ++;
+ num_rsp --;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ goto wait_for_more;
+ /* NOT REACHED */
+ }
+
+ bt_devclose(s);
+
+ return (i - *ii);
+}
+
+int
bt_devinfo(struct bt_devinfo *di)
{
union {
@@ -53,6 +483,7 @@
struct ng_btsocket_hci_raw_node_debug r8;
} rp;
struct sockaddr_hci ha;
+ socklen_t halen;
int s, rval;
if (di == NULL) {
@@ -60,27 +491,14 @@
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);
+ s = bt_devopen(di->devname);
if (s < 0)
return (-1);
rval = -1;
- if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
- connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0)
+ halen = sizeof(ha);
+ if (getsockname(s, (struct sockaddr *) &ha, &halen) < 0)
goto bad;
strlcpy(di->devname, ha.hci_node, sizeof(di->devname));
@@ -138,7 +556,7 @@
rval = 0;
bad:
- close(s);
+ bt_devclose(s);
return (rval);
}
@@ -205,6 +623,13 @@
return (count);
}
+static int
+bt_devany_cb(int s, struct bt_devinfo const *di, void *xdevname)
+{
+ strlcpy((char *) xdevname, di->devname, HCI_DEVNAME_SIZE);
+ return (1);
+}
+
static char *
bt_dev2node(char const *devname, char *nodename, int nnlen)
{
Index: bluetooth.3
===================================================================
--- bluetooth.3 (revision 191328)
+++ bluetooth.3 (working copy)
@@ -25,7 +25,7 @@
.\" $Id: bluetooth.3,v 1.5 2003/05/20 23:04:30 max Exp $
.\" $FreeBSD$
.\"
-.Dd February 13, 2009
+.Dd April 9, 2009
.Dt BLUETOOTH 3
.Os
.Sh NAME
@@ -41,6 +41,23 @@
.Nm bt_endprotoent ,
.Nm bt_aton ,
.Nm bt_ntoa ,
+.Nm bt_devaddr ,
+.Nm bt_devname ,
+.Nm bt_devinfo ,
+.Nm bt_devenum ,
+.Nm bt_devopen ,
+.Nm bt_devclose ,
+.Nm bt_devsend ,
+.Nm bt_devrecv ,
+.Nm bt_devreq ,
+.Nm bt_devfilter ,
+.Nm bt_devfilter_pkt_set ,
+.Nm bt_devfilter_pkt_clr ,
+.Nm bt_devfilter_pkt_tst ,
+.Nm bt_devfilter_evt_set ,
+.Nm bt_devfilter_evt_clr ,
+.Nm bt_devfilter_evt_tst ,
+.Nm bt_devinquiry ,
.Nm bdaddr_same ,
.Nm bdaddr_any ,
.Nm bdaddr_copy
@@ -84,6 +101,32 @@
.Ft int
.Fn bt_devenum "bt_devenum_cb_t *cb" "void *arg"
.Ft int
+.Fn bt_devopen "char const *devname"
+.Ft int
+.Fn bt_devclose "int s"
+.Ft int
+.Fn bt_devsend "int s" "uint16_t opcode" "void *param" "size_t plen"
+.Ft int
+.Fn bt_devrecv "int s" "void *buf" "size_t size" "time_t to"
+.Ft int
+.Fn bt_devreq "int s" "struct bt_devreq *r" "time_t to"
+.Ft int
+.Fn bt_devfilter "int s" "struct bt_devfilter const *new" "struct bt_devfilter *old"
+.Ft void
+.Fn bt_devfilter_pkt_set "struct bt_devfilter *filter" "int type"
+.Ft void
+.Fn bt_devfilter_pkt_clt "struct bt_devfilter *filter" "int type"
+.Ft int
+.Fn bt_devfilter_pkt_tst "struct bt_devfilter const *filter" "int type"
+.Ft void
+.Fn bt_devfilter_evt_set "struct bt_devfilter *filter" "int event"
+.Ft void
+.Fn bt_devfilter_evt_clt "struct bt_devfilter *filter" "int event"
+.Ft int
+.Fn bt_devfilter_evt_tst "struct bt_devfilter const *filter" "int event"
+.Ft int
+.Fn bt_devinquiry "char const *devname" "time_t length" "int num_rsp" "struct bt_devinquiry **ii"
+.Ft int
.Fn bdaddr_same "const bdaddr_t *a" "const bdaddr_t *b"
.Ft int
.Fn bdaddr_any "const bdaddr_t *a"
@@ -311,6 +354,229 @@
or -1 if an error occurred.
.Pp
The
+.Fn bt_devopen
+function opens Bluetooth device with the given
+.Fa devname
+and returns connected and bound
+.Dv HCI
+socket.
+The function returns -1 if an error has occurred.
+.Pp
+The
+.Fn bt_devclose
+closes passed
+.Dv HCI
+socket
+.Fa s ,
+previously obtained with
+.Xr bt_devopen 3 .
+.Pp
+The
+.Fn bt_devsend
+function sends Bluetooth
+.Dv HCI
+command with the given
+.Fa opcode
+to the provided socket
+.Fa s ,
+previously obtained with
+.Xr bt_devopen 3 .
+The
+.Fa opcode
+parameter is exppected to be in the host byte order.
+The
+.Fa param
+and
+.Fa plen
+parameters specify command parameters.
+The
+.Fn bt_devsend
+function does not modify
+.Dv HCI
+filter on the provided socket
+.Fa s .
+The function returns 0 on success,
+or -1 if an error occurred.
+.Pp
+The
+.Fn bt_devrecv
+function receives one Bluetooth
+.Dv HCI
+packet from the socket
+.Fa s ,
+previously obtained with
+.Xr bt_devopen 3 .
+The packet is placed into the provided buffer
+.Fa buf
+of size
+.Fa size .
+The
+.Fa to
+parameter specifies receive timeout in seconds.
+The
+.Fn bt_devrecv
+function does not modify
+.Dv HCI
+filter on the provided socket
+.Fa s .
+The function returns total number of bytes recevied,
+or -1 if an error occurred.
+.Pp
+The
+.Fn bt_devreq
+function makes Bluetooth
+.Dv HCI
+request to the socket
+.Fa s ,
+previously obtained with
+.Xr bt_devopen 3 .
+The function will send the specified command and will wait for the specified
+event,
+or timeout
+.Fa to
+seconds to occur.
+The
+.Vt bt_devreq
+structure is defined as follows
+.Bd -literal -offset indent
+struct bt_devreq
+{
+ uint16_t opcode;
+ uint8_t event;
+ void *cparam;
+ size_t clen;
+ void *rparam;
+ size_t rlen;
+};
+.Ed
+.Pp
+The
+.Fa opcode
+field specifies the command and is expected to be in the host byte order.
+The
+.Fa cparam
+and
+.Fa clen
+fields specify command parameters data and command parameters data size
+respectively.
+The
+.Fa event
+field specifies which Bluetooth
+.Dv HCI
+event ID the function should wait for.
+The
+.Fa rparam
+and
+.Fa rlen
+parameters specify buffer and buffer size respectively where return
+parameters should be placed.
+The
+.Fn bt_devreq
+function does not modify filter on the provided
+.Dv HCI
+socket
+.Fa s .
+The function returns 0 on success, or -1 if an error occurred.
+.Pp
+The
+.Fn bt_devfilter
+controls the local
+.Dv HCI
+filter associated with the socket
+.Fa s ,
+previously obtained with
+.Xr bt_devopen 3 .
+Filtering can be done on packet types, i.e.
+.Dv ACL ,
+.Dv SCO or
+.Dv HCI
+event packets, and, in addition, on
+.Dv HCI
+event IDs.
+Before applying
+.Fa new
+filter (if provided) the function will try to obtain current filter
+from the socket
+.Fa s
+and place it into the
+.Fa old
+parameter (if provided).
+The function returns 0 on success, or -1 if an error occurred.
+.Pp
+The
+.Fn bt_devfilter_pkt_set ,
+.Fn bt_devfilter_pkt_clr
+and
+.Fn bt_devfilter_pkt_tst
+functions can be used to modify and test
+.Dv HCI
+filter
+.Fa filter .
+The
+.Fa type
+parameter specifies
+.Dv HCI
+packet type.
+.Pp
+The
+.Fn bt_devfilter_evt_set ,
+.Fn bt_devfilter_evt_clr
+and
+.Fn bt_devfilter_evt_tst
+functions can be used to modify and test
+.Dv HCI
+event filter
+.Fa filter .
+The
+.Fa event
+parameter specifies
+.Dv HCI
+event ID.
+.Pp
+The
+.Fn bt_devinquiry
+function performs Bluetooth inquiry.
+The
+.Fa devname
+parameter specifies which local Bluetooth device should perform an inquiry.
+If not secified, i.e.
+.Dv NULL ,
+then first available device will be used.
+The
+.Fa length
+parameters specifies the total length of an inquiry in seconds.
+If not specified, i.e. 0, default value will be used.
+The
+.Fa num_rsp
+parameter specifies the number of responses that can be received before
+the inquiry is halted.
+If not specified, i.e. 0, default value will be used.
+The
+.Fa ii
+parameter specifies where to place inquiry results.
+On success, the function will return total number of inquiry results,
+will allocate buffer to store all the inquiry results and
+will return pointer to the allocated buffer in the
+.Fa ii
+parameter.
+It is up to the caller of the function to dispose of the buffer.
+The function returns -1 if an error has occurred.
+The
+.Vt bt_devinquiry
+structure is defined as follows
+.Bd -literal -offset indent
+struct bt_devinquiry {
+ bdaddr_t bdaddr;
+ uint8_t pscan_rep_mode;
+ uint8_t pscan_period_mode;
+ uint8_t dev_class[3];
+ uint16_t clock_offset;
+ int8_t rssi;
+ uint8_t data[240];
+};
+.Ed
+.Pp
+The
.Fn bdaddr_same ,
.Fn bdaddr_any
and
@@ -444,6 +710,6 @@
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin at yahoo.com
.Sh BUGS
-These functions use static data storage;
+Some of those functions use static data storage;
if the data is needed for future use, it should be
copied before any subsequent calls overwrite it.
Index: bluetooth.h
===================================================================
--- bluetooth.h (revision 191328)
+++ bluetooth.h (working copy)
@@ -39,6 +39,7 @@
#include <sys/endian.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include <errno.h>
#include <netdb.h>
@@ -46,6 +47,7 @@
#include <netgraph/bluetooth/include/ng_hci.h>
#include <netgraph/bluetooth/include/ng_l2cap.h>
#include <netgraph/bluetooth/include/ng_btsocket.h>
+#include <time.h>
__BEGIN_DECLS
@@ -129,8 +131,48 @@
uint8_t _padding[20]; /* leave space for future additions */
};
+struct bt_devreq
+{
+ uint16_t opcode;
+ uint8_t event;
+ void *cparam;
+ size_t clen;
+ void *rparam;
+ size_t rlen;
+};
+
+struct bt_devfilter {
+ bitstr_t bit_decl(packet_mask, 8);
+ bitstr_t bit_decl(event_mask, 256);
+};
+
+struct bt_devinquiry {
+ bdaddr_t bdaddr;
+ uint8_t pscan_rep_mode;
+ uint8_t pscan_period_mode;
+ uint8_t dev_class[3];
+ uint16_t clock_offset;
+ int8_t rssi;
+ uint8_t data[240];
+};
+
typedef int (bt_devenum_cb_t)(int, struct bt_devinfo const *, void *);
+int bt_devopen (char const *devname);
+int bt_devclose(int s);
+int bt_devsend (int s, uint16_t opcode, void *param, size_t plen);
+int bt_devrecv (int s, void *buf, size_t size, time_t to);
+int bt_devreq (int s, struct bt_devreq *r, time_t to);
+int bt_devfilter(int s, struct bt_devfilter const *new,
+ struct bt_devfilter *old);
+void bt_devfilter_pkt_set(struct bt_devfilter *filter, int type);
+void bt_devfilter_pkt_clr(struct bt_devfilter *filter, int type);
+int bt_devfilter_pkt_tst(struct bt_devfilter const *filter, int type);
+void bt_devfilter_evt_set(struct bt_devfilter *filter, int event);
+void bt_devfilter_evt_clr(struct bt_devfilter *filter, int event);
+int bt_devfilter_evt_tst(struct bt_devfilter const *filter, int event);
+int bt_devinquiry(char const *devname, time_t length, int num_rsp,
+ struct bt_devinquiry **ii);
int bt_devinfo (struct bt_devinfo *di);
int bt_devenum (bt_devenum_cb_t *cb, void *arg);
Index: Makefile
===================================================================
--- Makefile (revision 191328)
+++ Makefile (working copy)
@@ -33,6 +33,19 @@
MLINKS+= bluetooth.3 bt_devinfo.3
MLINKS+= bluetooth.3 bt_devenum.3
+MLINKS+= bluetooth.3 bt_devopen.3
+MLINKS+= bluetooth.3 bt_devclose.3
+MLINKS+= bluetooth.3 bt_devsend.3
+MLINKS+= bluetooth.3 bt_devreq.3
+MLINKS+= bluetooth.3 bt_devfilter.3
+MLINKS+= bluetooth.3 bt_devfilter_pkt_set.3
+MLINKS+= bluetooth.3 bt_devfilter_pkt_clr.3
+MLINKS+= bluetooth.3 bt_devfilter_pkt_tst.3
+MLINKS+= bluetooth.3 bt_devfilter_evt_set.3
+MLINKS+= bluetooth.3 bt_devfilter_evt_clr.3
+MLINKS+= bluetooth.3 bt_devfilter_evt_tst.3
+MLINKS+= bluetooth.3 bt_devinquiry.3
+
MLINKS+= bluetooth.3 bdaddr_same.3
MLINKS+= bluetooth.3 bdaddr_any.3
MLINKS+= bluetooth.3 bdaddr_copy.3
More information about the freebsd-bluetooth
mailing list