[asterisk-dev] chan_bluetooth patch for SVN trunk

Brian Candler B.Candler at pobox.com
Mon Oct 23 03:58:10 MST 2006


The following patch enables chan_bluetooth to compile under SVN trunk. It is
a diff against the code in the infradead CVS server; see
http://lists.digium.com/pipermail/asterisk-dev/2005-May/012465.html

My test platform is CentOS 4.4, Asterisk SVN trunk r45305, a "DABS Value"
class 1 USB Bluetooth dongle, and a Plantronics Explorer 320 bluetooth
headset.

Notes on the patch
------------------

I don't have any documentation on the 1.2 or 1.4 channel API, nor a list of
changes between them, so I am not doing anything intelligent here; I just
modified it until it would compile, without any warnings.

There are several points labelled "XXX REMOVED FOR TRUNK". This is where a
structure member or function call no longer exists in trunk, so I just
blindly commented out the access to it.

This needs changing by someone who knows what they're doing, so that it's a
conditional compilation based on the actual Asterisk version being built,
and/or so that it uses whatever the correct "new" way is for channel drivers
in trunk to do whatever it was doing previously.

Notes on operation
------------------

It "kind of" works. That is, I had it paired with a headset and was able to
make a call to it. It's flaky as hell - however, from what I've read before,
chan_bluetooth is flaky as hell anyway :-)

The received audio in the headset is fine. The sent microphone audio is
extremely quiet, and I have to hold the thing right in front of my mouth to
show that it's working. But this might be an artefact of the particular
headset I'm testing, rather than chan_bluetooth.

Error state 1: it gets into a state where Asterisk thinks its placing a
call, but no ringing tone appears in the headeset.

    -- Executing [s at macro-ext:1] Dial("Zap/1-1", "BLT/320Plantronics|15") in new stack
[Oct 23 11:19:31] DEBUG[3495]: chan_bluetooth.c:1263 blt_request: Dialing '(null)' via '320Plantronics'
[Oct 23 11:19:31] DEBUG[3495]: chan_bluetooth.c:1023 blt_call: Calling 320Plantronics on BLT [t: 0]
 [HS] 320Plantronics < +CIEV: 3,1
 [HS] 320Plantronics < RING
    -- Called 320Plantronics
    -- BLT is ringing
 [HS] 320Plantronics < RING
 [HS] 320Plantronics < RING
 [HS] 320Plantronics < RING
    -- Nobody picked up in 15000 ms
[Oct 23 11:19:46] DEBUG[3495]: chan_bluetooth.c:1074 blt_hangup: blt_hangup(BLT)
 [HS] 320Plantronics < +CIEV: 3,0

If I try to fix that by stopping and restarting Asterisk, then I get to:

Error state 2: it loops infinitely saying

*CLI> [Oct 23 11:11:54] NOTICE[3204]: chan_bluetooth.c:2268 try_connect: Connect to device 320Plantronics failed: Operation already in progress (errno 114)
[Oct 23 11:11:57] NOTICE[3204]: chan_bluetooth.c:2268 try_connect: Connect to device 320Plantronics failed: Operation already in progress (errno 114)
[Oct 23 11:11:59] NOTICE[3204]: chan_bluetooth.c:2268 try_connect: Connect to device 320Plantronics failed: Operation already in progress (errno 114)

The following sequence does NOT fix this:
- stop Asterisk
- "service bluetooth restart"
- start Asterisk

However, I can get it to work again as follows:
- stop Asterisk
- "service bluetooth stop"
- unplug and replug the USB BT adaptor
- "service bluetooth start"
- start Asterisk

Error state 3: Asterisk thinks the headset is busy, when it isn't, and then
loses comms with it completely.

[Oct 23 11:39:11] DEBUG[4092]: chan_bluetooth.c:1263 blt_request: Dialing '(null)' via '320Plantronics'
[Oct 23 11:39:11] DEBUG[4092]: chan_bluetooth.c:1023 blt_call: Calling 320Plantronics on BLT [t: 0]
 [HS] 320Plantronics < +CIEV: 3,1
 [HS] 320Plantronics < RING
    -- Called 320Plantronics
    -- BLT is ringing
[Oct 23 11:39:12] NOTICE[4077]: chan_bluetooth.c:2679 rd_close: Device 320Plantronics disconnected, scheduled reconnect in 5 seconds: Software caused connection abort (errno 103)
[Oct 23 11:39:12] DEBUG[4092]: chan_bluetooth.c:1074 blt_hangup: blt_hangup(BLT)
 [HS] 320Plantronics < +CIEV: 3,0
  == Everyone is busy/congested at this time (1:0/0/1)
    -- Executing [s at macro-ext:2] Playback("Zap/1-1", "vm-nobodyavail") in new stack
    -- Playing 'vm-nobodyavail' (language 'en')
    -- Executing [s at macro-ext:3] Hangup("Zap/1-1", "") in new stack
  == Spawn extension (macro-ext, s, 3) exited non-zero on 'Zap/1-1' in macro 'ext'
  == Spawn extension (macro-ext, s, 3) exited non-zero on 'Zap/1-1'
    -- Hungup 'Zap/1-1'
[Oct 23 11:39:17] WARNING[4077]: chan_bluetooth.c:2289 try_connect: NBIO connect() to 320Plantronics returned 113: No route to host
[Oct 23 11:39:22] WARNING[4077]: chan_bluetooth.c:2289 try_connect: NBIO connect() to 320Plantronics returned 113: No route to host
[Oct 23 11:39:27] WARNING[4077]: chan_bluetooth.c:2289 try_connect: NBIO connect() to 320Plantronics returned 113: No route to host
[Oct 23 11:39:32] WARNING[4077]: chan_bluetooth.c:2289 try_connect: NBIO connect() to 320Plantronics returned 113: No route to host
[Oct 23 11:39:37] WARNING[4077]: chan_bluetooth.c:2289 try_connect: NBIO connect() to 320Plantronics returned 113: No route to host

I did try one other device, which was a Nokia N70 phone as audio gateway.
Initially I got:

*CLI> [Oct 23 11:51:32] NOTICE[4475]: chan_bluetooth.c:2268 try_connect: Connect to device BrianC failed: Protocol error (errno 71)

And then later:

*CLI> [Oct 23 11:51:43] NOTICE[4475]: chan_bluetooth.c:2268 try_connect: Connect to device BrianC failed: Operation already in progress (errno 114)
[Oct 23 11:52:00] NOTICE[4475]: chan_bluetooth.c:2227 try_connect: Initialised bluetooth link to device BrianC
 [AG]     BrianC < AT+BRSF=23
 [AG]     BrianC > ERROR
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1844 ag_brsf_response: Bluetooth features: ERROR
 [AG]     BrianC < AT+CIND=?
[Oct 23 11:52:00] WARNING[4475]: chan_bluetooth.c:2585 handle_rd_data: Device BrianC: Unhandled Unsolicited: +BRSF: 47
 [AG]     BrianC > +BRSF: 47
 [AG]     BrianC > OK
 [AG]     BrianC < AT+CIND?
 [AG]     BrianC > ERROR
 [AG]     BrianC < AT+CMER=3,0,0,1
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 1 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 2 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 3 set to 1
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 4 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 5 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 6 set to 1
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 7 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 8 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 9 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1695 ag_unsol_cind: CIND IND 10 set to 0 [(0-3))]
 [AG]     BrianC > +CIND: ("service",(0,1)),("call",(0,1)),("call_setup",(0-3)),("callsetup",(0-3))
 [AG]     BrianC > OK
 [AG]     BrianC < AT+CLIP=1
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 1 set to 1
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 2 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:479 set_cind: CIND 3 set to 0
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1695 ag_unsol_cind: CIND IND 4 set to 0 [0]
 [AG]     BrianC > +CIND: 1,0,0,0
 [AG]     BrianC > OK
 [AG]     BrianC < AT+CGMI=?
 [AG]     BrianC > OK
 [AG]     BrianC < AT+CGMI
 [AG]     BrianC > ERROR
 [AG]     BrianC > OK
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1764 ag_unknown_response: Got UNKN response: OK
 [AG]     BrianC > ERROR
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1764 ag_unknown_response: Got UNKN response: ERROR
 [AG]     BrianC > ERROR
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1764 ag_unknown_response: Got UNKN response: ERROR
 [AG]     BrianC > ERROR
[Oct 23 11:52:00] DEBUG[4475]: chan_bluetooth.c:1764 ag_unknown_response: Got UNKN response: ERROR

Surprisingly, with Dial(BLT/BrianC/079XXXXXXX,15) in extensions.conf, the
phone did actually place a call to the given number, but audio didn't work.

Anyway, I'm posting this in the hope that it's useful to someone, and if
anyone decides to start maintaining chan_bluetooth again, it may save them
some time.

Regards,

Brian.
-------------- next part --------------
--- channels/chan_bluetooth.c.orig	2006-10-23 11:07:20.000000000 +0100
+++ channels/chan_bluetooth.c	2006-10-23 10:21:27.000000000 +0100
@@ -91,6 +91,7 @@
 
 /* ---------------------------------- */
 
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <string.h>
 #include <asterisk/lock.h>
@@ -217,7 +218,7 @@
   // device
   int autoconnect;                  /* 1 for autoconnect */
   int outgoing_id;                  /* Outgoing connection scheduler id */
-  char * name;                      /* Devices friendly name */
+  const char * name;                /* Devices friendly name */
   blt_role_t role;                  /* Device role (HS or AG) */
   bdaddr_t bdaddr;                  /* remote address */
   int channel;                      /* remote channel */
@@ -228,7 +229,7 @@
   char rd_buff[BLT_RDBUFF_MAX];     /* RFCOMM input buffer */
   int rd_buff_pos;                  /* RFCOMM input buffer position */
   int ready;                        /* 1 When ready */
-  char *context;
+  const char *context;
 
   /* AG mode */
   char last_ok_cmd[BLT_RDBUFF_MAX];        /* Runtime[AG]: Last AT command that was OK */
@@ -328,7 +329,7 @@
 static struct ast_frame *blt_read(struct ast_channel *chan);
 static int blt_call(struct ast_channel *c, char *dest, int timeout);
 static int blt_write(struct ast_channel *chan, struct ast_frame *f);
-static int blt_indicate(struct ast_channel *chan, int cond);
+static int blt_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen);
 
 static const struct ast_channel_tech blt_tech = {
 	.type = BLT_CHAN_NAME,
@@ -378,7 +379,7 @@
   return "Unknown";
 }
 
-int sock_err(int fd)
+static int sock_err(int fd)
 {
   int ret;
   int len = sizeof(ret);
@@ -387,7 +388,7 @@
 }
 
 /* ---------------------------------- */
-int parse_clip(const char * str, char *number, int number_len, char * name, int name_len, int *type)
+static int parse_clip(const char * str, char *number, int number_len, char * name, int name_len, int *type)
 {
   const char *c = str;
   const char *start;
@@ -531,7 +532,7 @@
 
 /* ---------------------------------- */
 
-int
+static int
 set_buffer(char * ring, char * data, int circular_len, int * pos, int data_len)
 {
   int start_pos = *(pos);
@@ -555,7 +556,7 @@
   return 0;
 }
 
-int
+static int
 get_buffer(char * dst, char * ring, int ring_size, int * head, int to_copy)
 {
   int copy;
@@ -1128,7 +1129,7 @@
 }
 
 static int 
-blt_indicate(struct ast_channel * c, int condition)
+blt_indicate(struct ast_channel * c, int condition, const void *data, size_t datalen)
 {
   ast_log(LOG_DEBUG, "blt_indicate (%d)\n", condition);
 
@@ -1178,7 +1179,7 @@
     return NULL;
   }
 
-  snprintf(ast->name, sizeof(ast->name), "BLT/%s", dev->name);
+  snprintf((char *)ast->name, sizeof(ast->name), "BLT/%s", dev->name);
 
   // ast->fds[0] = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
 
@@ -1190,7 +1191,7 @@
 
   ast_setstate(ast, state);
 
-  ast->type = BLT_CHAN_NAME;
+  //ast->type = BLT_CHAN_NAME;  XXX REMOVED FOR TRUNK
 
   ast->tech_pvt = dev;
 #if ASTERISK_VERSION_NUM > 010107
@@ -1210,7 +1211,7 @@
     ast_set_callerid(ast, dev->cid_num, dev->cid_name, dev->cid_num);
   }
 
-  ast->language[0] = '\0';
+  //ast->language[0] = '\0';   XXX REMOVED FOR TRUNK
 
   ast->fds[0] = dev->sco_pipe[0];
   write(dev->sco_pipe[1], &c, 1);
@@ -1757,7 +1758,7 @@
 
 /* -- Handle negotiation when we're a HS -- */
 
-void
+static void
 ag_unknown_response(blt_dev_t * dev, char * cmd)
 {
   ast_log(LOG_DEBUG, "Got UNKN response: %s\n", cmd);
@@ -1767,7 +1768,7 @@
 
 }
 
-void
+static void
 ag_cgmi_response(blt_dev_t * dev, char * cmd)
 {
   // CGMM - Phone Model
@@ -1788,7 +1789,7 @@
   dev->cb = ag_unknown_response;
 }
 
-void
+static void
 ag_cgmi_valid_response(blt_dev_t * dev, char * cmd)
 {
   // send_atcmd(dev, "AT+WS46?");
@@ -1803,14 +1804,14 @@
   }
 }
 
-void
+static void
 ag_clip_response(blt_dev_t * dev, char * cmd)
 {
   send_atcmd(dev, "AT+CGMI=?");
   dev->cb = ag_cgmi_valid_response;
 }
 
-void
+static void
 ag_cmer_response(blt_dev_t * dev, char * cmd)
 {
   dev->cb = ag_clip_response;
@@ -1819,7 +1820,7 @@
   send_atcmd(dev, "AT+CLIP=1");
 }
 
-void
+static void
 ag_cind_status_response(blt_dev_t * dev, char * cmd)
 {
   // XXX:T: Handle response.
@@ -1828,7 +1829,7 @@
   // Initiase SCO link!
 }
 
-void
+static void
 ag_cind_response(blt_dev_t * dev, char * cmd)
 {
   dev->cb = ag_cind_status_response;
@@ -1836,7 +1837,7 @@
   send_atcmd(dev, "AT+CIND?");
 }
 
-void
+static void
 ag_brsf_response(blt_dev_t * dev, char * cmd)
 {
   dev->cb = ag_cind_response;
@@ -2879,7 +2880,7 @@
 {
   struct ast_config * cfg;
   struct ast_variable * v;
-  char * cat;
+  const char * cat;
 
   cfg = ast_config_load(BLT_CONFIG_FILE);
 
@@ -2906,7 +2907,7 @@
 
   while(cat) {
 
-    char * str;
+    const char * str;
 
     if (strcasecmp(cat, "general")) {
       blt_dev_t * device = malloc(sizeof(blt_dev_t));
@@ -3056,7 +3057,7 @@
 }
 
 static char *
-complete_device(char * line, char * word, int pos, int state, int rpos, blt_role_t role)
+complete_device(const char * line, const char * word, int pos, int state, int rpos, blt_role_t role)
 {
   blt_dev_t * dev;
   int which = 0;
@@ -3090,7 +3091,7 @@
 }
 
 static char *
-complete_device_2_ag(char * line, char * word, int pos, int state)
+complete_device_2_ag(const char * line, const char * word, int pos, int state)
 {
   return complete_device(line, word, pos, state, 2, BLT_ROLE_AG);
 }
@@ -3103,7 +3104,6 @@
 cli_show_peers =
     { { "bluetooth", "show", "peers", NULL }, blt_show_peers, "List Bluetooth Peers", show_peers_usage };
 
-
 static char ag_sendcmd[] =
 "Usage: bluetooth ag <device> sendcmd <cmd>\n"
 "       Sends a AT cmd over the RFCOMM link, and print result (AG only)\n";
@@ -3120,7 +3120,7 @@
 cli_show_information =
     { { "bluetooth", "show", "information", NULL }, blt_show_information, "List Bluetooth Info", show_information };
 
-void
+static void
 remove_sdp_records(void)
 {
 
@@ -3198,13 +3198,16 @@
 
   }
 
-  ast_unregister_atexit(remove_sdp_records);
+  //ast_unregister_atexit(remove_sdp_records); XXX REMOVED FOR TRUNK
   remove_sdp_records();
   return 0;
 }
 
-int
-load_module()
+static int
+unload_module(void);
+
+static int
+load_module(void)
 {
   sdp_session_t * sess;
   int dd;
@@ -3285,14 +3288,14 @@
   ast_cli_register(&cli_show_peers);
   ast_cli_register(&cli_ag_sendcmd);
 
-  ast_register_atexit(remove_sdp_records);
+  //ast_register_atexit(remove_sdp_records); XXX REMOVED FOR TRUNK
 
   ast_log(LOG_NOTICE, "Loaded Bluetooth support, %s\n", BLT_SVN_REVISION + 1);
 
   return 0;
 }
 
-int
+static int
 unload_module(void)
 {
   ast_cli_unregister(&cli_ag_sendcmd);
@@ -3301,25 +3304,8 @@
   return __unload_module();
 }
 
-int
-usecount()
-{
-  int res;
-  ast_mutex_lock(&usecnt_lock);
-  res = usecnt;
-  ast_mutex_unlock(&usecnt_lock);
-  return res;
-}
-
-char *description()
-{
-  return "Bluetooth Channel Driver";
-}
-
-char *
-key()
-{
-  return ASTERISK_GPL_KEY;
-}
-
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Bluetooth channel driver",
+		.load = load_module,
+		.unload = unload_module,
+);
 
-------------- next part --------------
--- channels/Makefile~	2006-10-23 10:35:21.000000000 +0100
+++ channels/Makefile	2006-10-23 10:35:21.000000000 +0100
@@ -107,6 +107,10 @@
 	$(CMD_PREFIX) $(CXX) $(SOLINK) -o $@ $< h323/libchanh323.a $(CHANH323LIB) -L$(PWLIBDIR)/lib $(PTLIB) -L$(OPENH323DIR)/lib $(H323LIB) -L/usr/lib -lcrypto -lssl -lexpat
 endif
 
+chan_bluetooth.so: chan_bluetooth.o
+	$(ECHO_PREFIX) echo "   [LD] $^ -> $@"
+	$(CMD_PREFIX) $(CXX) $(SOLINK) -lbluetooth -o $@ $<
+
 chan_misdn.o: ASTCFLAGS+=-Imisdn 
 
 misdn_config.o: ASTCFLAGS+=-Imisdn 


More information about the asterisk-dev mailing list