bt_dev API

Iain Hibbert plunky at rya-online.net
Wed Jun 10 08:17:09 UTC 2009


On Tue, 9 Jun 2009, Maksim Yevmenkin wrote:

> > Are you still with us?  After some delay (and a tan from last week :) I am
> > about ready with the bt_dev stuff for NetBSD now (latest dump at
> > www.netbsd.org:~plunky/btdev-20090609.tar.gz)
>
> sorry. i'm completely swamped at $real_job :(

sounds like hair loss is imminent, heh :)

> > - bt_devopen(name, flags) flags argument?
>
> i guess its fine, but i still kinda like setopt() call.

my reasoning to set it in devopen is that if you open -> bind -> setopt
then there is a race condition where you could get packets already in the
buffer where you don't get the control messages.

anyway I attach a FreeBSD patch for you that implements some changes -
note I haven't compile tested it, and I don't know if you need to bump
library version but it looks about right

 - spelling fixes in manpage
 - add flags argument to bt_devopen()
 - bt_devopen(NULL, 0) will open for any device
 - change return value of bt_devsend()
 - add name argument to bt_devinfo()

> > - struct bt_devinfo state field needs to be genericalised,
>
> i have not look at the source. i'm guessing its probably fine too :)

I'm still thinking about how best to do that, will look at the linux
sources later to see what might fit.  I'm thinking that either

a) bt_devinfo structure should be completely MI and have the caller get OS
specific information on their own time

b) incompletely specify the bt_devinfo structure in the manpage (as in
"the bt_devinfo structure contains at least the following fields:") so
that callers are not tempted to rely on OS specific data.

regards,
iain
-------------- next part --------------
Index: bluetooth.3
===================================================================
RCS file: /home/ncvs/src/lib/libbluetooth/bluetooth.3,v
retrieving revision 1.10
diff -u -r1.10 bluetooth.3
--- bluetooth.3	22 Apr 2009 15:50:03 -0000	1.10
+++ bluetooth.3	10 Jun 2009 08:01:18 -0000
@@ -97,14 +97,14 @@
 .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"
+.Fn bt_devinfo "char const *devname" "struct bt_devinfo *di"
 .Ft int
 .Fn bt_devenum "bt_devenum_cb_t *cb" "void *arg"
 .Ft int
-.Fn bt_devopen "char const *devname"
+.Fn bt_devopen "char const *devname" "int flags"
 .Ft int
 .Fn bt_devclose "int s"
-.Ft int
+.Ft ssize_t
 .Fn bt_devsend "int s" "uint16_t opcode" "void *param" "size_t plen"
 .Ft ssize_t
 .Fn bt_devrecv "int s" "void *buf" "size_t size" "time_t to"
@@ -115,13 +115,13 @@
 .Ft void
 .Fn bt_devfilter_pkt_set "struct bt_devfilter *filter" "uint8_t type"
 .Ft void
-.Fn bt_devfilter_pkt_clt "struct bt_devfilter *filter" "uint8_t type"
+.Fn bt_devfilter_pkt_clr "struct bt_devfilter *filter" "uint8_t type"
 .Ft int
 .Fn bt_devfilter_pkt_tst "struct bt_devfilter const *filter" "uint8_t type"
 .Ft void
 .Fn bt_devfilter_evt_set "struct bt_devfilter *filter" "uint8_t event"
 .Ft void
-.Fn bt_devfilter_evt_clt "struct bt_devfilter *filter" "uint8_t event"
+.Fn bt_devfilter_evt_clr "struct bt_devfilter *filter" "uint8_t event"
 .Ft int
 .Fn bt_devfilter_evt_tst "struct bt_devfilter const *filter" "uint8_t event"
 .Ft int
@@ -272,14 +272,9 @@
 .Pp
 The
 .Fn bt_devinfo
-function populates prodivded
+function populates provided
 .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
@@ -360,6 +355,20 @@
 and returns a connected and bound
 .Dv HCI
 socket handle.
+If the
+.Fa devname
+is
+.Dv NULL
+the socket will receive messages from all devices.
+Any combination of the following
+.Fa flags
+may be used to pre-set the socket options:
+.Bl -tag -width ".Dv BTOPT_DIRECTION"
+.It Dv BTOPT_DIRECTION
+Enable control messages on each packet indicating the direction of travel.
+.It Dv BTOPT_TIMESTAMP
+Enable control messages providing packet timestamps.
+.El
 The function returns -1 if an error has occurred.
 .Pp
 The
@@ -383,7 +392,7 @@
 .Xr bt_devopen 3 .
 The
 .Fa opcode
-parameter is exppected to be in the host byte order.
+parameter is expected to be in the host byte order.
 The
 .Fa param
 and
@@ -395,7 +404,7 @@
 .Dv HCI
 filter on the provided socket
 .Fa s .
-The function returns 0 on success,
+The function returns the number of characters successfully written,
 or -1 if an error occurred.
 .Pp
 The
Index: bluetooth.h
===================================================================
RCS file: /home/ncvs/src/lib/libbluetooth/bluetooth.h,v
retrieving revision 1.5
diff -u -r1.5 bluetooth.h
--- bluetooth.h	22 Apr 2009 15:50:03 -0000	1.5
+++ bluetooth.h	10 Jun 2009 08:01:18 -0000
@@ -158,9 +158,9 @@
 
 typedef int	(bt_devenum_cb_t)(int, struct bt_devinfo const *, void *);
 
-int		bt_devopen (char const *devname);
+int		bt_devopen (char const *devname, int flags);
 int		bt_devclose(int s);
-int		bt_devsend (int s, uint16_t opcode, void *param, size_t plen);
+ssize_t		bt_devsend (int s, uint16_t opcode, void *param, size_t plen);
 ssize_t		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,
@@ -173,10 +173,17 @@
 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);
-int		bt_devinfo (struct bt_devinfo *di);
+int		bt_devinfo (char const *devname, struct bt_devinfo *di);
 int		bt_devenum (bt_devenum_cb_t *cb, void *arg);
 
 /*
+ * bt_devopen flags
+ */
+
+#define	BTOPT_DIRECTION		(1 << 0)
+#define	BTOPT_TIMESTAMP		(1 << 1)
+
+/*
  * bdaddr utility functions (from NetBSD)
  */
 
Index: hci.c
===================================================================
RCS file: /home/ncvs/src/lib/libbluetooth/hci.c,v
retrieving revision 1.3
diff -u -r1.3 hci.c
--- hci.c	14 May 2009 17:10:19 -0000	1.3
+++ hci.c	10 Jun 2009 08:01:18 -0000
@@ -45,40 +45,53 @@
 static char * bt_dev2node (char const *devname, char *nodename, int nnlen);
 
 int
-bt_devopen(char const *devname)
+bt_devopen(char const *devname, int flags)
 {
 	struct sockaddr_hci	ha;
 	bdaddr_t		ba;
-	int			s;
+	int			opt, 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,
+	if (devname != NULL) {
+		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);
+			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) {
+	opt = 1;
+	if ((flags & BTOPT_DIRECTION) && setsockopt(s, SOL_HCI_RAW,
+	    SO_HCI_RAW_DIRECTION, &opt, sizeof(opt)) < 0) {
 		close(s);
 		return (-1);
 	}
 
+	opt = 1;
+	if ((flags & BTOPT_TIMESTAMP) && setsockopt(s, SOL_SOCKET,
+	    SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
+		close(s);
+		return (-1);
+	}
+
+	if (devname != NULL) {
+		if (bind(s, (struct sockaddr *) &ha, sizeof(ha)) < 0 ||
+		    connect(s, (struct sockaddr *) &ha, sizeof(ha)) < 0) {
+			close(s);
+			return (-1);
+		}
+	}
+
 	return (s);
 }
 
@@ -88,12 +101,13 @@
 	return (close(s));
 }
 
-int
+ssize_t
 bt_devsend(int s, uint16_t opcode, void *param, size_t plen)
 {
 	ng_hci_cmd_pkt_t	h;
 	struct iovec		iv[2];
 	int			ivn;
+	ssize_t			n;
 
 	if ((plen == 0 && param != NULL) ||
 	    (plen > 0 && param == NULL) ||
@@ -117,14 +131,14 @@
 	} else
 		h.length = 0;
 
-	while (writev(s, iv, ivn) < 0) {
+	while ((n = writev(s, iv, ivn)) < 0) {
 		if (errno == EAGAIN || errno == EINTR)
 			continue;
 
 		return (-1);
 	}
 
-	return (0);
+	return (n);
 }
 
 ssize_t
@@ -532,7 +546,7 @@
 }
 
 int
-bt_devinfo(struct bt_devinfo *di)
+bt_devinfo(char const *devname, struct bt_devinfo *di)
 {
 	union {
 		struct ng_btsocket_hci_raw_node_state		r0;
@@ -554,7 +568,7 @@
 		return (-1);
 	}
 
-	s = bt_devopen(di->devname);
+	s = bt_devopen(devname);
 	if (s < 0)
 		return (-1);
 
@@ -662,8 +676,7 @@
 	}
 
 	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)
+		if (bt_devinfo(rp.names[i].name, &di) < 0)
 			continue;
 
 		count ++;


More information about the freebsd-bluetooth mailing list