$NetBSD: patch-ae,v 1.1.1.1 2009/05/25 12:50:01 wiz Exp $

Replace "FreeBSD" Bluetooth support with "BSD".
This should cover NetBSD, FreeBSD, OpenBSD and DragonflyBSD at least.

The BLUETOOTH_RF_SEARCHING option will only work on systems that have
the later Service Discovery API in libbluetooth.

--- /dev/null	1970-01-01 01:00:00.000000000 +0100
+++ libgammu/device/bluetoth/blue_bsd.c	2009-05-22 09:43:12.000000000 +0100
@@ -0,0 +1,248 @@
+/*-
+ * Copyright (c) 2009 Iain Hibbert
+ * 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 ``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 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.
+ */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_BLUETOOTHDEVICE
+#ifdef BSD_BLUE_FOUND
+
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <bluetooth.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sdp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../../gsmcomon.h"
+#include "../devfunc.h"
+#include "bluetoth.h"
+
+/*
+ * Handle FreeBSD compatibility
+ */
+#ifndef BTPROTO_RFCOMM
+#define BTPROTO_RFCOMM	BLUETOOTH_PROTO_RFCOMM
+#define BDADDR_ANY	NG_HCI_BDADDR_ANY
+#define sockaddr_bt	sockaddr_rfcomm
+#define	bt_len		rfcomm_len
+#define	bt_family	rfcomm_family
+#define bt_channel	rfcomm_channel
+#define bt_bdaddr	rfcomm_bdaddr
+#endif
+
+static GSM_Error bluetooth_open(GSM_StateMachine *s, bdaddr_t *bdaddr, int channel)
+{
+	GSM_Device_BlueToothData	*d = &s->Device.Data.BlueTooth;
+	struct sockaddr_bt 		sa;
+	int 				fd;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.bt_len = sizeof(sa);
+	sa.bt_family = AF_BLUETOOTH;
+
+	smprintf(s, "Connecting to RF channel %i\n", channel);
+
+	fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+	if (fd < 0) {
+		smprintf(s, "Can't create socket\n");
+		return ERR_DEVICENODRIVER;
+	}
+
+	bdaddr_copy(&sa.bt_bdaddr, BDADDR_ANY);
+
+	if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+		smprintf(s, "Can't bind socket: %s\n", strerror(errno));
+		close(fd);
+		return ERR_DEVICEOPENERROR;
+	}
+
+	sa.bt_channel = channel;
+	bdaddr_copy(&sa.bt_bdaddr, bdaddr);
+
+	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+		smprintf(s, "Can't connect to %s: %s\n", bt_ntoa(bdaddr, NULL), strerror(errno));
+		close(fd);
+		return ERR_DEVICEOPENERROR;
+	}
+
+	d->hPhone = fd;
+    	return ERR_NONE;
+}
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
+{
+	bdaddr_t	bdaddr;
+	struct hostent *he = NULL;
+
+	if (!bt_aton(device, &bdaddr)) {
+		if ((he = bt_gethostbyname(device)) == NULL) {
+			smprintf(s, "%s: %s\n", device, hstrerror(h_errno));
+			return ERR_UNKNOWN;
+		}
+
+		bdaddr_copy(&bdaddr, (bdaddr_t *)he->h_addr);
+	}
+
+	return bluetooth_open(s, &bdaddr, port);
+}
+
+#ifdef BLUETOOTH_RF_SEARCHING
+
+static int bluetooth_channel(sdp_data_t *value)
+{
+	sdp_data_t	pdl, seq;
+	uintmax_t	channel;
+
+	sdp_get_alt(value, value);	/* strip any alt container */
+
+	while (sdp_get_seq(value, &pdl)) {
+		if (sdp_get_seq(&pdl, &seq)
+		    && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP)
+		    && sdp_get_seq(&pdl, &seq)
+		    && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_RFCOMM)
+		    && sdp_get_uint(&seq, &channel)
+		    && channel >= 1 && channel <= 30)
+			return channel;
+	}
+
+	return -1;
+}
+
+static char *bluetooth_service(sdp_data_t *value)
+{
+	char		*str;
+	size_t		len;
+
+	if (!sdp_get_str(value, &str, &len))
+		return NULL;
+
+	return strndup(str, len);
+}
+
+static GSM_Error bluetooth_search(GSM_StateMachine *s, bdaddr_t *bdaddr)
+{
+	sdp_data_t	rec, rsp, ssp, value;
+	uint8_t		buf[3];
+	uint16_t	attr;
+	sdp_session_t	ss;
+	int		ch, channel, sc, score;
+	char		*sv;
+
+	ss = sdp_open(NULL, bdaddr);
+	if (ss == NULL) {
+		smprintf(s, "SDP Connection failed: %s\n", strerror(errno));
+		return ERR_TIMEOUT;
+	}
+
+	ssp.next = buf;
+	ssp.end = buf + sizeof(buf);
+	sdp_put_uuid16(&ssp, SDP_UUID_PROTOCOL_RFCOMM);
+	ssp.end = ssp.next;
+	ssp.next = buf;
+
+	if (!sdp_service_search_attribute(ss, &ssp, NULL, &rsp)) {
+		smprintf(s, "SDP Service Search Attribute failed: %s\n", strerror(errno));
+		sdp_close(ss);
+		return ERR_UNKNOWN;
+	}
+
+	channel = -1;
+	score = 0;
+
+	while (sdp_get_seq(&rsp, &rec)) {
+		ch = -1;
+		sv = NULL;
+
+		while (sdp_get_attr(&rec, &attr, &value)) {
+			switch (attr) {
+			case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
+				ch = bluetooth_channel(&value);
+				break;
+
+			case SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET:
+				sv = bluetooth_service(&value);
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		if (ch != -1) {
+			smprintf(s, "   Channel %i", ch);
+			if (sv != NULL) {
+				sc = bluetooth_checkservicename(s, sv);
+				smprintf(s, " - \"%s\" (score=%d)", sv, sc);
+				if (sc > score) {
+					score = sc;
+					channel = ch;
+				}
+			}
+			smprintf(s, "\n");
+		}
+
+		free(sv);
+	}
+
+	sdp_close(ss);
+
+	if (channel == -1) {
+		smprintf(s, "No suitable service found!\n");
+		return ERR_NOTSUPPORTED;
+	}
+
+	return bluetooth_open(s, bdaddr, channel);
+}
+
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
+{
+	char		*device = s->CurrentConfig->Device;
+	bdaddr_t	bdaddr;
+	struct hostent *he = NULL;
+
+	if (!bt_aton(device, &bdaddr)) {
+		if ((he = bt_gethostbyname(device)) == NULL) {
+			smprintf(s, "%s: %s\n", device, hstrerror(h_errno));
+			return ERR_UNKNOWN;
+		}
+
+		bdaddr_copy(&bdaddr, (bdaddr_t *)he->h_addr);
+	}
+
+	return bluetooth_search(s, &bdaddr);
+}
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */
