From: Iain Hibbert <plu...@netbsd.org>

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
Openobex-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/openobex-users

Reply via email to