From: Iain Hibbert <[email protected]>
This should work on NetBSD and FreeBSD
and possibly OpenBSD and DragonflyBSD also with a little work
---
acinclude.m4 | 84 ++++++--------
configure.in | 1 -
obexftp/bt_kit.c | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
obexftp/bt_kit.h | 34 +++---
obexftp/client.c | 7 +-
5 files changed, 405 insertions(+), 68 deletions(-)
diff --git a/acinclude.m4 b/acinclude.m4
index c0ca90f..9a18ea1 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -50,31 +50,44 @@ AC_DEFUN([AC_PATH_WINBT], [
AC_MSG_RESULT([$winbt_cv_found])
])
-AC_DEFUN([AC_PATH_NETBSDBT], [
- AC_CACHE_CHECK([for NetBSD Bluetooth support], netbsdbt_cv_found, [
+AC_DEFUN([AC_PATH_BSDBT], [
+ AC_CACHE_CHECK([for BSD Bluetooth support], bsdbt_cv_found, [
AC_TRY_COMPILE([
#include <bluetooth.h>
], [
- struct sockaddr_bt *bt;
- ], netbsdbt_cv_found=yes, netbsdbt_cv_found=no)
+ #ifndef BTPROTO_RFCOMM
+ #define BTPROTO_RFCOMM BLUETOOTH_PROTO_RFCOMM
+ #endif
+
+ bdaddr_t bdaddr;
+ int family = AF_BLUETOOTH;
+ int proto = BTPROTO_RFCOMM;
+ ], bsdbt_cv_found=yes, bsdbt_cv_found=no)
])
-])
-
-AC_DEFUN([AC_PATH_FREEBSDBT], [
- AC_CACHE_CHECK([for FreeBSD Bluetooth support], freebsdbt_cv_found, [
- AC_TRY_COMPILE([
- #include <bluetooth.h>
- ], [
- struct sockaddr_rfcomm *rfcomm;
- ], freebsdbt_cv_found=yes, freebsdbt_cv_found=no)
- ])
- if test "${freebsdbt_cv_found}" = "yes"; then
+ if test "${bsdbt_cv_found}" = "yes"; then
BLUETOOTH_LIBS=-lbluetooth
+ AC_CACHE_CHECK([for BSD Service Discovery support],
bsdsdp_cv_found, [
+ AC_TRY_COMPILE([
+ #include <bluetooth.h>
+ #include <sdp.h>
+ ], [
+ struct bt_devinquiry di;
+ sdp_data_t data;
+ ], bsdsdp_cv_found=yes, bsdsdp_cv_found=no)
+ ])
fi
])
AC_DEFUN([AC_PATH_BLUEZ], [
- PKG_CHECK_MODULES(BLUETOOTH, bluez, bluez_found=yes, AC_MSG_RESULT(no))
+ PKG_CHECK_MODULES(BLUETOOTH, bluez, [
+ bluez_found=yes
+ AC_MSG_CHECKING(for BlueZ Service Discovery support)
+ AC_TRY_COMPILE([
+ #include <bluetooth/sdp.h>
+ ],[
+ sdp_list_t sdplist;
+ ], bluezsdp_found=yes, bluezsdp_found=no)
+ ], AC_MSG_RESULT(no))
])
AC_DEFUN([AC_PATH_BLUETOOTH], [
@@ -83,10 +96,10 @@ AC_DEFUN([AC_PATH_BLUETOOTH], [
AC_PATH_BLUEZ
;;
*-*-freebsd*)
- AC_PATH_FREEBSDBT
+ AC_PATH_BSDBT
;;
*-*-netbsd*)
- AC_PATH_NETBSDBT
+ AC_PATH_BSDBT
;;
*-*-mingw32*)
AC_PATH_WINBT
@@ -96,44 +109,21 @@ AC_DEFUN([AC_PATH_BLUETOOTH], [
AC_SUBST(BLUETOOTH_LIBS)
])
-AC_DEFUN([BLUETOOTH_CHECK],[
+AC_DEFUN([BLUETOOTH_CHECK],[
AC_ARG_ENABLE([bluetooth],
[AC_HELP_STRING([--disable-bluetooth],
[Disables bluetooth support
@<:@default=auto@:>@])],
[ac_bluetooth_enabled=$enableval],
[ac_bluetooth_enabled=yes])
if test "$ac_bluetooth_enabled" = yes; then
- AC_PATH_BLUETOOTH
- if test "${netbsdbt_cv_found}" = "yes" -o "${freebsdbt_cv_found}" =
"yes" -o "${bluez_found}" = "yes" -o "${winbt_cv_found}" = "yes"; then
+ AC_PATH_BLUETOOTH
+ if test "${bsdbt_cv_found}" = "yes" -o "${bluez_found}" = "yes" -o
"${winbt_cv_found}" = "yes"; then
AC_DEFINE([HAVE_BLUETOOTH], [1], [Define if system supports
Bluetooth and it's enabled])
fi
-fi
-])
-
-
-dnl
-dnl Check for Bluetooth SDP library
-dnl Waring: the AC_TRY_COMPILE won't work with -Werror
-dnl
-
-AC_DEFUN([SDPLIB_CHECK],[
- AC_MSG_CHECKING(for Bluetooth SDP support)
-
- AC_TRY_COMPILE( [
- #include <bluetooth/sdp.h>
- ],[
- sdp_list_t sdplist;
- ],
- am_cv_sdplib_found=yes,
- am_cv_sdplib_found=no
- )
-
- if test $am_cv_sdplib_found = yes; then
- AC_DEFINE(HAVE_SDPLIB,1,[Define if system supports Bluetooth
SDP])
-
+ if test "${bsdsdp_cv_found}" = "yes" -o "${bluezsdp_found}" = "yes";
then
+ AC_DEFINE([HAVE_SDP], [1], [Define if system supports Bluetooth
Service Discovery])
fi
-
- AC_MSG_RESULT($am_cv_sdplib_found)
+fi
])
diff --git a/configure.in b/configure.in
index 16bf3ca..9b1439d 100644
--- a/configure.in
+++ b/configure.in
@@ -41,7 +41,6 @@ dnl IRDA_CHECK
BLUETOOTH_CHECK
if test "${bluez_found}" = "yes"; then
REQUIRES="$REQUIRES bluez"
- SDPLIB_CHECK
fi
USB_CHECK
if test "${am_cv_usb_found}" = "yes"; then
diff --git a/obexftp/bt_kit.c b/obexftp/bt_kit.c
index 41aa224..67ee4ec 100644
--- a/obexftp/bt_kit.c
+++ b/obexftp/bt_kit.c
@@ -349,8 +349,350 @@ int btkit_unregister_service(int UNUSED(svclass))
#else /* _WIN32 */
-#ifdef HAVE_SDPLIB /* should switch on OS here */
+#ifdef HAVE_SDP
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+char **btkit_discover(const char *src)
+{
+ struct bt_devinquiry *di;
+ char **res;
+ int num_rsp = 10;
+ int length = 8;
+ int i;
+
+ DEBUG(2, "%s: Scanning ...\n", __func__);
+
+ num_rsp = bt_devinquiry(src, length, num_rsp, &di);
+ if(num_rsp < 0) {
+ DEBUG(1, "%s: Inquiry failed\n", __func__);
+ return NULL;
+ }
+
+ res = calloc(num_rsp + 1, sizeof(char *));
+ for(i = 0; i < num_rsp; i++) {
+ res[i] = bt_malloc(18); /* size of text bdaddr */
+ bt_ntoa(&di->bdaddr, res[i]);
+ DEBUG(2, "%s: Found\t%s\n", __func__, res[i]);
+ }
+
+ free(di);
+
+ return res;
+}
+
+static int btkit_getname_cb(int UNUSED(s), const struct bt_devinfo *di, void
*arg)
+{
+
+ if ((di->enabled)) {
+ strncpy(arg, di->devname, HCI_DEVNAME_SIZE);
+ return 1;
+ }
+
+ return 0;
+}
+
+char *btkit_getname(const char *src, const char *addr)
+{
+ hci_remote_name_req_cp cp;
+ hci_remote_name_req_compl_ep ep;
+ struct bt_devreq req;
+ int s;
+
+ return_val_if_fail(addr != NULL, NULL);
+
+ if (!src) {
+ if (bt_devenum(btkit_getname_cb, ep.name) == -1) {
+ DEBUG(1, "%s: device enumeration failed\n", __func__);
+ return NULL;
+ }
+
+ src = (const char *)ep.name;
+ }
+
+ s = bt_devopen(src, 0);
+ if (s == -1) {
+ DEBUG(1, "%s: HCI device open failed\n", __func__);
+ return NULL;
+ }
+
+ memset(&cp, 0, sizeof(cp));
+ bt_aton(addr, &cp.bdaddr);
+
+ memset(&req, 0, sizeof(req));
+ req.opcode = HCI_CMD_REMOTE_NAME_REQ;
+ req.cparam = &cp;
+ req.clen = sizeof(cp);
+ req.event = HCI_EVENT_REMOTE_NAME_REQ_COMPL;
+ req.rparam = &ep;
+ req.rlen = sizeof(ep);
+
+ if (bt_devreq(s, &req, 100) == -1) {
+ DEBUG(1, "%s: remote name request failed\n", __func__);
+ strcpy(ep.name, "No Name");
+ }
+
+ close(s);
+
+ return strndup(ep.name, sizeof(ep.name));
+}
+
+static int btkit_browse_sdp(sdp_session_t ss, uuid_t *uuid)
+{
+ uint8_t buf[19]; /* enough for uuid128 (ssp) and uint16 (ail) */
+ sdp_data_t seq, ssp, ail, rsp, rec, value, pdl;
+ uintmax_t channel;
+ uint16_t attr;
+
+ seq.next = buf;
+ seq.end = buf + sizeof(buf);
+
+ /* build ServiceSearchPattern */
+ ssp.next = seq.next;
+ sdp_put_uuid(&seq, uuid);
+ ssp.end = seq.next;
+
+ /* build AttributeIDList */
+ ail.next = seq.next;
+ sdp_put_uint16(&seq, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+ ail.end = seq.next;
+
+ if (!sdp_service_search_attribute(ss, &ssp, &ail, &rsp)) {
+ DEBUG(1, "%s: SDP service search failed\n", __func__);
+ return -1;
+ }
+
+ /*
+ * we expect the response to contain a list of records
+ * containing ProtocolDescriptorList. Return the first
+ * one with a valid RFCOMM channel.
+ */
+ while (sdp_get_seq(&rsp, &rec)) {
+ if (!sdp_get_attr(&rec, &attr, &value)
+ || attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST)
+ continue;
+
+ /* drop any alt header */
+ sdp_get_alt(&value, &value);
+
+ /* for each protocol stack */
+ while (sdp_get_seq(&value, &pdl)) {
+ /* and for each protocol */
+ while (sdp_get_seq(&pdl, &seq)) {
+ /* check for RFCOMM */
+ if (sdp_match_uuid16(&seq,
SDP_UUID_PROTOCOL_RFCOMM)
+ && sdp_get_uint(&seq, &channel)
+ && channel >= RFCOMM_CHANNEL_MIN
+ && channel <= RFCOMM_CHANNEL_MAX)
+ return channel;
+ }
+ }
+ }
+
+ DEBUG(1, "%s: no channel found\n", __func__);
+
+ return -1;
+}
+
+int btkit_browse(const char *src, const char *addr, int svclass)
+{
+ bdaddr_t laddr, raddr;
+ sdp_session_t ss;
+ uuid_t uuid;
+ int channel;
+
+ return_val_if_fail(addr != NULL, -1);
+ bt_aton(addr, &raddr);
+
+ if (src) {
+ if (!bt_devaddr(src, &laddr)) {
+ DEBUG(1, "%s: invalid source address\n", __func__);
+ return -1;
+ }
+ } else {
+ bdaddr_copy(&laddr, BDADDR_ANY);
+ }
+
+ ss = sdp_open(&laddr, &raddr);
+ if (ss == NULL) {
+ DEBUG(1, "%s: Failed to connect to SDP server\n", __func__);
+ return -1;
+ }
+
+ if (svclass >= 0x0001 && svclass <= 0x0004) {
+ uuid_dec_be(SVC_UUID_SYNCML, &uuid);
+ uuid.time_low = svclass;
+ } else if (svclass >= 0x1000 && svclass <= 0x12FF) {
+ uuid_dec_be(SVC_UUID_BASE, &uuid);
+ uuid.time_low = svclass;
+ } else {
+ svclass = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER;
+ }
+
+ DEBUG(1, "%s: svclass 0x%04x\n", __func__, svclass);
+
+ channel = -1;
+
+ /* Try PCSUITE first */
+ if (svclass == SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER) {
+ DEBUG(1, "%s: trying PCSUITE first\n", __func__);
+ uuid_dec_be(SVC_UUID_PCSUITE, &uuid);
+ channel = btkit_browse_sdp(ss, &uuid);
+
+ uuid_dec_be(SVC_UUID_BASE, &uuid);
+ uuid.time_low = svclass;
+ }
+
+ if (channel == -1)
+ channel = btkit_browse_sdp(ss, &uuid);
+
+ sdp_close(ss);
+ return channel;
+}
+
+static sdp_session_t ss;
+static uint32_t opush_handle;
+static uint32_t ftrn_handle;
+static uint32_t irmc_handle;
+
+int btkit_register_obex(int svclass, int channel)
+{
+ uint8_t buffer[256];
+ sdp_data_t rec;
+ uint32_t *hp;
+
+ DEBUG(1, "%s: svclass 0x%04x channel %d\n", __func__, svclass, channel);
+
+ /* Build SDP record */
+ rec.next = buffer;
+ rec.end = buffer + sizeof(buffer);
+
+ sdp_put_uint16(&rec, SDP_ATTR_SERVICE_RECORD_HANDLE);
+ sdp_put_uint32(&rec, 0x00000000);
+
+ sdp_put_uint16(&rec, SDP_ATTR_SERVICE_CLASS_ID_LIST);
+ sdp_put_seq(&rec, 3);
+ sdp_put_uuid16(&rec, (uint16_t)svclass);
+
+ sdp_put_uint16(&rec, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+ sdp_put_seq(&rec, 17);
+ sdp_put_seq(&rec, 3);
+ sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_L2CAP);
+ sdp_put_seq(&rec, 5);
+ sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_RFCOMM);
+ sdp_put_uint8(&rec, (uint8_t)channel);
+ sdp_put_seq(&rec, 3);
+ sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_OBEX);
+
+ sdp_put_uint16(&rec, SDP_ATTR_BROWSE_GROUP_LIST);
+ sdp_put_seq(&rec, 3);
+ sdp_put_uuid16(&rec, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
+
+ sdp_put_uint16(&rec, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
+ sdp_put_seq(&rec, 9);
+ sdp_put_uint16(&rec, 0x656e); /* "en" */
+ sdp_put_uint16(&rec, 106); /* UTF-8 */
+ sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
+
+ sdp_put_uint16(&rec, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
+ sdp_put_seq(&rec, 8);
+ sdp_put_seq(&rec, 6);
+ sdp_put_uuid16(&rec, (uint16_t)svclass);
+ sdp_put_uint16(&rec, 0x0100); /* v1.0 */
+
+ sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID +
SDP_ATTR_SERVICE_NAME_OFFSET);
+ switch (svclass) {
+ case SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH:
+ sdp_put_str(&rec, "OBEX Object Push", -1);
+
+ sdp_put_uint16(&rec, SDP_ATTR_SUPPORTED_FORMATS_LIST);
+ sdp_put_seq(&rec, 2);
+ sdp_put_uint8(&rec, 0xff); /* Any */
+ hp = &opush_handle;
+ break;
+
+ case SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER:
+ sdp_put_str(&rec, "OBEX File Transfer", -1);
+ hp = &ftrn_handle;
+ break;
+
+ case SDP_SERVICE_CLASS_IR_MC_SYNC:
+ sdp_put_str(&rec, "IrMC Sync", -1);
+ hp = &irmc_handle;
+ break;
+
+ default:
+ DEBUG(1, "%s: unknown svclass\n", __func__);
+ return -1;
+ break;
+ }
+
+ rec.end = rec.next;
+ rec.next = buffer;
+
+ /* Register service with SDP server */
+ if (ss == NULL) {
+ ss = sdp_open_local(NULL);
+ if (ss == NULL) {
+ DEBUG(1, "%s: failed to open SDP session\n", __func__);
+ return -1;
+ }
+ DEBUG(2, "%s: opened SDP session\n", __func__);
+ }
+
+ if (!sdp_record_insert(ss, NULL, hp, &rec)) {
+ DEBUG(1, "%s: failed to insert SDP record\n", __func__);
+ sdp_data_print(&rec, 2);
+ return -1;
+ }
+
+ return 0;
+}
+
+int btkit_unregister_service(int svclass)
+{
+ uint32_t *hp;
+
+ if (ss == NULL) {
+ DEBUG(1, "%s: no session open\n", __func__);
+ return -1;
+ }
+
+ switch (svclass) {
+ case SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH:
+ hp = &opush_handle;
+ break;
+
+ case SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER:
+ hp = &ftrn_handle;
+ break;
+
+ case SDP_SERVICE_CLASS_IR_MC_SYNC:
+ hp = &irmc_handle;
+ break;
+
+ default:
+ DEBUG(1, "%s: unknown svclass\n", __func__);
+ return -1;
+ break;
+ }
+
+ if (!sdp_record_remove(ss, *hp)) {
+ DEBUG(1, "%s: failed to remove SDP record\n", __func__);
+ return -1;
+ }
+
+ *hp = 0;
+
+ if (opush_handle == 0 && ftrn_handle == 0 && irmc_handle == 0) {
+ DEBUG(2, "%s: closed SDP session\n", __func__);
+ sdp_close(ss);
+ ss = NULL;
+ }
+
+ return 0;
+}
+
+#else /* defined(__NetBSD__) || defined(__FreeBSD__) */
/**
Discover all bluetooth devices in range.
@@ -695,6 +1037,7 @@ int btkit_register_obex(int service, int channel)
return 0;
}
+#endif /* BlueZ/Linux */
#else
#warning "no bluetooth sdp support for this platform"
@@ -723,7 +1066,7 @@ int btkit_unregister_service(int UNUSED(svclass))
return -1;
}
-#endif /* HAVE_SDPLIB */
+#endif /* HAVE_SDP */
#endif /* _WIN32 */
#else
diff --git a/obexftp/bt_kit.h b/obexftp/bt_kit.h
index 154c73b..6eeba6b 100644
--- a/obexftp/bt_kit.h
+++ b/obexftp/bt_kit.h
@@ -79,26 +79,26 @@ extern "C" {
BTKITSYM int ba2str(const bdaddr_t *btaddr, char *straddr);
BTKITSYM int str2ba(const char *straddr, BTH_ADDR *btaddr);
-/* FreeBSD 5 and up */
-#elif defined(__FreeBSD__)
-//#include <sys/types.h>
+/* Various BSD systems */
+#elif defined(__NetBSD__) || defined(__FreeBSD__)
+#define COMPAT_BLUEZ
#include <bluetooth.h>
-#define sockaddr_rc sockaddr_rfcomm
-#define rc_family rfcomm_family
-#define rc_bdaddr rfcomm_bdaddr
-#define rc_channel rfcomm_channel
-#define BTPROTO_RFCOMM BLUETOOTH_PROTO_RFCOMM
-#define BDADDR_ANY NG_HCI_BDADDR_ANY
+#ifdef HAVE_SDP
+#include <sdp.h>
+#include <string.h>
+#endif
-/* NetBSD-4 and up */
-#elif defined(__NetBSD__)
-#include <bluetooth.h>
-#include <netbt/rfcomm.h>
-#define sockaddr_rc sockaddr_bt
-#define rc_family bt_family
-#define rc_bdaddr bt_bdaddr
-#define rc_channel bt_channel
+#ifndef BDADDR_ANY
#define BDADDR_ANY NG_HCI_BDADDR_ANY
+#endif
+
+#ifndef RFCOMM_CHANNEL_MIN
+#define RFCOMM_CHANNEL_MIN 1
+#endif
+
+#ifndef RFCOMM_CHANNEL_MAX
+#define RFCOMM_CHANNEL_MAX 30
+#endif
/* BlueZ, Linux 2.4.6 and up (incl. 2.6) */
#else
diff --git a/obexftp/client.c b/obexftp/client.c
index e0f494f..15ec298 100644
--- a/obexftp/client.c
+++ b/obexftp/client.c
@@ -664,7 +664,12 @@ int obexftp_connect_src(obexftp_client_t *cli, const char
*src, const char *devi
if (!src) {
bacpy(&src_addr, BDADDR_ANY);
}
-#ifdef HAVE_SDPLIB
+#if defined(_WIN32)
+ /* nothing */
+#elif defined(__NetBSD__) || defined(__FreeBSD__)
+ else if (bt_devaddr(src, &src_addr)) {
+ }
+#else
else if (!strncmp(src, "hci", 3)) {
hci_devba(atoi(src + 3), &src_addr);
}
--
1.7.4.1
------------------------------------------------------------------------------
All of the data generated in your IT infrastructure is seriously valuable.
Why? It contains a definitive record of application performance, security
threats, fraudulent activity, and more. Splunk takes this data and makes
sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-d2d-c2
_______________________________________________
Openobex-users mailing list
[email protected]
http://lists.sourceforge.net/lists/listinfo/openobex-users