[packages] remove asterisk-addons-1.4.x (#8898)
authorFlorian Fainelli <florian@openwrt.org>
Mon, 21 Feb 2011 09:24:58 +0000 (09:24 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Mon, 21 Feb 2011 09:24:58 +0000 (09:24 +0000)
SVN-Revision: 25645

net/asterisk-addons-1.4.x/Makefile [deleted file]
net/asterisk-addons-1.4.x/patches/011-chan_mobile.patch [deleted file]
net/asterisk-addons-1.4.x/patches/021-cross_configure.patch [deleted file]
net/asterisk-addons-1.4.x/patches/030-mysql_include.patch [deleted file]

diff --git a/net/asterisk-addons-1.4.x/Makefile b/net/asterisk-addons-1.4.x/Makefile
deleted file mode 100644 (file)
index 36c48ca..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-#
-# Copyright (C) 2007 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-
-PKG_NAME:=asterisk-addons
-PKG_VERSION:=1.4.8
-PKG_RELEASE:=1
-
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
-PKG_SOURCE_URL:=http://downloads.digium.com/pub/asterisk/releases/
-PKG_MD5SUM:=d4e75c39f737b5ba2a75a4420e1a5a78
-
-PKG_FIXUP = libtool
-
-include $(INCLUDE_DIR)/package.mk
-
-define Package/asterisk-addons/Default
-  SUBMENU:=asterisk14 (Complete Open Source PBX), v1.4.x
-  SECTION:=net
-  CATEGORY:=Network
-  TITLE:=Asterisk addons
-  URL:=http://www.asterisk.org/
-  MAINTAINER:=Hans Zandbelt <hans.zandbelt@gmail.com>
-endef
-
-define Package/asterisk-addons/Default/description
- Asterisk addons contains additional modules for Asterisk which are, for 
- one reason or another, not included in the normal base distribution.
-endef
-
-
-define Package/asterisk14-chan-mobile
-$(call Package/asterisk-addons/Default)
-  DEPENDS:= +asterisk14 +bluez-libs
-  TITLE+= Mobile channel support
-endef
-
-define Package/asterisk14-chan-mobile/description
-$(call Package/asterisk-addons/Default/description)
- This package contains the chan_mobile module for Asterisk.
-endef
-
-
-define Package/asterisk14-chan-ooh323
-$(call Package/asterisk-addons/Default)
-  DEPENDS:= +asterisk14
-  TITLE+= OO H.323 channel support
-endef
-
-define Package/asterisk14-chan-ooh323/description
-$(call Package/asterisk-addons/Default/description)
- This package contains the Objective Open H.323 support module for Asterisk.
-endef
-
-
-define Package/asterisk14-format-mp3
-$(call Package/asterisk-addons/Default)
-  DEPENDS:= +asterisk14
-  TITLE+= MP3 format support
-endef
-
-define Package/asterisk14-format-mp3/description
-$(call Package/asterisk-addons/Default/description)
- This package contains the MP3 support module for Asterisk.
-endef
-
-
-define Package/asterisk14-mysql
-$(call Package/asterisk-addons/Default)
-  DEPENDS:= +asterisk14 +libmysqlclient
-  TITLE+= MySQL support
-endef
-
-define Package/asterisk14-mysql/description
-$(call Package/asterisk-addons/Default/description)
- This package contains MySQL support modules for Asterisk.
-endef
-
-
-EXTRA_CFLAGS:=$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)
-EXTRA_LDFLAGS:=$(TARGET_LDFLAGS)
-
-ifneq ($(SDK)$(CONFIG_PACKAGE_asterisk14-mysql),)
-  EXTRA_CFLAGS+= -I$(STAGING_DIR)/usr/include/mysql
-  EXTRA_LDFLAGS+= -L$(STAGING_DIR)/usr/lib/mysql
-endif
-
-CONFIGURE_ARGS += \
-       --with-asterisk="$(STAGING_DIR)/usr/include/asterisk-1.4" \
-       --with-bluetooth="$(STAGING_DIR)/usr" \
-       --with-ncurses="$(STAGING_DIR)/usr" \
-       --with-mysqlclient="$(STAGING_DIR)/usr" \
-       
-define Build/Configure
-       ( cd $(PKG_BUILD_DIR); ./bootstrap.sh )
-       $(call Build/Configure/Default,,,)
-       $(call Build/Configure/Default,,,asterisk-ooh323c)
-endef
-
-# XXX: explanations
-# - use AM_CFLAGS for asterisk-ooh323c
-# - use OPTIMIZE & OPTIONS for format_mp3
-
-MAKE_ARGS:= \
-       AM_CFLAGS="$(TARGET_CFLAGS)" \
-       OPTIMIZE="$(TARGET_CFLAGS) -DLOW_MEMORY" \
-       OPTIONS="" \
-       NOISY_BUILD="yes" \
-       BLUETOOTH_LIB="$(TARGET_LDFLAGS) -lbluetooth" \
-
-MAKE_VARS:= \
-       CFLAGS="$(EXTRA_CFLAGS)" \
-       LDFLAGS="$(EXTRA_LDFLAGS)" \
-
-define Build/Compile
-       mkdir -p $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules
-       $(MAKE_VARS) \
-       $(MAKE) -C "$(PKG_BUILD_DIR)" \
-               $(MAKE_ARGS) \
-               all
-       $(MAKE_VARS) \
-       $(MAKE) -C "$(PKG_BUILD_DIR)" \
-               $(MAKE_ARGS) \
-               DESTDIR="$(PKG_INSTALL_DIR)" \
-               install samples
-endef
-
-
-define Package/asterisk14-chan-mobile/conffiles
-/etc/asterisk/mobile.conf
-endef
-
-define Package/asterisk14-chan-mobile/install
-       $(INSTALL_DIR) $(1)/etc/asterisk
-       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/mobile.conf $(1)/etc/asterisk/
-       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
-       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_mobile.so $(1)/usr/lib/asterisk/modules/
-endef
-
-
-define Package/asterisk14-chan-ooh323/install
-       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
-       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/chan_ooh323.so $(1)/usr/lib/asterisk/modules/
-endef
-
-
-define Package/asterisk14-format-mp3/install
-       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
-       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/format_mp3.so $(1)/usr/lib/asterisk/modules/
-endef
-
-
-define Package/asterisk14-mysql/conffiles
-/etc/asterisk/cdr_mysql.conf
-/etc/asterisk/res_mysql.conf
-endef
-
-define Package/asterisk14-mysql/install
-       $(INSTALL_DIR) $(1)/etc/asterisk
-       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/cdr_mysql.conf $(1)/etc/asterisk/
-       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/asterisk/res_mysql.conf $(1)/etc/asterisk/
-       $(INSTALL_DIR) $(1)/usr/lib/asterisk/modules
-       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/app_addon_sql_mysql.so $(1)/usr/lib/asterisk/modules/
-       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/cdr_addon_mysql.so $(1)/usr/lib/asterisk/modules/
-       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/asterisk/modules/res_config_mysql.so $(1)/usr/lib/asterisk/modules/
-endef
-
-
-$(eval $(call BuildPackage,asterisk14-chan-mobile))
-$(eval $(call BuildPackage,asterisk14-chan-ooh323))
-$(eval $(call BuildPackage,asterisk14-format-mp3))
-$(eval $(call BuildPackage,asterisk14-mysql))
diff --git a/net/asterisk-addons-1.4.x/patches/011-chan_mobile.patch b/net/asterisk-addons-1.4.x/patches/011-chan_mobile.patch
deleted file mode 100644 (file)
index 21a16c7..0000000
+++ /dev/null
@@ -1,2263 +0,0 @@
-diff -Nru asterisk-addons-1.4.8.org/build_tools/menuselect-deps.in asterisk-addons-1.4.8/build_tools/menuselect-deps.in
---- asterisk-addons-1.4.8.org/build_tools/menuselect-deps.in   2007-05-14 18:22:44.000000000 +0200
-+++ asterisk-addons-1.4.8/build_tools/menuselect-deps.in       2009-06-04 22:20:03.000000000 +0200
-@@ -1,2 +1,3 @@
-+BLUETOOTH=@PBX_BLUETOOTH@
- MYSQLCLIENT=@PBX_MYSQLCLIENT@
- ASTERISK=@PBX_ASTERISK@
-diff -Nru asterisk-addons-1.4.8.org/channels/chan_mobile.c asterisk-addons-1.4.8/channels/chan_mobile.c
---- asterisk-addons-1.4.8.org/channels/chan_mobile.c   1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-addons-1.4.8/channels/chan_mobile.c       2009-06-04 22:20:03.000000000 +0200
-@@ -0,0 +1,2150 @@
-+/*
-+ * Asterisk -- An open source telephony toolkit.
-+ *
-+ * Copyright (C) 1999 - 2006, Digium, Inc.
-+ *
-+ * Mark Spencer <markster@digium.com>
-+ *
-+ * See http://www.asterisk.org for more information about
-+ * the Asterisk project. Please do not directly contact
-+ * any of the maintainers of this project for assistance;
-+ * the project provides a web site, mailing lists and IRC
-+ * channels for your use.
-+ *
-+ * This program is free software, distributed under the terms of
-+ * the GNU General Public License Version 2. See the LICENSE file
-+ * at the top of the source tree.
-+ */
-+
-+/*! \file
-+ *
-+ * \brief Bluetooth Mobile Device channel driver
-+ *
-+ * \author Dave Bowerman <david.bowerman@gmail.com>
-+ *
-+ * \ingroup channel_drivers
-+ */
-+
-+/*** MODULEINFO
-+      <depend>bluetooth</depend>
-+ ***/
-+
-+#include <asterisk.h>
-+
-+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <sys/socket.h>
-+#include <sys/time.h>
-+#include <errno.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <arpa/inet.h>
-+#include <fcntl.h>
-+#include <sys/ioctl.h>
-+#include <signal.h>
-+
-+#include <bluetooth/bluetooth.h>
-+#include <bluetooth/hci.h>
-+#include <bluetooth/hci_lib.h>
-+#include <bluetooth/sdp.h>
-+#include <bluetooth/sdp_lib.h>
-+#include <bluetooth/rfcomm.h>
-+#include <bluetooth/sco.h>
-+#include <bluetooth/l2cap.h>
-+
-+#include <asterisk/lock.h>
-+#include <asterisk/channel.h>
-+#include <asterisk/config.h>
-+#include <asterisk/logger.h>
-+#include <asterisk/module.h>
-+#include <asterisk/pbx.h>
-+#include <asterisk/options.h>
-+#include <asterisk/utils.h>
-+#include <asterisk/linkedlists.h>
-+#include <asterisk/cli.h>
-+#include <asterisk/devicestate.h>
-+#include <asterisk/causes.h>
-+#include <asterisk/dsp.h>
-+#include <asterisk/app.h>
-+#include <asterisk/manager.h>
-+
-+#define MBL_CONFIG "mobile.conf"
-+
-+#define DEVICE_FRAME_SIZE 48
-+#define DEVICE_FRAME_FORMAT AST_FORMAT_SLINEAR
-+#define CHANNEL_FRAME_SIZE 320
-+
-+static int prefformat = DEVICE_FRAME_FORMAT;
-+
-+static int discovery_interval = 60;                   /* The device discovery interval, default 60 seconds. */
-+static pthread_t discovery_thread = AST_PTHREADT_NULL;        /* The discovery thread */
-+static sdp_session_t *sdp_session;
-+
-+enum mbl_type {
-+      MBL_TYPE_PHONE,
-+      MBL_TYPE_HEADSET
-+};
-+
-+enum mbl_state {
-+      MBL_STATE_INIT = 0,
-+      MBL_STATE_INIT1,
-+      MBL_STATE_INIT2,
-+      MBL_STATE_INIT3,
-+      MBL_STATE_INIT4,
-+      MBL_STATE_INIT5,
-+      MBL_STATE_INIT6,
-+      MBL_STATE_INIT7,
-+      MBL_STATE_PREIDLE,
-+      MBL_STATE_IDLE,
-+      MBL_STATE_DIAL,
-+      MBL_STATE_DIAL1,
-+      MBL_STATE_OUTGOING,
-+      MBL_STATE_RING,
-+      MBL_STATE_RING2,
-+      MBL_STATE_RING3,
-+      MBL_STATE_INCOMING,
-+      MBL_STATE_HANGUP,
-+      MBL_STATE_INSMS,
-+      MBL_STATE_OUTSMS,
-+      MBL_STATE_OUTSMS1,
-+      MBL_STATE_OUTSMS2
-+};
-+
-+struct adapter_pvt {
-+      int dev_id;                                     /* device id */
-+      int hci_socket;                                 /* device descriptor */
-+      char id[31];                                    /* the 'name' from mobile.conf */
-+      bdaddr_t addr;                                  /* adddress of adapter */
-+      unsigned int inuse:1;                           /* are we in use ? */
-+      unsigned int alignment_detection:1;             /* do alignment detection on this adpater? */
-+      int sco_socket;
-+      AST_LIST_ENTRY(adapter_pvt) entry;
-+};
-+
-+static AST_RWLIST_HEAD_STATIC(adapters, adapter_pvt);
-+
-+struct mbl_pvt {
-+      struct ast_channel *owner;                      /* Channel we belong to, possibly NULL */
-+      struct ast_frame fr;                            /* "null" frame */
-+      enum mbl_type type;                             /* Phone or Headset */
-+      char id[31];                                    /* The id from mobile.conf */
-+      int group;                                      /* group number for group dialling */
-+      bdaddr_t addr;                                  /* address of device */
-+      struct adapter_pvt *adapter;                    /* the adapter we use */
-+      char context[AST_MAX_CONTEXT];                  /* the context for incoming calls */
-+      char connected;                                 /* is it connected? */
-+      int rfcomm_port;                                /* rfcomm port number */
-+      int rfcomm_socket;                              /* rfcomm socket descriptor */
-+      char rfcomm_buf[256];
-+      char io_buf[CHANNEL_FRAME_SIZE + AST_FRIENDLY_OFFSET];
-+      char io_save_buf[DEVICE_FRAME_SIZE];
-+      int io_save_len;
-+      int io_pipe[2];
-+      int sco_socket;                                 /* sco socket descriptor */
-+      pthread_t sco_listener_thread;                  /* inbound sco listener for this device */
-+      enum mbl_state state;                           /* monitor thread current state */
-+      pthread_t monitor_thread;                       /* monitor thread handle */
-+      char dial_number[AST_MAX_EXTENSION];            /* number for the monitor thread to dial */
-+      int dial_timeout;
-+      char ciev_call_0[5];                            /* dynamically built reponse strings */
-+      char ciev_call_1[5];
-+      char ciev_callsetup_0[5];
-+      char ciev_callsetup_1[5];
-+      char ciev_callsetup_2[5];
-+      char ciev_callsetup_3[5];
-+      unsigned int no_callsetup:1;
-+      unsigned int has_sms:1;
-+      unsigned int sent_answer:1;
-+      unsigned int do_alignment_detection:1;
-+      unsigned int alignment_detection_triggered:1;
-+      unsigned int do_hangup:1;
-+      unsigned int blackberry:1;
-+      short alignment_samples[4];
-+      int alignment_count;
-+      char sms_txt[160];
-+      struct ast_dsp *dsp;
-+      struct ast_frame *dsp_fr;
-+      int dtmf_skip;
-+      int skip_frames;
-+      char hangup_count;
-+      AST_LIST_ENTRY(mbl_pvt) entry;
-+};
-+
-+static AST_RWLIST_HEAD_STATIC(devices, mbl_pvt);
-+
-+/* CLI stuff */
-+static const char show_usage[] =
-+"Usage: mobile show devices\n" 
-+"       Shows the state of Bluetooth Cell / Mobile devices.\n";
-+
-+static const char search_usage[] =
-+"Usage: mobile search\n" 
-+"       Searches for Bluetooth Cell / Mobile devices in range.\n";
-+
-+static const char rfcomm_usage[] =
-+"Usage: mobile rfcomm command\n" 
-+"       Send command to the rfcomm port.\n";
-+
-+static int handle_cli_mobile_show_devices(int fd, int argc, char **argv);
-+static int handle_cli_mobile_search(int fd, int argc, char **argv);
-+static int handle_cli_mobile_rfcomm(int fd, int argc, char **argv);
-+
-+static struct ast_cli_entry mbl_cli[] = {
-+      {{"mobile", "show", "devices", NULL}, handle_cli_mobile_show_devices, "Show Bluetooth Cell / Mobile devices", show_usage},
-+      {{"mobile", "search", NULL}, handle_cli_mobile_search, "Search for Bluetooth Cell / Mobile devices", search_usage},
-+      {{"mobile", "rfcomm", NULL}, handle_cli_mobile_rfcomm, "Send commands to the rfcomm port for debugging", rfcomm_usage},
-+};
-+
-+/* App stuff */
-+static char *app_mblstatus = "MobileStatus";
-+static char *mblstatus_synopsis = "MobileStatus(Device,Variable)";
-+static char *mblstatus_desc =
-+"MobileStatus(Device,Variable)\n"
-+"  Device - Id of mobile device from mobile.conf\n"
-+"  Variable - Variable to store status in will be 1-3.\n" 
-+"             In order, Disconnected, Connected & Free, Connected & Busy.\n";
-+
-+static char *app_mblsendsms = "MobileSendSMS";
-+static char *mblsendsms_synopsis = "MobileSendSMS(Device,Dest,Message)";
-+static char *mblsendsms_desc =
-+"MobileSendSms(Device,Dest,Message)\n"
-+"  Device - Id of device from mobile.conf\n"
-+"  Dest - destination\n"
-+"  Message - text of the message\n";
-+
-+static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num);
-+static struct ast_channel *mbl_request(const char *type, int format, void *data, int *cause);
-+static int mbl_call(struct ast_channel *ast, char *dest, int timeout);
-+static int mbl_hangup(struct ast_channel *ast);
-+static int mbl_answer(struct ast_channel *ast);
-+static int mbl_digit_begin(struct ast_channel *ast, char digit);
-+static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
-+static struct ast_frame *mbl_read(struct ast_channel *ast);
-+static int mbl_write(struct ast_channel *ast, struct ast_frame *frame);
-+static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-+static int mbl_devicestate(void *data);
-+
-+static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen);
-+
-+static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel);
-+static int rfcomm_write(struct mbl_pvt *pvt, char *buf);
-+static int rfcomm_read(struct mbl_pvt *pvt, char *buf, char flush, int timeout);
-+
-+static int sco_connect(bdaddr_t src, bdaddr_t dst);
-+static int sco_write(int s, char *buf, int len);
-+static int sco_read(int s, char *buf, int len);
-+
-+static void *do_sco_listen(void *data);
-+static int sdp_search(char *addr, int profile);
-+
-+static const struct ast_channel_tech mbl_tech = {
-+      .type = "Mobile",
-+      .description = "Bluetooth Mobile Device Channel Driver",
-+      .capabilities = AST_FORMAT_SLINEAR,
-+      .requester = mbl_request,
-+      .call = mbl_call,
-+      .hangup = mbl_hangup,
-+      .answer = mbl_answer,
-+      .send_digit_begin = mbl_digit_begin,
-+      .send_digit_end = mbl_digit_end,
-+      .read = mbl_read,
-+      .write = mbl_write,
-+      .fixup = mbl_fixup,
-+      .devicestate = mbl_devicestate
-+};
-+
-+/* CLI Commands implementation */
-+
-+static int handle_cli_mobile_show_devices(int fd, int argc, char **argv)
-+{
-+      struct mbl_pvt *pvt;
-+      char bdaddr[18];
-+      char group[6];
-+
-+#define FORMAT1 "%-15.15s %-17.17s %-5.5s %-15.15s %-9.9s %-5.5s %-3.3s\n"
-+
-+      if (argc != 3)
-+              return RESULT_SHOWUSAGE;
-+
-+      ast_cli(fd, FORMAT1, "ID", "Address", "Group", "Adapter", "Connected", "State", "SMS");
-+      AST_RWLIST_RDLOCK(&devices);
-+      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+              ba2str(&pvt->addr, bdaddr);
-+              snprintf(group, 5, "%d", pvt->group);
-+              ast_cli(fd, FORMAT1, pvt->id, bdaddr, group, pvt->adapter->id, pvt->connected ? "Yes" : "No",
-+                      (pvt->state == MBL_STATE_IDLE) ? "Free" : (pvt->state < MBL_STATE_IDLE) ? "Init" : "Busy",
-+                      (pvt->has_sms) ? "Yes" : "No");
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+
-+#undef FORMAT1
-+
-+      return RESULT_SUCCESS;
-+}
-+
-+static int handle_cli_mobile_search(int fd, int argc, char **argv)
-+{
-+      struct adapter_pvt *adapter;
-+      inquiry_info *ii = NULL;
-+      int max_rsp, num_rsp;
-+      int len, flags;
-+      int i, phport, hsport;
-+      char addr[19] = {0};
-+      char name[31] = {0};
-+
-+#define FORMAT1 "%-17.17s %-30.30s %-6.6s %-7.7s %-4.4s\n"
-+#define FORMAT2 "%-17.17s %-30.30s %-6.6s %-7.7s %d\n"
-+
-+      if (argc != 2)
-+              return RESULT_SHOWUSAGE;
-+
-+      /* find a free adapter */
-+      AST_RWLIST_RDLOCK(&adapters);
-+      AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
-+              if (!adapter->inuse)
-+                      break;
-+      }
-+      AST_RWLIST_UNLOCK(&adapters);
-+
-+      if (!adapter) {
-+              ast_cli(fd, "All Bluetooth adapters are in use at this time.\n");
-+              return RESULT_SUCCESS;
-+      }
-+
-+      len  = 8;
-+      max_rsp = 255;
-+      flags = IREQ_CACHE_FLUSH;
-+
-+      ii = alloca(max_rsp * sizeof(inquiry_info));
-+      num_rsp = hci_inquiry(adapter->dev_id, len, max_rsp, NULL, &ii, flags);
-+      if (num_rsp > 0) {
-+              ast_cli(fd, FORMAT1, "Address", "Name", "Usable", "Type", "Port");
-+              for (i = 0; i < num_rsp; i++) {
-+                      ba2str(&(ii + i)->bdaddr, addr);
-+                      name[0] = 0x00;
-+                      if (hci_read_remote_name(adapter->hci_socket, &(ii + i)->bdaddr, sizeof(name) - 1, name, 0) < 0)
-+                              strcpy(name, "[unknown]");
-+                      phport = sdp_search(addr, HANDSFREE_AGW_PROFILE_ID);
-+                      if (!phport)
-+                              hsport = sdp_search(addr, HEADSET_PROFILE_ID);
-+                      else
-+                              hsport = 0;
-+                      ast_cli(fd, FORMAT2, addr, name, (phport > 0 || hsport > 0) ? "Yes" : "No",
-+                              (phport > 0) ? "Phone" : "Headset", (phport > 0) ? phport : hsport);
-+              }
-+      } else
-+              ast_cli(fd, "No Bluetooth Cell / Mobile devices found.\n");
-+
-+#undef FORMAT1
-+#undef FORMAT2
-+
-+      return RESULT_SUCCESS;
-+}
-+
-+static int handle_cli_mobile_rfcomm(int fd, int argc, char **argv)
-+{
-+      char buf[128];
-+      struct mbl_pvt *pvt = NULL;
-+
-+      if (argc != 4)
-+              return RESULT_SHOWUSAGE;
-+
-+      AST_RWLIST_RDLOCK(&devices);
-+      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+              if (!strcmp(pvt->id, argv[2]))
-+                      break;
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+
-+      if (!pvt || !pvt->connected) {
-+              ast_cli(fd, "Device %s not found.\n", argv[2]);
-+              return RESULT_SUCCESS;
-+      }
-+
-+      snprintf(buf, sizeof(buf), "%s\r", argv[3]);
-+      rfcomm_write(pvt, buf);
-+
-+      return RESULT_SUCCESS;
-+}
-+
-+/*
-+
-+      Dialplan applications implementation
-+
-+*/
-+
-+static int mbl_status_exec(struct ast_channel *ast, void *data)
-+{
-+
-+      struct mbl_pvt *pvt;
-+      char *parse;
-+      int stat;
-+      char status[2];
-+
-+      AST_DECLARE_APP_ARGS(args,
-+              AST_APP_ARG(device);
-+              AST_APP_ARG(variable);
-+      );
-+
-+      if (ast_strlen_zero(data))
-+              return -1;
-+
-+      parse = ast_strdupa(data);
-+
-+      AST_STANDARD_APP_ARGS(args, parse);
-+
-+      if (ast_strlen_zero(args.device) || ast_strlen_zero(args.variable))
-+              return -1;
-+
-+      stat = 1;
-+
-+      AST_RWLIST_RDLOCK(&devices);
-+      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+              if (!strcmp(pvt->id, args.device))
-+                      break;
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+
-+      if (pvt) {
-+              if (pvt->connected)
-+                      stat = 2;
-+              if (pvt->owner)
-+                      stat = 3;
-+      }
-+
-+      snprintf(status, sizeof(status), "%d", stat);
-+      pbx_builtin_setvar_helper(ast, args.variable, status);
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_sendsms_exec(struct ast_channel *ast, void *data)
-+{
-+
-+      struct mbl_pvt *pvt;
-+      char *parse;
-+
-+      AST_DECLARE_APP_ARGS(args,
-+              AST_APP_ARG(device);
-+              AST_APP_ARG(dest);
-+              AST_APP_ARG(message);
-+      );
-+
-+      if (ast_strlen_zero(data))
-+              return -1;
-+
-+      parse = ast_strdupa(data);
-+
-+      AST_STANDARD_APP_ARGS(args, parse);
-+
-+      if (ast_strlen_zero(args.device)) {
-+              ast_log(LOG_ERROR,"NULL device for message -- SMS will not be sent.\n");
-+              return -1;
-+      }
-+
-+      if (ast_strlen_zero(args.dest)) {
-+              ast_log(LOG_ERROR,"NULL destination for message -- SMS will not be sent.\n");
-+              return -1;
-+      }
-+
-+      if (ast_strlen_zero(args.message)) {
-+              ast_log(LOG_ERROR,"NULL Message to be sent -- SMS will not be sent.\n");
-+              return -1;
-+      }
-+
-+      AST_RWLIST_RDLOCK(&devices);
-+      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+              if (!strcmp(pvt->id, args.device))
-+                      break;
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+
-+      if (!pvt) {
-+              ast_log(LOG_ERROR,"Bluetooth device %s wasn't found in the list -- SMS will not be sent.\n", args.device);
-+              return -1;
-+      }
-+
-+      if (!pvt->connected) {
-+              ast_log(LOG_ERROR,"Bluetooth device %s wasn't connected -- SMS will not be sent.\n", args.device);
-+              return -1;
-+      }
-+
-+      if (!pvt->has_sms) {
-+              ast_log(LOG_ERROR,"Bluetooth device %s doesn't handle SMS -- SMS will not be sent.\n", args.device);
-+              return -1;
-+      }
-+
-+      if (pvt->state != MBL_STATE_IDLE) {
-+              ast_log(LOG_ERROR,"Bluetooth device %s isn't IDLE -- SMS will not be sent.\n", args.device);
-+              return -1;
-+      }
-+
-+      ast_copy_string(pvt->dial_number, args.dest, sizeof(pvt->dial_number));
-+      ast_copy_string(pvt->sms_txt, args.message, sizeof(pvt->sms_txt));
-+      pvt->state = MBL_STATE_OUTSMS;
-+
-+      return 0;
-+
-+}
-+
-+/*
-+
-+      Channel Driver callbacks
-+
-+*/
-+
-+static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num)
-+{
-+
-+      struct ast_channel *chn;
-+
-+      if (pipe(pvt->io_pipe) == -1) {
-+              ast_log(LOG_ERROR, "Failed to create io_pipe.\n");
-+              return NULL;
-+      }
-+
-+      if (pvt->sco_socket != -1)
-+              close(pvt->sco_socket);
-+      pvt->sco_socket = -1;
-+      pvt->io_save_len = 0;
-+      pvt->sent_answer = 0;
-+      pvt->skip_frames = 0;
-+      pvt->alignment_count = 0;
-+      pvt->alignment_detection_triggered = 0;
-+      if (pvt->adapter->alignment_detection)
-+              pvt->do_alignment_detection = 1;
-+      else
-+              pvt->do_alignment_detection = 0;
-+      pvt->do_hangup = 1;
-+      chn = ast_channel_alloc(1, state, cid_num, pvt->id, 0, 0, pvt->context, 0, "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);
-+      if (chn) {
-+              chn->tech = &mbl_tech;
-+              chn->nativeformats = prefformat;
-+              chn->rawreadformat = prefformat;
-+              chn->rawwriteformat = prefformat;
-+              chn->writeformat = prefformat;
-+              chn->readformat = prefformat;
-+              chn->tech_pvt = pvt;
-+              chn->fds[0] = pvt->io_pipe[0];
-+              if (state == AST_STATE_RING)
-+                      chn->rings = 1;
-+              ast_string_field_set(chn, language, "en");
-+              pvt->owner = chn;
-+              return chn;
-+      }
-+
-+      return NULL;
-+
-+}
-+
-+static struct ast_channel *mbl_request(const char *type, int format, void *data, int *cause)
-+{
-+
-+      struct ast_channel *chn = NULL;
-+      struct mbl_pvt *pvt;
-+      char *dest_dev = NULL;
-+      char *dest_num = NULL;
-+      int oldformat, group = -1;
-+
-+      if (!data) {
-+              ast_log(LOG_WARNING, "Channel requested with no data\n");
-+              *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
-+              return NULL;
-+      }
-+
-+      oldformat = format;
-+      format &= (AST_FORMAT_SLINEAR);
-+      if (!format) {
-+              ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%d'\n", oldformat);
-+              *cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
-+              return NULL;
-+      }
-+
-+      dest_dev = ast_strdupa((char *)data);
-+
-+      dest_num = strchr(dest_dev, '/');
-+      if (dest_num)
-+              *dest_num++ = 0x00;
-+
-+      if (((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) && ((dest_dev[1] >= '0') && (dest_dev[1] <= '9'))) {
-+              group = atoi(&dest_dev[1]);
-+      }
-+
-+      /* Find requested device and make sure it's connected. */
-+      AST_RWLIST_RDLOCK(&devices);
-+      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+              if (group > -1 && pvt->group == group && pvt->connected && !pvt->owner) {
-+                      break;
-+              } else if (!strcmp(pvt->id, dest_dev)) {
-+                      break;
-+              }
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+      if (!pvt || !pvt->connected || pvt->owner) {
-+              ast_log(LOG_WARNING, "Request to call on device %s which is not connected / already in use.\n", dest_dev);
-+              *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
-+              return NULL;
-+      }
-+
-+      if ((pvt->type == MBL_TYPE_PHONE) && !dest_num) {
-+              ast_log(LOG_WARNING, "Can't determine destination number.\n");
-+              *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
-+              return NULL;
-+      }
-+
-+      chn = mbl_new(AST_STATE_DOWN, pvt, NULL);
-+      if (!chn) {
-+              ast_log(LOG_WARNING, "Unable to allocate channel structure.\n");
-+              *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
-+              return NULL;
-+      }
-+
-+      return chn;
-+
-+}
-+
-+static int mbl_call(struct ast_channel *ast, char *dest, int timeout)
-+{
-+
-+      struct mbl_pvt *pvt;
-+      char *dest_dev = NULL;
-+      char *dest_num = NULL;
-+
-+      dest_dev = ast_strdupa((char *)dest);
-+
-+      pvt = ast->tech_pvt;
-+
-+      if (pvt->type == MBL_TYPE_PHONE) {
-+              dest_num = strchr(dest_dev, '/');
-+              if (!dest_num) {
-+                      ast_log(LOG_WARNING, "Cant determine destination number.\n");
-+                      return -1;
-+              }
-+              *dest_num++ = 0x00;
-+      }
-+
-+      if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
-+              ast_log(LOG_WARNING, "mbl_call called on %s, neither down nor reserved\n", ast->name);
-+              return -1;
-+      }
-+
-+      ast_log(LOG_DEBUG, "Calling %s on %s\n", dest, ast->name);
-+
-+      if (pvt->type == MBL_TYPE_PHONE) {
-+              ast_copy_string(pvt->dial_number, dest_num, sizeof(pvt->dial_number));
-+              pvt->state = MBL_STATE_DIAL;
-+              pvt->dial_timeout = (timeout == 0) ? 30 : timeout;
-+      } else {
-+              pvt->state = MBL_STATE_RING;
-+      }
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_hangup(struct ast_channel *ast)
-+{
-+
-+      struct mbl_pvt *pvt;
-+
-+      if (!ast->tech_pvt) {
-+              ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
-+              return 0;
-+      }
-+      pvt = ast->tech_pvt;
-+
-+      ast_log(LOG_DEBUG, "Hanging up device %s.\n", pvt->id);
-+
-+      ast->fds[0] = -1;
-+      
-+      close(pvt->io_pipe[0]);
-+      close(pvt->io_pipe[1]);
-+
-+      if (pvt->type == MBL_TYPE_HEADSET && pvt->sco_socket != -1) {
-+              close(pvt->sco_socket);
-+              pvt->sco_socket = -1;
-+      }
-+
-+      if ((pvt->state == MBL_STATE_INCOMING || pvt->state == MBL_STATE_OUTGOING || pvt->state == MBL_STATE_DIAL1 || pvt->state == MBL_STATE_RING3) && pvt->type == MBL_TYPE_PHONE) {
-+              if (pvt->do_hangup) {
-+                      rfcomm_write(pvt, "AT+CHUP\r");
-+              }
-+              pvt->state = MBL_STATE_HANGUP;
-+              pvt->hangup_count = 0;
-+      } else
-+              pvt->state = MBL_STATE_IDLE;
-+
-+      pvt->owner = NULL;
-+      ast->tech_pvt = NULL;
-+      ast_setstate(ast, AST_STATE_DOWN);
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_answer(struct ast_channel *ast)
-+{
-+
-+      struct mbl_pvt *pvt;
-+
-+      pvt = ast->tech_pvt;
-+
-+      rfcomm_write(pvt, "ATA\r");
-+
-+      ast_setstate(ast, AST_STATE_UP);
-+
-+      pvt->sent_answer = 1;
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_digit_begin(struct ast_channel *chan, char digit)
-+{
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
-+{
-+
-+      struct mbl_pvt *pvt;
-+      char buf[11];
-+
-+      pvt = ast->tech_pvt;
-+
-+      if (pvt->type == MBL_TYPE_HEADSET)
-+              return 0;
-+
-+      ast_log(LOG_DEBUG, "Dialed %c\n", digit);
-+
-+      switch(digit) {
-+      case '0':
-+      case '1':
-+      case '2':
-+      case '3':
-+      case '4':
-+      case '5':
-+      case '6':
-+      case '7':
-+      case '8':
-+      case '9':
-+      case '*':
-+      case '#':
-+              snprintf(buf, sizeof(buf), "AT+VTS=%c\r", digit);
-+              rfcomm_write(pvt, buf);
-+              break;
-+      default:
-+              ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
-+              return -1;
-+      }
-+
-+      return 0;
-+
-+}
-+
-+static struct ast_frame *mbl_read(struct ast_channel *ast)
-+{
-+
-+      struct mbl_pvt *pvt = ast->tech_pvt;
-+      struct ast_frame *f;
-+      int r;
-+
-+      //ast_log(LOG_DEBUG, "*** mbl_read()\n");
-+
-+      if (!pvt->owner) {
-+              return &ast_null_frame;
-+      }
-+      memset(&pvt->fr, 0x00, sizeof(struct ast_frame));
-+      pvt->fr.frametype = AST_FRAME_VOICE;
-+      pvt->fr.subclass = DEVICE_FRAME_FORMAT;
-+      pvt->fr.datalen = CHANNEL_FRAME_SIZE;
-+      pvt->fr.samples = CHANNEL_FRAME_SIZE / 2;
-+      pvt->fr.src = "Mobile";
-+      pvt->fr.offset = AST_FRIENDLY_OFFSET;
-+      pvt->fr.mallocd = 0;
-+      pvt->fr.delivery.tv_sec = 0;
-+      pvt->fr.delivery.tv_usec = 0;
-+      pvt->fr.data = pvt->io_buf + AST_FRIENDLY_OFFSET;
-+
-+      if ((r = read(pvt->io_pipe[0], pvt->fr.data, CHANNEL_FRAME_SIZE)) != CHANNEL_FRAME_SIZE) {
-+              if (r == -1) {
-+                      ast_log(LOG_ERROR, "read error %d\n", errno);
-+                      return &ast_null_frame;
-+              } else {
-+                      pvt->fr.datalen = r;
-+                      pvt->fr.samples = r / 2;
-+              }
-+      }
-+
-+      f = ast_dsp_process(0, pvt->dsp, &pvt->fr);
-+      if (f && (f->frametype == AST_FRAME_DTMF_END)) {
-+              pvt->fr.frametype = AST_FRAME_DTMF_END;
-+              pvt->fr.subclass = f->subclass;
-+      }
-+
-+      return &pvt->fr;
-+
-+}
-+
-+static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)
-+{
-+
-+      struct mbl_pvt *pvt = ast->tech_pvt;
-+      int i, r, io_need, num_frames;
-+      char *pfr, buf[DEVICE_FRAME_SIZE];
-+
-+      //ast_log(LOG_DEBUG, "*** mbl_write\n");
-+
-+      if (frame->frametype != AST_FRAME_VOICE) {
-+              return 0;
-+      }
-+
-+      io_need = 0;
-+      if (pvt->io_save_len > 0) {
-+              io_need = DEVICE_FRAME_SIZE - pvt->io_save_len;
-+              memcpy(pvt->io_save_buf + pvt->io_save_len, frame->data, io_need);
-+              sco_write(pvt->sco_socket, pvt->io_save_buf, DEVICE_FRAME_SIZE);
-+              if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE))) {
-+                      if (pvt->do_alignment_detection)
-+                              do_alignment_detection(pvt, buf, r);
-+                      if (ast->_state == AST_STATE_UP)        /* Dont queue the audio in the pipe if the call is not up yet. just toss it. */
-+                              sco_write(pvt->io_pipe[1], buf, r);
-+              }
-+      }
-+
-+      num_frames = (frame->datalen - io_need) / DEVICE_FRAME_SIZE;
-+      pfr = frame->data + io_need;
-+
-+      for (i=0; i<num_frames; i++) {
-+              sco_write(pvt->sco_socket, pfr, DEVICE_FRAME_SIZE);
-+              if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE))) {
-+                      if (pvt->do_alignment_detection)
-+                              do_alignment_detection(pvt, buf, r);
-+                      if (ast->_state == AST_STATE_UP)
-+                              sco_write(pvt->io_pipe[1], buf, r);
-+              }
-+              pfr += DEVICE_FRAME_SIZE;
-+      }
-+
-+      pvt->io_save_len = (frame->datalen - io_need) - (num_frames * DEVICE_FRAME_SIZE);
-+      if (pvt->io_save_len > 0) {
-+              memcpy(pvt->io_save_buf, pfr, pvt->io_save_len);
-+      }
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
-+{
-+
-+      struct mbl_pvt *pvt = oldchan->tech_pvt;
-+
-+      if (pvt && pvt->owner == oldchan)
-+              pvt->owner = newchan;
-+
-+      return 0;
-+
-+}
-+
-+static int mbl_devicestate(void *data)
-+{
-+
-+      char *device;
-+      int res = AST_DEVICE_INVALID;
-+      struct mbl_pvt *pvt;
-+
-+      device = ast_strdupa(S_OR(data, ""));
-+
-+      ast_log(LOG_DEBUG, "Checking device state for device %s\n", device);
-+
-+      AST_RWLIST_RDLOCK(&devices);
-+      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+              if (!strcmp(pvt->id, device))
-+                      break;
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+
-+      if (pvt) {
-+              if (pvt->connected) {
-+                      if (pvt->owner)
-+                              res = AST_DEVICE_INUSE;
-+                      else
-+                              res = AST_DEVICE_NOT_INUSE;
-+              }
-+      }
-+
-+      return res;
-+
-+}
-+
-+/*
-+
-+      Callback helpers
-+
-+*/
-+
-+/*
-+
-+      do_alignment_detection()
-+
-+      This routine attempts to detect where we get misaligned sco audio data from the bluetooth adaptor.
-+
-+      Its enabled by alignmentdetect=yes under the adapter entry in mobile.conf
-+
-+      Some adapters suffer a problem where occasionally they will byte shift the audio stream one byte to the right.
-+      The result is static or white noise on the inbound (from the adapter) leg of the call.
-+      This is characterised by a sudden jump in magnitude of the value of the 16 bit samples.
-+
-+      Here we look at the first 4 48 byte frames. We average the absolute values of each sample in the frame,
-+      then average the sum of the averages of frames 1, 2, and 3.
-+      Frame zero is usually zero.
-+      If the end result > 100, and it usually is if we have the problem, set a flag and compensate by shifting the bytes
-+      for each subsequent frame during the call.
-+
-+      If the result is <= 100 then clear the flag so we dont come back in here...
-+
-+      This seems to work OK....
-+
-+*/
-+
-+static void do_alignment_detection(struct mbl_pvt *pvt, char *buf, int buflen)
-+{
-+
-+      int i;
-+      short a, *s;
-+      char *p;
-+
-+      if (pvt->alignment_detection_triggered) {
-+              for (i=buflen, p=buf+buflen-1; i>0; i--, p--)
-+                      *p = *(p-1);
-+              *(p+1) = 0;
-+              return;
-+      }
-+
-+      if (pvt->alignment_count < 4) {
-+              s = (short *)buf;
-+              for (i=0, a=0; i<buflen/2; i++) {
-+                      a += *s++;
-+                      a /= i+1;
-+              }
-+              pvt->alignment_samples[pvt->alignment_count++] = a;
-+              return;
-+      }
-+
-+      ast_log(LOG_DEBUG, "Alignment Detection result is [%-d %-d %-d %-d]\n", pvt->alignment_samples[0], pvt->alignment_samples[1], pvt->alignment_samples[2], pvt->alignment_samples[3]);
-+
-+      a = abs(pvt->alignment_samples[1]) + abs(pvt->alignment_samples[2]) + abs(pvt->alignment_samples[3]);
-+      a /= 3;
-+      if (a > 100) {
-+              pvt->alignment_detection_triggered = 1;
-+              ast_log(LOG_DEBUG, "Alignment Detection Triggered.\n");
-+      } else
-+              pvt->do_alignment_detection = 0;
-+
-+}
-+
-+/*
-+
-+      rfcomm helpers
-+
-+*/
-+
-+static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel) {
-+
-+      struct sockaddr_rc addr;
-+      int s;
-+
-+      if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
-+              ast_log(LOG_DEBUG, "socket() failed (%d).\n", errno);
-+              return -1;
-+      }
-+
-+      memset(&addr, 0, sizeof(addr));
-+      addr.rc_family = AF_BLUETOOTH;
-+      bacpy(&addr.rc_bdaddr, &src);
-+      addr.rc_channel = (uint8_t) 1;
-+      if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-+              ast_log(LOG_DEBUG, "bind() failed (%d).\n", errno);
-+              close(s);
-+              return -1;
-+      }
-+
-+      memset(&addr, 0, sizeof(addr));
-+      addr.rc_family = AF_BLUETOOTH;
-+      bacpy(&addr.rc_bdaddr, &dst);
-+      addr.rc_channel = remote_channel;
-+      if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-+              ast_log(LOG_DEBUG, "connect() failed (%d).\n", errno);
-+              close(s);
-+              return -1;
-+      }
-+
-+      return s;
-+
-+}
-+
-+static int rfcomm_write(struct mbl_pvt *pvt, char *buf)
-+{
-+
-+      char *p;
-+      ssize_t num_write;
-+      int len;
-+
-+      ast_log(LOG_DEBUG, "rfcomm_write() (%s) [%s]\n", pvt->id, buf);
-+      len = strlen(buf);
-+      p = buf;
-+      while (len > 0) {
-+              if ((num_write = write(pvt->rfcomm_socket, p, len)) == -1) {
-+                      ast_log(LOG_DEBUG, "rfcomm_write() error [%d]\n", errno);
-+                      return 0;
-+              }
-+              len -= num_write;
-+              p += num_write;
-+      }
-+
-+      return 1;
-+
-+}
-+
-+/*
-+
-+      Here we need to return complete '\r' terminated single responses to the devices monitor thread, or
-+      a timeout if nothing is available.
-+      The rfcomm connection to the device is asynchronous, so there is no guarantee that responses will
-+      be returned in a single read() call. We handle this by buffering the input and returning one response
-+      per call, or a timeout if nothing is available.
-+
-+*/
-+
-+static int rfcomm_read(struct mbl_pvt *pvt, char *buf, char flush, int timeout)
-+{
-+
-+      int sel, rlen, slen;
-+      fd_set rfds;
-+      struct timeval tv;
-+      char *p;
-+
-+      if (!flush) {
-+              if ((p = strchr(pvt->rfcomm_buf, '\r'))) {
-+                      *p++ = 0x00;
-+                      if (*p == '\n')
-+                              p++;
-+                      memmove(buf, pvt->rfcomm_buf, strlen(pvt->rfcomm_buf));
-+                      *(buf + strlen(pvt->rfcomm_buf)) = 0x00;
-+                      memmove(pvt->rfcomm_buf, p, strlen(p));
-+                      *(pvt->rfcomm_buf+strlen(p)) = 0x00;
-+                      return 1;
-+              }
-+      } else {
-+              pvt->rfcomm_buf[0] = 0x00;
-+      }
-+
-+      FD_ZERO(&rfds);
-+      FD_SET(pvt->rfcomm_socket, &rfds);
-+
-+      tv.tv_sec = timeout;
-+      tv.tv_usec = 0;
-+
-+      if ((sel = select(pvt->rfcomm_socket + 1, &rfds, NULL, NULL, &tv)) > 0) {
-+              if (FD_ISSET(pvt->rfcomm_socket, &rfds)) {
-+                      slen = strlen(pvt->rfcomm_buf);
-+                      rlen = read(pvt->rfcomm_socket, pvt->rfcomm_buf + slen, sizeof(pvt->rfcomm_buf) - slen - 1);
-+                      if (rlen > 0) {
-+                              pvt->rfcomm_buf[slen+rlen] = 0x00;
-+                              if ((p = strchr(pvt->rfcomm_buf, '\r'))) {
-+                                      *p++ = 0x00;
-+                                      if (*p == '\n')
-+                                              p++;
-+                                      memmove(buf, pvt->rfcomm_buf, strlen(pvt->rfcomm_buf));
-+                                      *(buf + strlen(pvt->rfcomm_buf)) = 0x00;
-+                                      memmove(pvt->rfcomm_buf, p, strlen(p));
-+                                      *(pvt->rfcomm_buf+strlen(p)) = 0x00;
-+                                      return 1;
-+                              }
-+                      } else
-+                              return rlen;
-+              }
-+      } else if (sel == 0) { /* timeout */
-+              return 0;
-+      }
-+
-+      return 1;
-+
-+}
-+
-+/*
-+
-+      sco helpers
-+
-+*/
-+
-+static int sco_connect(bdaddr_t src, bdaddr_t dst)
-+{
-+
-+      struct sockaddr_sco addr;
-+      int s;
-+
-+      if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
-+              ast_log(LOG_DEBUG, "socket() failed (%d).\n", errno);
-+              return -1;
-+      }
-+
-+      memset(&addr, 0, sizeof(addr));
-+      addr.sco_family = AF_BLUETOOTH;
-+      bacpy(&addr.sco_bdaddr, &src);
-+      if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-+              ast_log(LOG_DEBUG, "bind() failed (%d).\n", errno);
-+              close(s);
-+              return -1;
-+      }
-+
-+      memset(&addr, 0, sizeof(addr));
-+      addr.sco_family = AF_BLUETOOTH;
-+      bacpy(&addr.sco_bdaddr, &dst);
-+
-+      if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-+              ast_log(LOG_DEBUG, "sco connect() failed (%d).\n", errno);
-+              close(s);
-+              return -1;
-+      }
-+
-+      return s;
-+
-+}
-+
-+static int sco_write(int s, char *buf, int len)
-+{
-+
-+      int r;
-+
-+      if (s == -1) {
-+              ast_log(LOG_DEBUG, "sco_write() not ready\n");
-+              return 0;
-+      }
-+
-+      ast_log(LOG_DEBUG, "sco_write()\n");
-+
-+      r = write(s, buf, len);
-+      if (r == -1) {
-+              ast_log(LOG_DEBUG, "sco write error %d\n", errno);
-+              return 0;
-+      }
-+
-+      return 1;
-+
-+}
-+
-+static int sco_read(int s, char *buf, int len)
-+{
-+
-+      int r;
-+
-+      if (s == -1) {
-+              ast_log(LOG_DEBUG, "sco_read() not ready\n");
-+              return 0;
-+      }
-+
-+      ast_log(LOG_DEBUG, "sco_read()\n");
-+
-+      r = read(s, buf, len);
-+      if (r == -1) {
-+              ast_log(LOG_DEBUG, "sco_read() error %d\n", errno);
-+              return 0;
-+      }
-+
-+      return r;
-+
-+}
-+
-+/*
-+
-+      sdp helpers
-+
-+*/
-+
-+static int sdp_search(char *addr, int profile)
-+{
-+
-+      sdp_session_t *session = 0;
-+      bdaddr_t bdaddr;
-+      uuid_t svc_uuid;
-+      uint32_t range = 0x0000ffff;
-+      sdp_list_t *response_list, *search_list, *attrid_list;
-+      int status, port;
-+      sdp_list_t *proto_list;
-+      sdp_record_t *sdprec;
-+
-+      str2ba(addr, &bdaddr);
-+      port = 0;
-+      session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);
-+      if (!session) {
-+              ast_log(LOG_DEBUG, "sdp_connect() failed on device %s.\n", addr);
-+              return 0;
-+      }
-+
-+      sdp_uuid32_create(&svc_uuid, profile);
-+      search_list = sdp_list_append(0, &svc_uuid);
-+      attrid_list = sdp_list_append(0, &range);
-+      response_list = 0x00;
-+      status = sdp_service_search_attr_req(session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
-+      if (status == 0) {
-+              if (response_list) {
-+                      sdprec = (sdp_record_t *) response_list->data;
-+                      proto_list = 0x00;
-+                      if (sdp_get_access_protos(sdprec, &proto_list) == 0) {
-+                              port = sdp_get_proto_port(proto_list, RFCOMM_UUID);
-+                              sdp_list_free(proto_list, 0);
-+                      }
-+                      sdp_record_free(sdprec);
-+                      sdp_list_free(response_list, 0);
-+              } else
-+                      ast_log(LOG_DEBUG, "No responses returned for device %s.\n", addr);
-+      } else
-+              ast_log(LOG_DEBUG, "sdp_service_search_attr_req() failed on device %s.\n", addr);
-+
-+      sdp_list_free(search_list, 0);
-+      sdp_list_free(attrid_list, 0);
-+      sdp_close(session);
-+
-+      return port;
-+
-+}
-+
-+static sdp_session_t *sdp_register(void)
-+{
-+
-+      uint32_t service_uuid_int[] = {0, 0, 0, GENERIC_AUDIO_SVCLASS_ID};
-+      uint8_t rfcomm_channel = 1;
-+      const char *service_name = "Asterisk PABX";
-+      const char *service_dsc = "Asterisk PABX";
-+      const char *service_prov = "Asterisk";
-+
-+      uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class1_uuid, svc_class2_uuid;
-+      sdp_list_t  *l2cap_list = 0, *rfcomm_list = 0, *root_list = 0, *proto_list = 0, *access_proto_list = 0, *svc_uuid_list = 0;
-+      sdp_data_t *channel = 0;
-+
-+      int err = 0;
-+      sdp_session_t *session = 0;
-+
-+      sdp_record_t *record = sdp_record_alloc();
-+
-+      sdp_uuid128_create(&svc_uuid, &service_uuid_int);
-+      sdp_set_service_id(record, svc_uuid);
-+
-+      sdp_uuid32_create(&svc_class1_uuid, GENERIC_AUDIO_SVCLASS_ID);
-+      sdp_uuid32_create(&svc_class2_uuid, HEADSET_PROFILE_ID);
-+
-+      svc_uuid_list = sdp_list_append(0, &svc_class1_uuid);
-+      svc_uuid_list = sdp_list_append(svc_uuid_list, &svc_class2_uuid);
-+      sdp_set_service_classes(record, svc_uuid_list);
-+
-+      sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
-+      root_list = sdp_list_append(0, &root_uuid);
-+      sdp_set_browse_groups( record, root_list );
-+
-+      sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
-+      l2cap_list = sdp_list_append(0, &l2cap_uuid);
-+      proto_list = sdp_list_append(0, l2cap_list);
-+
-+      sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
-+      channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
-+      rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
-+      sdp_list_append(rfcomm_list, channel);
-+      sdp_list_append(proto_list, rfcomm_list);
-+
-+      access_proto_list = sdp_list_append(0, proto_list);
-+      sdp_set_access_protos(record, access_proto_list);
-+
-+      sdp_set_info_attr(record, service_name, service_prov, service_dsc);
-+
-+      if (!(session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY)))
-+              ast_log(LOG_WARNING, "Failed to connect sdp and create session.\n");
-+      else
-+              err = sdp_record_register(session, record, 0);
-+
-+      sdp_data_free(channel);
-+      sdp_list_free(rfcomm_list, 0);
-+      sdp_list_free(root_list, 0);
-+      sdp_list_free(access_proto_list, 0);
-+      sdp_list_free(svc_uuid_list, 0);
-+
-+      return session;
-+
-+}
-+
-+/*
-+
-+      Thread routines
-+
-+*/
-+
-+static void *do_monitor_phone(void *data)
-+{
-+
-+      struct mbl_pvt *pvt = (struct mbl_pvt *)data;
-+      struct ast_channel *chn;
-+      char monitor = 1;
-+      char buf[256];
-+      char cid_num[AST_MAX_EXTENSION], *pcids, *pcide;
-+      int s, t, i, smsi;
-+      int group, group2;
-+      int callp = 0, callsetupp;
-+      char brsf, nsmode, *p, *p1;
-+      char sms_src[13];
-+      char sms_txt[160];
-+
-+      brsf = nsmode = 0;
-+
-+      if (!rfcomm_write(pvt, "AT+BRSF=4\r"))
-+              monitor = 0;
-+
-+      while (monitor) {
-+
-+              if (pvt->state == MBL_STATE_DIAL1)
-+                      t = pvt->dial_timeout;
-+              else if (pvt->state == MBL_STATE_HANGUP)
-+                      t = 2;
-+              else if (pvt->state == MBL_STATE_OUTSMS1)
-+                      t = 2;
-+              else if (pvt->state == MBL_STATE_OUTSMS2)
-+                      t = 10;
-+              else
-+                      t = 1;
-+
-+              s = rfcomm_read(pvt, buf, 0, t);
-+
-+              if ((s > 0) && (buf[0] != 0x0) && (buf[0] != '\r')) {
-+                      ast_log(LOG_DEBUG, "rfcomm_read() (%s) [%s]\n", pvt->id, buf);
-+                      switch (pvt->state) {
-+                      case MBL_STATE_INIT:
-+                              if (strstr(buf, "+BRSF:")) {
-+                                      brsf = 1;
-+                              } else if (strstr(buf, "ERROR") && !nsmode) {   /* Hmmm, Non-Standard Phone, just continue */
-+                                      rfcomm_write(pvt, "AT+CIND=?\r");
-+                                      pvt->state++;
-+                                      nsmode = 1;
-+                              } else if (strstr(buf, "OK") && brsf) {
-+                                      if (pvt->blackberry) {
-+                                              rfcomm_write(pvt, "AT+CMER=3,0,0,1\r");
-+                                              pvt->state = MBL_STATE_INIT3;
-+                                      } else {
-+                                              rfcomm_write(pvt, "AT+CIND=?\r");
-+                                              pvt->state++;
-+                                      }
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT1:
-+                              if (strstr(buf, "+CIND:")) {
-+                                      group = callp = callsetupp = 0;
-+                                      group2 = 1;
-+                                      for (i=0; i<strlen(buf); i++) {
-+                                              if (buf[i] == '(')
-+                                                      group++;
-+                                              if (buf[i] == ')') {
-+                                                      group--;
-+                                                      if (group == 0)
-+                                                              group2++;
-+                                              }
-+                                              if (strstr(buf+i, "\"call\""))
-+                                                      callp = group2;
-+                                              if (strstr(buf+i, "\"call_setup\""))
-+                                                      callsetupp = group2;
-+                                              if (strstr(buf+i, "\"callsetup\""))
-+                                                      callsetupp = group2;
-+                                      }
-+                                      snprintf(pvt->ciev_call_0, sizeof(pvt->ciev_call_0), "%d,0", callp);
-+                                      snprintf(pvt->ciev_call_1, sizeof(pvt->ciev_call_1), "%d,1", callp);
-+                                      snprintf(pvt->ciev_callsetup_0, sizeof(pvt->ciev_callsetup_0), "%d,0", callsetupp);
-+                                      snprintf(pvt->ciev_callsetup_1, sizeof(pvt->ciev_callsetup_1), "%d,1", callsetupp);
-+                                      snprintf(pvt->ciev_callsetup_2, sizeof(pvt->ciev_callsetup_2), "%d,2", callsetupp);
-+                                      snprintf(pvt->ciev_callsetup_3, sizeof(pvt->ciev_callsetup_3), "%d,3", callsetupp);
-+                                      if (callsetupp == 0) /* This phone has no call setup indication!! ... */
-+                                              pvt->no_callsetup = 1;
-+                                      ast_log(LOG_DEBUG, "CIEV_CALL=%d CIEV_CALLSETUP=%d\n", callp, callsetupp);
-+                              }
-+                              if (strstr(buf, "OK")) {
-+                                      rfcomm_write(pvt, "AT+CIND?\r");
-+                                      pvt->state++;
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT2:
-+                              if ((p = strstr(buf, "+CIND:"))) {
-+                                      p += 5;
-+                                      if (*(p+(callp*2)) == '1') {
-+                                              ast_verbose(VERBOSE_PREFIX_3 "Bluetooth Device %s has a call in progress - delaying connection.\n", pvt->id);
-+                                              monitor = 0;
-+                                      }
-+                              } else if (strstr(buf, "OK")) {
-+                                      if (pvt->blackberry) {
-+                                              rfcomm_write(pvt, "AT+CLIP=1\r");
-+                                              pvt->state = MBL_STATE_INIT4;
-+                                      } else {
-+                                              rfcomm_write(pvt, "AT+CMER=3,0,0,1\r");
-+                                              pvt->state++;
-+                                      }
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT3:
-+                              if (strstr(buf, "OK")) {
-+                                      if (pvt->blackberry) {
-+                                              rfcomm_write(pvt, "AT+CIND=?\r");
-+                                              pvt->state = MBL_STATE_INIT1;
-+                                      } else {
-+                                              rfcomm_write(pvt, "AT+CLIP=1\r");
-+                                              pvt->state++;
-+                                      }
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT4:
-+                              if (strstr(buf, "OK")) {
-+                                      rfcomm_write(pvt, "AT+VGS=15\r");
-+                                      pvt->state++;
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT5:
-+                              if (strstr(buf, "OK")) {
-+                                      rfcomm_write(pvt, "AT+CMGF=1\r");
-+                                      pvt->state++;
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT6:
-+                              if (strstr(buf, "ERROR")) {     /* No SMS Support ! */
-+                                      pvt->state = MBL_STATE_PREIDLE;
-+                              } else if (strstr(buf, "OK")) {
-+                                      rfcomm_write(pvt, "AT+CNMI=2,1,0,1,0\r");
-+                                      pvt->state++;
-+                              }
-+                              break;
-+                      case MBL_STATE_INIT7:
-+                              if (strstr(buf, "OK")) {        /* We have SMS Support */
-+                                      pvt->has_sms = 1;
-+                                      pvt->state = MBL_STATE_PREIDLE;
-+                              } else if (strstr(buf, "ERROR")) {
-+                                      pvt->has_sms = 0;
-+                                      pvt->state = MBL_STATE_PREIDLE;
-+                              }
-+                              break;
-+                      case MBL_STATE_PREIDLE: /* Nothing handled here, wait for timeout, then off we go... */
-+                              break;
-+                      case MBL_STATE_IDLE:
-+                              ast_log(LOG_DEBUG, "Device %s [%s]\n", pvt->id, buf);
-+                              if (strstr(buf, "RING")) {
-+                                      pvt->state = MBL_STATE_RING;
-+                              } else if (strstr(buf, "+CIEV:")) {
-+                                      if (strstr(buf, pvt->ciev_callsetup_3)) {       /* User has dialed out on handset */
-+                                              monitor = 0;                            /* We disconnect now, as he is    */
-+                                      }                                               /* probably leaving BT range...   */
-+                              }
-+                              break;
-+                      case MBL_STATE_DIAL: /* Nothing handled here, we need to wait for a timeout */
-+                              break;
-+                      case MBL_STATE_DIAL1:
-+                              if (strstr(buf, "OK")) {
-+                                      if (pvt->no_callsetup) {
-+                                              ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
-+                                      } else {
-+                                              ast_setstate(pvt->owner, AST_STATE_RINGING);
-+                                      }
-+                                      pvt->state = MBL_STATE_OUTGOING;
-+                              }
-+                              break;
-+                      case MBL_STATE_OUTGOING:
-+                              if (strstr(buf, "+CIEV")) {
-+                                      if (strstr(buf, pvt->ciev_call_0)) {                            /* call was hung up */
-+                                              pvt->do_hangup = 0;
-+                                              ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                                      } else if (strstr(buf, pvt->ciev_callsetup_3)) {                /* b-party ringing */
-+                                              ast_queue_control(pvt->owner, AST_CONTROL_RINGING);
-+                                      } else if (strstr(buf, pvt->ciev_call_1) && !pvt->no_callsetup) { /* b-party answer */
-+                                              ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
-+                                      }
-+                              }
-+                              break;
-+                      case MBL_STATE_RING:
-+                              cid_num[0] = 0x00;
-+                              if ((pcids = strstr(buf, "+CLIP:"))) {
-+                                      if ((pcids = strchr(pcids, '"'))) {
-+                                              if ((pcide = strchr(pcids+1, '"'))) {
-+                                                      strncpy(cid_num, pcids+1, pcide - pcids - 1);
-+                                                      cid_num[pcide - pcids - 1] = 0x00;
-+                                              }
-+                                      }
-+                                      chn = mbl_new(AST_STATE_RING, pvt, cid_num);
-+                                      if (chn) {
-+                                              if (ast_pbx_start(chn)) {
-+                                                      ast_log(LOG_ERROR, "Unable to start pbx on incoming call.\n");
-+                                                      ast_hangup(chn);
-+                                              } else
-+                                                      pvt->state = MBL_STATE_RING3;
-+                                      } else {
-+                                              ast_log(LOG_ERROR, "Unable to allocate channel for incoming call.\n");
-+                                              rfcomm_write(pvt, "AT+CHUP\r");
-+                                              pvt->state = MBL_STATE_IDLE;
-+                                      }
-+                              }
-+                              break;
-+                      case MBL_STATE_RING2:
-+                              chn = mbl_new(AST_STATE_RING, pvt, cid_num);
-+                              if (chn) {
-+                                      if (ast_pbx_start(chn)) {
-+                                              ast_log(LOG_ERROR, "Unable to start pbx on incoming call.\n");
-+                                              ast_hangup(chn);
-+                                      } else
-+                                              pvt->state = MBL_STATE_RING3;
-+                              } else {
-+                                      ast_log(LOG_ERROR, "Unable to allocate channel for incoming call.\n");
-+                                      rfcomm_write(pvt, "AT+CHUP\r");
-+                                      pvt->state = MBL_STATE_IDLE;
-+                              }
-+                              break;
-+                      case MBL_STATE_RING3:
-+                              if (strstr(buf, "+CIEV")) {
-+                                      if (strstr(buf, pvt->ciev_call_1)) {
-+                                              if (pvt->sent_answer) { /* We answered */
-+                                                      pvt->state = MBL_STATE_INCOMING;
-+                                              } else {                /* User answered on handset!, disconnect */
-+                                                      pvt->state = MBL_STATE_IDLE;
-+                                                      if (pvt->sco_socket > -1)
-+                                                              close(pvt->sco_socket);
-+                                                      ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                                              }
-+                                      }
-+                                      if ((strstr(buf, pvt->ciev_callsetup_0) || strstr(buf, pvt->ciev_call_0))) { /* Caller disconnected */
-+                                              ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                                      }
-+                              } 
-+                              break;
-+                      case MBL_STATE_INCOMING:
-+                              if (strstr(buf, "+CIEV")) {
-+                                      if (strstr(buf, pvt->ciev_call_0)) {
-+                                              pvt->do_hangup = 0;
-+                                              ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                                      }
-+                              }
-+                              break;
-+                      case MBL_STATE_HANGUP:
-+                              if (strstr(buf, "OK") || strstr(buf, pvt->ciev_call_0)) {
-+                                      close(pvt->sco_socket);
-+                                      pvt->sco_socket = -1;
-+                                      pvt->state = MBL_STATE_IDLE;
-+                              }
-+                              break;
-+                      case MBL_STATE_INSMS:
-+                              if (strstr(buf, "+CMGR:")) {
-+                                      memset(sms_src, 0x00, sizeof(sms_src));
-+                                      if ((p = strchr(buf, ','))) {
-+                                              if (*(++p) == '"')
-+                                                      p++;
-+                                              if ((p1 = strchr(p, ','))) {
-+                                                      if (*(--p1) == '"')
-+                                                              p1--;
-+                                                      memset(sms_src, 0x00, sizeof(sms_src));
-+                                                      strncpy(sms_src, p, p1 - p + 1);
-+                                              }
-+                                      }
-+                              } else if (strstr(buf, "OK")) {
-+                                      chn = mbl_new(AST_STATE_DOWN, pvt, NULL);
-+                                      strcpy(chn->exten, "sms");
-+                                      pbx_builtin_setvar_helper(chn, "SMSSRC", sms_src);
-+                                      pbx_builtin_setvar_helper(chn, "SMSTXT", sms_txt);
-+                                      if (ast_pbx_start(chn))
-+                                              ast_log(LOG_ERROR, "Unable to start pbx on incoming sms.\n");
-+                                      pvt->state = MBL_STATE_IDLE;
-+                              } else {
-+                                      ast_copy_string(sms_txt, buf, sizeof(sms_txt));
-+                              }
-+                              break;
-+                      case MBL_STATE_OUTSMS:
-+                              break;
-+                      case MBL_STATE_OUTSMS1:
-+                              break;
-+                      case MBL_STATE_OUTSMS2:
-+                              if (strstr(buf, "OK")) {
-+                                      pvt->state = MBL_STATE_IDLE;
-+                              }
-+                              break;
-+                      }
-+                      /* Unsolicited responses */
-+
-+                      if (strstr(buf, "+CMTI:")) {    /* SMS Incoming... */
-+                              if ((p = strchr(buf, ','))) {
-+                                      p++;
-+                                      smsi = atoi(p);
-+                                      if (smsi > 0) {
-+                                              snprintf(buf, sizeof(buf), "AT+CMGR=%d\r", smsi);
-+                                              rfcomm_write(pvt, buf);
-+                                              pvt->state = MBL_STATE_INSMS;
-+                                      }
-+                              }
-+                      }
-+
-+              } else if (s == 0) { /* Timeouts */
-+                      if (pvt->state == MBL_STATE_INIT2) { /* Some devices dont respond to AT+CIND? properly. RIM Blackberry 4 example */
-+                              pvt->state++;
-+                              rfcomm_write(pvt, "AT+CMER=3,0,0,1\r");
-+                      } else if (pvt->state == MBL_STATE_INIT3) { /* Some devices dont respond to AT+CMER=3,0,0,1 properly. VK 2020 for example */
-+                              pvt->state++;
-+                              rfcomm_write(pvt, "AT+CLIP=1\r");
-+                      } else if (pvt->state == MBL_STATE_PREIDLE) {
-+                              pvt->connected = 1;
-+                              ast_verbose(VERBOSE_PREFIX_3 "Bluetooth Device %s initialised and ready.\n", pvt->id);
-+                              pvt->state = MBL_STATE_IDLE;
-+                      } else if (pvt->state == MBL_STATE_DIAL) {
-+                              snprintf(buf, sizeof(buf), "ATD%s;\r", pvt->dial_number);
-+                              if (!rfcomm_write(pvt, buf)) {
-+                                      ast_log(LOG_ERROR, "Dial failed on %s state %d\n", pvt->owner->name, pvt->state);
-+                                      ast_queue_control(pvt->owner, AST_CONTROL_CONGESTION);
-+                                      pvt->state = MBL_STATE_IDLE;
-+                              } else {
-+                                      pvt->state = MBL_STATE_DIAL1;
-+                              }
-+                      } else if (pvt->state == MBL_STATE_DIAL1) {
-+                              ast_log(LOG_ERROR, "Dial failed on %s state %d\n", pvt->owner->name, pvt->state);
-+                              ast_queue_control(pvt->owner, AST_CONTROL_CONGESTION);
-+                              ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                              pvt->state = MBL_STATE_IDLE;
-+                      } else if (pvt->state == MBL_STATE_RING) { /* No CLIP?, bump it */
-+                              pvt->state = MBL_STATE_RING2;
-+                      } else if (pvt->state == MBL_STATE_HANGUP) {
-+                              if (pvt->do_hangup) {
-+                                      if (pvt->hangup_count == 6) {
-+                                              ast_log(LOG_DEBUG, "Device %s failed to hangup after 6 tries, disconnecting.\n", pvt->id);
-+                                              monitor = 0;
-+                                      }
-+                                      rfcomm_write(pvt, "AT+CHUP\r");
-+                                      pvt->hangup_count++;
-+                              } else
-+                                      pvt->state = MBL_STATE_IDLE;
-+                      } else if (pvt->state == MBL_STATE_OUTSMS) {
-+                              snprintf(buf, sizeof(buf), "AT+CMGS=\"%s\"\r", pvt->dial_number);
-+                              rfcomm_write(pvt, buf);
-+                              pvt->state = MBL_STATE_OUTSMS1;
-+                      } else if (pvt->state == MBL_STATE_OUTSMS1) {
-+                              if (pvt->rfcomm_buf[0] == '>') {
-+                                      snprintf(buf, sizeof(buf), "%s%c", pvt->sms_txt, 0x1a);
-+                                      rfcomm_write(pvt, buf);
-+                                      pvt->state = MBL_STATE_OUTSMS2;
-+                              } else {
-+                                      ast_log(LOG_ERROR, "Failed to send SMS to %s on device %s\n", pvt->dial_number, pvt->id);
-+                                      pvt->state = MBL_STATE_IDLE;
-+                              }
-+                      } else if (pvt->state == MBL_STATE_OUTSMS2) {
-+                              ast_log(LOG_ERROR, "Failed to send SMS to %s on device %s\n", pvt->dial_number, pvt->id);
-+                              pvt->state = MBL_STATE_IDLE;
-+                      }
-+              } else if (s == -1) {
-+                      if (option_verbose > 2)
-+                              ast_verbose(VERBOSE_PREFIX_3  "Bluetooth Device %s has disconnected, reason (%d).\n", pvt->id, errno); 
-+                      monitor = 0;
-+              }
-+
-+      }
-+
-+      if (pvt->rfcomm_socket > -1)
-+              close(pvt->rfcomm_socket);
-+      if (pvt->sco_socket > -1)
-+              close(pvt->sco_socket);
-+      pvt->sco_socket = -1;
-+      pvt->connected = 0;
-+      pvt->monitor_thread = AST_PTHREADT_NULL;
-+
-+      pthread_cancel(pvt->sco_listener_thread);
-+      pthread_join(pvt->sco_listener_thread, NULL);
-+      pvt->sco_listener_thread = AST_PTHREADT_NULL;
-+
-+      close(pvt->adapter->sco_socket);
-+
-+      manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
-+
-+      pvt->adapter->inuse = 0;
-+
-+      return NULL;
-+
-+}
-+
-+static void *do_monitor_headset(void *data)
-+{
-+
-+      struct mbl_pvt *pvt = (struct mbl_pvt *)data;
-+      char monitor = 1;
-+      char buf[256];
-+      int s, t;
-+
-+      pvt->state = MBL_STATE_PREIDLE;
-+
-+      while (monitor) {
-+
-+              if (pvt->state == MBL_STATE_RING2)
-+                      t = 2;
-+              else
-+                      t = 1;
-+              s = rfcomm_read(pvt, buf, 0, t);
-+
-+              if ((s > 0) && (buf[0] != 0x0) && (buf[0] != '\r')) {
-+                      ast_log(LOG_DEBUG, "rfcomm_read() (%s) [%s]\n", pvt->id, buf);
-+                      switch (pvt->state) {
-+                      case MBL_STATE_RING2:
-+                              if (strstr(buf, "AT+CKPD=")) {
-+                                      ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
-+                                      pvt->state = MBL_STATE_INCOMING;
-+                                      rfcomm_write(pvt, "\r\n+VGS=13\r\n");
-+                                      rfcomm_write(pvt, "\r\n+VGM=13\r\n");
-+                              }
-+                              break;
-+                      case MBL_STATE_INCOMING:
-+                              if (strstr(buf, "AT+CKPD=")) {
-+                                      ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                              }
-+                              break;
-+                      default:
-+                              break;
-+                      }
-+                      if (strstr(buf, "AT+VGS=")) {
-+                              rfcomm_write(pvt, "\r\nOK\r\n");
-+                      } else if (strstr(buf, "AT+VGM=")) {
-+                              rfcomm_write(pvt, "\r\nOK\r\n");
-+                      }
-+              } else if (s == 0) {    /* Timeouts */
-+                      if (pvt->state == MBL_STATE_PREIDLE) {
-+                              pvt->connected = 1;
-+                              ast_verbose(VERBOSE_PREFIX_3 "Bluetooth Device %s initialised and ready.\n", pvt->id);
-+                              pvt->state = MBL_STATE_IDLE;
-+                      } else if (pvt->state == MBL_STATE_RING) {
-+                              pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr);
-+                              if (pvt->sco_socket > -1) {
-+                                      ast_setstate(pvt->owner, AST_STATE_RINGING);
-+                                      ast_queue_control(pvt->owner, AST_CONTROL_RINGING);
-+                                      pvt->state = MBL_STATE_RING2;
-+                              } else {
-+                                      ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
-+                              }
-+                      } else if (pvt->state == MBL_STATE_RING2) {
-+                              rfcomm_write(pvt, "\r\nRING\r\n");
-+                      }
-+              } else if (s == -1) {
-+                      if (option_verbose > 2)
-+                              ast_verbose(VERBOSE_PREFIX_3  "Bluetooth Device %s has disconnected, reason (%d).\n", pvt->id, errno); 
-+                      monitor = 0;
-+              }
-+
-+      }
-+
-+      if (pvt->rfcomm_socket > -1)
-+              close(pvt->rfcomm_socket);
-+      if (pvt->sco_socket > -1)
-+              close(pvt->sco_socket);
-+      pvt->sco_socket = -1;
-+      pvt->connected = 0;
-+      pvt->monitor_thread = AST_PTHREADT_NULL;
-+
-+      manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Disconnect\r\nDevice: %s\r\n", pvt->id);
-+
-+      pvt->adapter->inuse = 0;
-+
-+      return NULL;
-+
-+}
-+
-+static int start_monitor(struct mbl_pvt *pvt)
-+{
-+
-+      if (pvt->type == MBL_TYPE_PHONE) {
-+              if (ast_pthread_create_background(&pvt->monitor_thread, NULL, do_monitor_phone, pvt) < 0) {
-+                      pvt->monitor_thread = AST_PTHREADT_NULL;
-+                      return 0;
-+              }
-+              /* we are a phone, so spin the sco listener on the adapter as well */
-+              if (ast_pthread_create_background(&pvt->sco_listener_thread, NULL, do_sco_listen, pvt->adapter) < 0) {
-+                      ast_log(LOG_ERROR, "Unable to create sco listener thread for device %s.\n", pvt->id);
-+              }
-+
-+      } else {
-+              if (ast_pthread_create_background(&pvt->monitor_thread, NULL, do_monitor_headset, pvt) < 0) {
-+                      pvt->monitor_thread = AST_PTHREADT_NULL;
-+                      return 0;
-+              }
-+      }
-+
-+      return 1;
-+
-+}
-+
-+static void *do_discovery(void *data)
-+{
-+
-+      struct adapter_pvt *adapter;
-+      struct mbl_pvt *pvt;
-+
-+      for (;;) {
-+              AST_RWLIST_RDLOCK(&adapters);
-+              AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
-+                      if (!adapter->inuse) {
-+                              AST_RWLIST_RDLOCK(&devices);
-+                              AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+                                      if (!adapter->inuse && !pvt->connected && !strcmp(adapter->id, pvt->adapter->id)) {
-+                                              if ((pvt->rfcomm_socket = rfcomm_connect(adapter->addr, pvt->addr, pvt->rfcomm_port)) > -1) {
-+                                                      pvt->state = 0;
-+                                                      if (start_monitor(pvt)) {
-+                                                              pvt->connected = 1;
-+                                                              adapter->inuse = 1;
-+                                                              manager_event(EVENT_FLAG_SYSTEM, "MobileStatus", "Status: Connect\r\nDevice: %s\r\n", pvt->id);
-+                                                              if (option_verbose > 2)
-+                                                                      ast_verbose(VERBOSE_PREFIX_3 "Bluetooth Device %s has connected.\n", pvt->id);
-+                                                      }
-+                                              }
-+                                      }
-+                              }
-+                              AST_RWLIST_UNLOCK(&devices);
-+                      }
-+              }
-+              AST_RWLIST_UNLOCK(&adapters);
-+              /* Go to sleep */
-+              sleep(discovery_interval);
-+      }
-+
-+      return NULL;
-+}
-+
-+static void *do_sco_listen(void *data)
-+{
-+
-+      int ns;
-+      struct sockaddr_sco addr;
-+      char saddr[18];
-+      struct sco_options so;
-+      socklen_t len;
-+      int opt = 1;
-+      socklen_t addrlen;
-+      struct mbl_pvt *pvt;
-+      struct adapter_pvt *adapter = (struct adapter_pvt *) data;
-+
-+      if ((adapter->sco_socket = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
-+              ast_log(LOG_ERROR, "Unable to create sco listener socket.\n");
-+              return NULL;
-+      }
-+      memset(&addr, 0, sizeof(addr));
-+      addr.sco_family = AF_BLUETOOTH;
-+      bacpy(&addr.sco_bdaddr, &adapter->addr);
-+      if (bind(adapter->sco_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
-+              ast_log(LOG_ERROR, "Unable to bind sco listener socket. (%d)\n", errno);
-+              close(adapter->sco_socket);
-+              return NULL;
-+      }
-+      if (setsockopt(adapter->sco_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
-+              ast_log(LOG_ERROR, "Unable to setsockopt sco listener socket.\n");
-+              close(adapter->sco_socket);
-+              return NULL;
-+      }
-+      if (listen(adapter->sco_socket, 5) < 0) {
-+              ast_log(LOG_ERROR, "Unable to listen sco listener socket.\n");
-+              close(adapter->sco_socket);
-+              return NULL;
-+      }
-+      while (1) {
-+              ast_log(LOG_DEBUG, "About to accept() socket.\n");
-+              addrlen = sizeof(struct sockaddr_sco);
-+              if ((ns = accept(adapter->sco_socket, (struct sockaddr *)&addr, &addrlen)) > -1) {
-+                      ast_log(LOG_DEBUG, "accept()ed socket.\n");
-+                      len = sizeof(so);
-+                      getsockopt(ns, SOL_SCO, SCO_OPTIONS, &so, &len);
-+
-+                      ba2str(&addr.sco_bdaddr, saddr);
-+                      ast_log(LOG_DEBUG, "Incoming Audio Connection from device %s MTU is %d\n", saddr, so.mtu);
-+
-+                      pvt = NULL;
-+                      AST_RWLIST_RDLOCK(&devices);
-+                      AST_RWLIST_TRAVERSE(&devices, pvt, entry) {
-+                              if (!bacmp(&pvt->addr, &addr.sco_bdaddr)) 
-+                                      break;
-+                      }
-+                      AST_RWLIST_UNLOCK(&devices);
-+                      if (pvt) {
-+                              if (pvt->sco_socket != -1)
-+                                      close(pvt->sco_socket);
-+                              pvt->sco_socket = ns;
-+                      } else
-+                              ast_log(LOG_DEBUG, "Could not find device for incoming Audio Connection.\n");
-+              } else {
-+                       ast_log(LOG_ERROR, "accept() failed %d\n", errno);
-+              }
-+      }
-+
-+      return NULL;
-+
-+}
-+
-+/*
-+
-+      Module
-+
-+*/
-+
-+static int mbl_load_config(void)
-+{
-+
-+      struct ast_config *cfg = NULL;
-+      char *cat = NULL;
-+      struct ast_variable *var;
-+      const char *id, *address, *useadapter, *port, *context, *type, *skip, *group, *master, *nocallsetup, *aligndetect, *blackberry;
-+      struct mbl_pvt *pvt;
-+      struct adapter_pvt *adapter;
-+      uint16_t vs;
-+      struct hci_dev_req dr;
-+      char nadapters = 0;
-+      // struct ast_flags config_flags = { 0 };
-+
-+      cfg = ast_config_load(MBL_CONFIG);
-+      if (!cfg)
-+              return 0;
-+
-+      for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
-+              if (!strcasecmp(var->name, "interval"))
-+                      discovery_interval = atoi(var->value);
-+      }
-+
-+      /* load adapters first */
-+      cat = ast_category_browse(cfg, NULL);
-+      while (cat) {
-+              if (!strcasecmp(cat, "adapter")) {
-+                      id = ast_variable_retrieve(cfg, cat, "id");
-+                      address = ast_variable_retrieve(cfg, cat, "address");
-+                      master = ast_variable_retrieve(cfg, cat, "forcemaster");
-+                      aligndetect = ast_variable_retrieve(cfg, cat, "alignmentdetection");
-+                      ast_log(LOG_DEBUG, "Loading adapter %s %s.\n", id, address);
-+                      if (!ast_strlen_zero(id) && !ast_strlen_zero(address)) {
-+                              if ((adapter = ast_calloc(1, sizeof(*adapter)))) {
-+                                      ast_copy_string(adapter->id, id, sizeof(adapter->id));
-+                                      str2ba(address, &adapter->addr);
-+                                      if (!ast_strlen_zero(aligndetect)) {
-+                                              if (*aligndetect == 'Y' || *aligndetect == 'y')
-+                                                      adapter->alignment_detection = 1;
-+                                      }
-+                                      adapter->dev_id = hci_devid(address);
-+                                      adapter->hci_socket = hci_open_dev(adapter->dev_id);
-+                                      if (adapter->dev_id < 0 || adapter->hci_socket < 0) {
-+                                              ast_log(LOG_ERROR, "Unable to open adapter %s. It won't be enabled.\n", adapter->id);
-+                                              ast_free(adapter);
-+                                      } else {
-+                                              if ((master) && (*master)) {
-+                                                      dr.dev_id = adapter->dev_id;
-+                                                      if (hci_strtolm("master", &dr.dev_opt)) {
-+                                                              if (ioctl(adapter->hci_socket, HCISETLINKMODE, (unsigned long) &dr) < 0) {
-+                                                                      ast_log(LOG_WARNING, "Unable to set adapter %s link mode to MASTER.\n", adapter->id);
-+                                                              }
-+                                                      }
-+                                              }
-+                                              hci_read_voice_setting(adapter->hci_socket, &vs, 1000);
-+                                              vs = htobs(vs);
-+                                              if (vs != 0x0060) {
-+                                                      ast_log(LOG_ERROR, "Incorrect voice setting for adapter %s, it must be 0x0060 - see 'man hciconfig' for details.\n", adapter->id);
-+                                                      hci_close_dev(adapter->hci_socket);
-+                                                      ast_free(adapter);
-+                                              } else {
-+                                                      AST_RWLIST_WRLOCK(&adapters);
-+                                                      AST_RWLIST_INSERT_HEAD(&adapters, adapter, entry);
-+                                                      AST_RWLIST_UNLOCK(&adapters);
-+                                                      nadapters++;
-+                                              }
-+                                      }
-+                              }
-+                      } else
-+                              ast_log(LOG_ERROR, "id/address missing for adapter %s. It won't be enabled.\n", cat);
-+              }
-+              cat = ast_category_browse(cfg, cat);
-+      }
-+
-+      if (!nadapters) {
-+              ast_log(LOG_WARNING, "***********************************************************************\n");
-+              ast_log(LOG_WARNING, "No Adapters defined. Please review mobile.conf. See sample for details.\n");
-+              ast_log(LOG_WARNING, "***********************************************************************\n");
-+      }
-+
-+      /* now load devices */
-+      cat = ast_category_browse(cfg, NULL);
-+      while (cat) {
-+              if (strcasecmp(cat, "general") && strcasecmp(cat, "adapter")) {
-+                      ast_log(LOG_DEBUG, "Loading device %s.\n", cat);
-+                      address = ast_variable_retrieve(cfg, cat, "address");
-+                      useadapter = ast_variable_retrieve(cfg, cat, "adapter");
-+                      port = ast_variable_retrieve(cfg, cat, "port");
-+                      context = ast_variable_retrieve(cfg, cat, "context");
-+                      type = ast_variable_retrieve(cfg, cat, "type");
-+                      skip = ast_variable_retrieve(cfg, cat, "dtmfskip");
-+                      group = ast_variable_retrieve(cfg, cat, "group");
-+                      nocallsetup = ast_variable_retrieve(cfg, cat, "nocallsetup");
-+                      blackberry = ast_variable_retrieve(cfg, cat, "blackberry");
-+                      if (!ast_strlen_zero(address) && !ast_strlen_zero(port) && !ast_strlen_zero(useadapter)) {
-+                              /* find the adapter */
-+                              AST_RWLIST_RDLOCK(&adapters);
-+                              AST_RWLIST_TRAVERSE(&adapters, adapter, entry) {
-+                                      if (!strcmp(adapter->id, useadapter))
-+                                              break;
-+                              }
-+                              AST_RWLIST_UNLOCK(&adapters);
-+                              if (!adapter) {
-+                                      ast_log(LOG_ERROR, "Device %s configured to use unknown adapter %s. It won't be enabled.\n", cat, useadapter);
-+                                      break;
-+                              }
-+                              if ((pvt = ast_calloc(1, sizeof(*pvt)))) {
-+                                      if (type && !strcmp(type, "headset"))
-+                                              pvt->type = MBL_TYPE_HEADSET;
-+                                      else
-+                                              pvt->type = MBL_TYPE_PHONE;
-+
-+                                      if (blackberry)
-+                                              pvt->blackberry = ast_true(blackberry);
-+
-+                                      ast_copy_string(pvt->id, cat, sizeof(pvt->id));
-+                                      str2ba(address, &pvt->addr);
-+                                      ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
-+                                      if (group)
-+                                              pvt->group = atoi(group);       /* group 0 if invalid */
-+                                      pvt->state = MBL_STATE_INIT;
-+                                      pvt->rfcomm_socket = -1;
-+                                      pvt->rfcomm_port = atoi(port);
-+                                      pvt->sco_socket = -1;
-+                                      pvt->monitor_thread = AST_PTHREADT_NULL;
-+                                      pvt->sco_listener_thread = AST_PTHREADT_NULL;
-+                                      if (!ast_strlen_zero(nocallsetup)) {
-+                                              if ((*nocallsetup == 'y') || (*nocallsetup == 'Y')) {
-+                                                      pvt->no_callsetup = 1;
-+                                                      ast_log(LOG_DEBUG, "Setting nocallsetup mode for device %s.\n", pvt->id);
-+                                              }
-+                                      }
-+                                      pvt->dsp = ast_dsp_new();
-+                                      if (skip) {
-+                                              if ((pvt->dtmf_skip = atoi(skip)) == 0)
-+                                                      pvt->dtmf_skip = 200;
-+                                      } else
-+                                              pvt->dtmf_skip = 200;
-+                                      ast_dsp_set_features(pvt->dsp, DSP_FEATURE_DTMF_DETECT);
-+                                      ast_dsp_digitmode(pvt->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
-+                                      pvt->adapter = adapter;
-+                                      AST_RWLIST_WRLOCK(&devices);
-+                                      AST_RWLIST_INSERT_HEAD(&devices, pvt, entry);
-+                                      AST_RWLIST_UNLOCK(&devices);
-+                              }
-+                      } else {
-+                              ast_log(LOG_ERROR, "Device %s has no address/port/adapter configured. It won't be enabled.\n", cat);
-+                      }
-+              }
-+              cat = ast_category_browse(cfg, cat);
-+      }
-+
-+      ast_config_destroy(cfg);
-+
-+      return 1;
-+
-+}
-+
-+static int unload_module(void)
-+{
-+
-+      struct mbl_pvt *pvt;
-+      struct adapter_pvt *adapter;
-+
-+      /* First, take us out of the channel loop */
-+      ast_channel_unregister(&mbl_tech);
-+
-+      /* Kill the discovery thread */
-+      if (discovery_thread != AST_PTHREADT_NULL) {
-+              pthread_cancel(discovery_thread);
-+              pthread_join(discovery_thread, NULL);
-+      }
-+
-+      /* Destroy the device list */
-+      AST_RWLIST_WRLOCK(&devices);
-+      while ((pvt = AST_RWLIST_REMOVE_HEAD(&devices, entry))) {
-+              if (pvt->monitor_thread != AST_PTHREADT_NULL) {
-+                      pthread_cancel(pvt->monitor_thread);
-+                      pthread_join(pvt->monitor_thread, NULL);
-+              }
-+              if (pvt->sco_listener_thread != AST_PTHREADT_NULL) {
-+                      pthread_cancel(pvt->sco_listener_thread);
-+                      pthread_join(pvt->sco_listener_thread, NULL);
-+              }
-+              if (pvt->sco_socket > -1) {
-+                      close(pvt->sco_socket);
-+              }
-+              if (pvt->adapter->sco_socket > -1) {
-+                      close(pvt->adapter->sco_socket);
-+              }
-+              if (pvt->rfcomm_socket > -1) {
-+                      close(pvt->rfcomm_socket);
-+              }
-+              ast_dsp_free(pvt->dsp);
-+              ast_free(pvt);
-+      }
-+      AST_RWLIST_UNLOCK(&devices);
-+
-+      /* Destroy the adapter list */
-+      AST_RWLIST_WRLOCK(&adapters);
-+      while ((adapter = AST_RWLIST_REMOVE_HEAD(&adapters, entry))) {
-+              hci_close_dev(adapter->hci_socket);
-+              ast_free(adapter);
-+      }
-+      AST_RWLIST_UNLOCK(&adapters);
-+
-+      if (sdp_session)
-+              sdp_close(sdp_session);
-+
-+      /* Unregister the CLI & APP */
-+      ast_cli_unregister_multiple(mbl_cli, sizeof(mbl_cli) / sizeof(mbl_cli[0]));
-+      ast_unregister_application(app_mblstatus);
-+      ast_unregister_application(app_mblsendsms);
-+
-+      return 0;
-+
-+}
-+
-+static int load_module(void)
-+{
-+
-+      int dev_id, s;
-+
-+      /* Check if we have Bluetooth, no point loading otherwise... */
-+      dev_id = hci_get_route(NULL);
-+      s = hci_open_dev(dev_id);
-+      if (dev_id < 0 || s < 0) {
-+              ast_log(LOG_ERROR, "No Bluetooth device found. Not loading module.\n");
-+              return AST_MODULE_LOAD_DECLINE;
-+      }
-+
-+      hci_close_dev(s);
-+
-+      if (!mbl_load_config()) {
-+              ast_log(LOG_ERROR, "Unable to read config file %s. Not loading module.\n", MBL_CONFIG);
-+              return AST_MODULE_LOAD_DECLINE;
-+      }
-+
-+      sdp_session = sdp_register();
-+
-+      /* Spin the discovery thread */
-+      if (ast_pthread_create_background(&discovery_thread, NULL, do_discovery, NULL) < 0) {
-+              ast_log(LOG_ERROR, "Unable to create discovery thread.\n");
-+              return AST_MODULE_LOAD_DECLINE;
-+      }
-+
-+      ast_cli_register_multiple(mbl_cli, sizeof(mbl_cli) / sizeof(mbl_cli[0]));
-+      ast_register_application(app_mblstatus, mbl_status_exec, mblstatus_synopsis, mblstatus_desc);
-+      ast_register_application(app_mblsendsms, mbl_sendsms_exec, mblsendsms_synopsis, mblsendsms_desc);
-+
-+      /* Make sure we can register our channel type */
-+      if (ast_channel_register(&mbl_tech)) {
-+              ast_log(LOG_ERROR, "Unable to register channel class %s\n", "Mobile");
-+              return AST_MODULE_LOAD_FAILURE;
-+      }
-+
-+      return 0;
-+}
-+
-+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Bluetooth Mobile Device Channel Driver",
-+              .load = load_module,
-+              .unload = unload_module,
-+);
-diff -Nru asterisk-addons-1.4.8.org/configs/mobile.conf.sample asterisk-addons-1.4.8/configs/mobile.conf.sample
---- asterisk-addons-1.4.8.org/configs/mobile.conf.sample       1970-01-01 01:00:00.000000000 +0100
-+++ asterisk-addons-1.4.8/configs/mobile.conf.sample   2009-06-04 22:20:03.000000000 +0200
-@@ -0,0 +1,68 @@
-+;
-+; mobile.conf
-+; configuration file for chan_mobile
-+;
-+
-+[general]
-+interval=30           ; Number of seconds between trying to connect to devices. 
-+
-+; The following is a list of adapters we use.
-+; id must be unique and address is the bdaddr of the adapter from hciconfig.
-+; Each adapter may only have one device (headset or phone) connected at a time.
-+; Add an [adapter] entry for each adapter you have.
-+
-+[adapter]
-+id=blue
-+address=00:09:DD:60:01:A3
-+;forcemaster=yes      ; attempt to force adapter into master mode. default is no.
-+;alignmentdetection=yes ; enable this if you sometimes get 'white noise' on asterisk side of the call
-+                      ; its a bug in the bluetooth adapter firmware, enabling this will compensate for it.
-+                      ; default is no.
-+
-+[adapter]
-+id=dlink
-+address=00:80:C8:35:52:78
-+
-+; The following is a list of the devices we deal with.
-+; Every device listed below will be available for calls in and out of Asterisk. 
-+; Each device needs an adapter=xxxx entry which determines which bluetooth adapter is used.
-+; Use the CLI command 'mobile search' to discover devices.
-+; Use the CLI command 'mobile show devices' to see device status.
-+;
-+; To place a call out through a mobile phone use Dial(Mobile/[device]/NNN.....) or Dial(Mobile/gn/NNN......) in your dialplan.
-+; To call a headset use Dial(Mobile/[device]).
-+
-+[LGTU550]
-+address=00:E0:91:7F:46:44     ; the address of the phone
-+port=4                                ; the rfcomm port number (from mobile search)
-+context=incoming-mobile               ; dialplan context for incoming calls
-+adapter=dlink                 ; adapter to use
-+group=1                               ; this phone is in channel group 1
-+;nocallsetup=yes              ; set this only if your phone reports that it supports call progress notification, but does not do it. Motorola L6 for example.
-+
-+[blackberry]
-+address=00:60:57:32:7E:B2
-+port=2
-+context=incoming-mobile
-+adapter=dlink
-+group=1
-+;blackberry=yes                       ; set this if you are using a blackberry device
-+
-+[6310i]
-+address=00:60:57:32:7E:B1
-+port=13
-+context=incoming-mobile
-+adapter=dlink
-+group=1                               ; this phone is in channel group 1 also.
-+
-+[headset]
-+address=00:0B:9E:11:AE:C6
-+port=1
-+type=headset                  ; This is a headset, not a Phone !
-+adapter=blue
-+
-+[headset1]
-+address=00:0B:9E:11:74:A5
-+port=1
-+type=headset
-+adapter=dlink
-diff -Nru asterisk-addons-1.4.8.org/configure.ac asterisk-addons-1.4.8/configure.ac
---- asterisk-addons-1.4.8.org/configure.ac     2008-02-13 23:58:11.000000000 +0100
-+++ asterisk-addons-1.4.8/configure.ac 2009-06-04 22:20:03.000000000 +0200
-@@ -161,11 +161,13 @@
- # from here on down, library checking should be done in alphabetical order
- # by the --with option name, to make things easier for the users :-)
-+AST_EXT_LIB_SETUP([BLUETOOTH], [Bluetooth Support], [bluetooth])
- AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
- AST_EXT_LIB_SETUP([NCURSES], [ncurses], [ncurses])
- AST_EXT_LIB_SETUP([MYSQLCLIENT], [mysqlclient], [mysqlclient])
- AST_EXT_LIB_SETUP([ASTERISK], [asterisk], [asterisk])
-+AST_EXT_LIB_CHECK([BLUETOOTH], [bluetooth], [ba2str], [bluetooth/bluetooth.h])
- AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
- AST_EXT_LIB_CHECK([NCURSES], [ncurses], [initscr], [curses.h])
-diff -Nru asterisk-addons-1.4.8.org/makeopts.in asterisk-addons-1.4.8/makeopts.in
---- asterisk-addons-1.4.8.org/makeopts.in      2008-02-13 23:58:11.000000000 +0100
-+++ asterisk-addons-1.4.8/makeopts.in  2009-06-04 22:20:03.000000000 +0200
-@@ -34,6 +34,9 @@
- sharedstatedir = @sharedstatedir@
- sysconfdir = @sysconfdir@
-+BLUETOOTH_LIB=@BLUETOOTH_LIB@
-+BLUETOOTH_INCLUDE=@BLUETOOTH_INCLUDE@
-+
- CURSES_LIB=@CURSES_LIB@
- CURSES_INCLUDE=@CURSES_INCLUDE@
diff --git a/net/asterisk-addons-1.4.x/patches/021-cross_configure.patch b/net/asterisk-addons-1.4.x/patches/021-cross_configure.patch
deleted file mode 100644 (file)
index ac6e809..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -Nru asterisk-addons-1.4.8.org/menuselect/Makefile asterisk-addons-1.4.8/menuselect/Makefile
---- asterisk-addons-1.4.8.org/menuselect/Makefile      2009-01-08 22:31:41.000000000 +0100
-+++ asterisk-addons-1.4.8/menuselect/Makefile  2009-06-04 22:21:23.000000000 +0200
-@@ -52,7 +52,7 @@
- $(OBJS) menuselect_gtk.o menuselect_curses.o menuselect_stub.o: autoconfig.h menuselect.h
- makeopts autoconfig.h: autoconfig.h.in makeopts.in
--      @./configure $(CONFIGURE_SILENT) CC= LD= AR= CFLAGS=
-+      @./configure $(CONFIGURE_SILENT) CC= LD= AR= CFLAGS= LDFLAGS=
- menuselect gmenuselect: mxml/libmxml.a
diff --git a/net/asterisk-addons-1.4.x/patches/030-mysql_include.patch b/net/asterisk-addons-1.4.x/patches/030-mysql_include.patch
deleted file mode 100644 (file)
index 2782d04..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
---- asterisk-addons-1.4.8/configure.ac.org     2011-02-16 15:32:41.000000000 +0100
-+++ asterisk-addons-1.4.8/configure.ac 2011-02-16 15:36:05.000000000 +0100
-@@ -191,11 +191,13 @@
- fi
- if test x"${MYSQL_CONFIG}" != xNo; then
-    MYSQLCLIENT_libs=`mysql_config --libs`
-+   MYSQLCLIENT_include=`mysql_config --include`
-    
-    AC_CHECK_LIB([mysqlclient], [mysql_init], [], [], ${MYSQLCLIENT_libs})
-    if test "${ac_cv_lib_mysqlclient_mysql_init}" = "yes"; then
-       MYSQLCLIENT_LIB="${MYSQLCLIENT_libs}"
-+      MYSQLCLIENT_INCLUDE="${MYSQLCLIENT_include}/.."
-       PBX_MYSQLCLIENT=1
-    elif test ! -z "${MYSQLCLIENT_MANDATORY}";
-    then