]> git.pld-linux.org Git - packages/asterisk.git/blob - asterisk-chan_bluetooth.patch
- up to 1.4.42
[packages/asterisk.git] / asterisk-chan_bluetooth.patch
1 diff -urN asterisk-1.4.0-beta3-o-o/build_tools/menuselect-deps.in asterisk-1.4.0-beta3/build_tools/menuselect-deps.in
2 --- asterisk-1.4.0-beta3-o-o/build_tools/menuselect-deps.in     2006-09-19 11:07:22.000000000 -0600
3 +++ asterisk-1.4.0-beta3/build_tools/menuselect-deps.in 2006-11-06 12:45:04.000000000 -0700
4 @@ -1,4 +1,5 @@
5  ASOUND=@PBX_ALSA@
6 +BLUETOOTH=@PBX_BLUETOOTH@
7  CURL=@PBX_CURL@
8  FREETDS=@PBX_FREETDS@
9  GSM=@PBX_GSM@
10 diff -urN asterisk-1.4.0-beta3-o-o/channels/chan_bluetooth.c asterisk-1.4.0-beta3/channels/chan_bluetooth.c
11 --- asterisk-1.4.0-beta3-o-o/channels/chan_bluetooth.c  1969-12-31 17:00:00.000000000 -0700
12 +++ asterisk-1.4.0-beta3/channels/chan_bluetooth.c      2006-11-06 12:44:39.000000000 -0700
13 @@ -0,0 +1,3145 @@
14 +/*
15 + * Asterisk -- A telephony toolkit for Linux.
16 + *
17 + * Asterisk Bluetooth Channel
18 + *
19 + * Author: Theo Zourzouvillys <theo@adaptive-it.co.uk>
20 + *
21 + * Adaptive Linux Solutions <http://www.adaptive-it.co.uk>
22 + *
23 + * Copyright (C) 2004 Adaptive Linux Solutions
24 + *
25 + * This program is free software, distributed under the terms of
26 + * the GNU General Public License
27 + *
28 + * ******************* NOTE NOTE NOTE NOTE NOTE *********************
29 + *
30 + * This code is not at all tested, and only been developed with a
31 + * HBH-200 headset and a Nokia 6310i right now.
32 + *
33 + * Expect it to crash, dial random numbers, and steal all your money.
34 + *
35 + * PLEASE try any headsets and phones, and let me know the results,
36 + * working or not, along with all debug output!
37 + *
38 + * ------------------------------------------------------------------
39 + *
40 + * Asterisk Bluetooth Support
41 + *
42 + * Well, here we go - Attempt to provide Handsfree profile support in
43 + * both AG and HF modes, AG (AudioGateway) mode support for using
44 + * headsets, and HF (Handsfree) mode for utilising mobile/cell phones
45 + *
46 + * It would be nice to also provide Headset support at some time in
47 + * the future, however, a working Handsfree profile is nice for now,
48 + * and as far as I can see, almost all new HS devices also support HF
49 + *
50 + * ------------------------------------------------------------------
51 + * INSTRUCTIONS
52 + *
53 + * You need to have bluez's bluetooth stack, along with user space
54 + * tools (>=v2.10), and running hcid and sdsp.
55 + *
56 + * See bluetooth.conf for configuration details.
57 + *
58 + * - Ensure bluetooth subsystem is up and running.  'hciconfig'
59 + *   should show interface as UP.
60 + *
61 + * - If you're trying to use a headset/HS, start up asterisk, and try
62 + *   to pair it as you normally would.
63 + *
64 + * - If you're trying to use a Phone/AG, just make sure bluetooth is
65 + *   enabled on your phone, and start up asterisk.
66 + *
67 + * - 'bluetooth show peers' will show all bluetooth devices states.
68 + *
69 + * - Send a call out by using Dial(BLT/DevName/0123456).  Call a HS 
70 + *   with Dial(BLT/DevName)
71 + *
72 + * ------------------------------------------------------------------
73 + * BUGS
74 + *
75 + * - What should happen when an AG is paired with asterisk and
76 + *   someone uses the AG dalling a number manually?  My test phone
77 + *   seems to try to open an SCO link.  Perhaps an extension to 
78 + *   route the call to, or maybe drop the RFCOM link all together?
79 + *
80 + * ------------------------------------------------------------------
81 + * COMPATIBILITY
82 + *
83 + * PLEASE email <theo@adaptive-it.co.uk> with the results of ANY
84 + * device not listed in here (working or not), or if the device is
85 + * listed and it doesn't work!  Please also email full debug output
86 + * for any device not working correctly or generating errors in log.
87 + * 
88 + * HandsFree Profile:
89 + *
90 + *  HS (HeadSet):
91 + *   - Ericsson HBH-200
92 + *
93 + *  AG (AudioGateway):
94 + *   - Nokia 6310i
95 + *
96 + * ------------------------------------------------------------------
97 + *
98 + * Questions, bugs, or (preferably) patches to:
99 + *
100 + *  <theo@adaptive-it.co.uk>
101 + *
102 + * ------------------------------------------------------------------
103 + */
104 +
105 +/*! \file
106 + *
107 + * \brief Channel driver for Bluetooth phones and headsets
108 + *
109 + * \author Theo Zourzouvillys <theo@adaptive-it.co.uk>
110 + *
111 + * \par See also
112 + * \arg \ref Config_bluetooth
113 + *
114 + * \ingroup channel_drivers
115 + */
116 +
117 +
118 +/*** MODULEINFO
119 +        <depend>bluetooth</depend>
120 + ***/
121 +
122 +
123 +/* ---------------------------------- */
124 +
125 +#include <stdio.h>
126 +#include <string.h>
127 +#include <asterisk/lock.h>
128 +#include <asterisk/utils.h>
129 +#include <asterisk/channel.h>
130 +#include <asterisk/channel_pvt.h>
131 +#include <asterisk/config.h>
132 +#include <asterisk/logger.h>
133 +#include <asterisk/module.h>
134 +#include <asterisk/pbx.h>
135 +#include <asterisk/sched.h>
136 +#include <asterisk/options.h>
137 +#include <asterisk/cli.h>
138 +#include <asterisk/callerid.h>
139 +#include <sys/socket.h>
140 +#include <sys/signal.h>
141 +#include <sys/time.h>
142 +#include <errno.h>
143 +#include <unistd.h>
144 +#include <stdlib.h>
145 +#include <arpa/inet.h>
146 +#include <fcntl.h>
147 +#include <sys/ioctl.h>
148 +#include <ctype.h>
149 +
150 +#include <bluetooth/bluetooth.h>
151 +#include <bluetooth/hci.h>
152 +#include <bluetooth/hci_lib.h>
153 +#include <bluetooth/sco.h>
154 +#include <bluetooth/rfcomm.h>
155 +#include <bluetooth/sdp.h>
156 +#include <bluetooth/sdp_lib.h>
157 +
158 +/* --- Data types and definitions --- */
159 +
160 +#ifndef HANDSFREE_AUDIO_GW_SVCLASS_ID
161 +# define HANDSFREE_AUDIO_GW_SVCLASS_ID 0x111f
162 +#endif
163 +
164 +#define BLUETOOTH_FORMAT    AST_FORMAT_SLINEAR
165 +#define BLT_CHAN_NAME       "BLT"
166 +#define BLT_CONFIG_FILE     "bluetooth.conf"
167 +#define BLT_RDBUFF_MAX      1024
168 +#define BLT_DEFAULT_HCI_DEV 0
169 +#define BLT_SVN_REVISION    "$Rev: 38 $"
170 +
171 +/* ---------------------------------- */
172 +
173 +typedef enum {
174 +  BLT_ROLE_NONE = 0, // Unknown Device
175 +  BLT_ROLE_HS = 1,   // Device is a Headset
176 +  BLT_ROLE_AG = 2    // Device is an Audio Gateway
177 +} blt_role_t;
178 +
179 +/* State when we're in HS mode */
180 +
181 +typedef enum {
182 +  BLT_STATE_WANT_R   = 0,
183 +  BLT_STATE_WANT_N   = 1,
184 +  BLT_STATE_WANT_CMD = 2,
185 +  BLT_STATE_WANT_N2  = 3,
186 +} blt_state_t;
187 +
188 +typedef enum {
189 +  BLT_STATUS_DOWN,
190 +  BLT_STATUS_CONNECTING,
191 +  BLT_STATUS_NEGOTIATING,
192 +  BLT_STATUS_READY,
193 +  BLT_STATUS_RINGING,
194 +  BLT_STATUS_IN_CALL,
195 +} blt_status_t;
196 +
197 +/* ---------------------------------- */
198 +
199 +/* Default config settings */
200 +
201 +#define BLT_DEFAULT_CHANNEL_AG   5
202 +#define BLT_DEFAULT_CHANNEL_HS   6
203 +#define BLT_DEFAULT_ROLE         BLT_ROLE_HS
204 +#define BLT_OBUF_LEN             (48 * 25)
205 +
206 +#define BUFLEN 4800
207 +
208 +/* ---------------------------------- */
209 +
210 +typedef struct blt_dev blt_dev_t;
211 +
212 +// XXX:T: Tidy this lot up.
213 +struct blt_dev {
214 +
215 +  blt_status_t status;              /* Device Status */
216 +
217 +  struct ast_channel * owner;       /* Channel we belong to, possibly NULL */
218 +  blt_dev_t * dev;                  /* The bluetooth device channel is for */
219 +  struct ast_frame fr;              /* Recieved frame */
220 +
221 +  /* SCO Handler */
222 +  int sco_pipe[2];                   /* SCO alert pipe */
223 +  int sco;                           /* SCO fd */
224 +  int sco_handle;                    /* SCO Handle */
225 +  int sco_mtu;                       /* SCO MTU */
226 +  int sco_running;                   /* 1 when sCO thread should be running */
227 +  pthread_t sco_thread;              /* SCO thread */
228 +  ast_mutex_t sco_lock;              /* SCO lock */
229 +  int sco_pos_in;                    /* Reader in position */
230 +  int sco_pos_out;                   /* Reader out position */
231 +  int sco_sending;                   /* Sending SCO packets */
232 +  char buf[1024];                    /* Incoming data buffer */
233 +  char sco_buf_out[BUFLEN+1];          /* 24 chunks of 48 */
234 +  char sco_buf_in[BUFLEN+1];           /* 24 chunks of 48 */
235 +
236 +  char dnid[1024];                    /* Outgoi gncall dialed number */
237 +  unsigned char * obuf[BLT_OBUF_LEN]; /* Outgoing data buffer */
238 +  int obuf_len;                       /* Output Buffer Position */
239 +  int obuf_wpos;                      /* Buffer Reader */
240 +
241 +  // device
242 +  int autoconnect;                  /* 1 for autoconnect */
243 +  int outgoing_id;                  /* Outgoing connection scheduler id */
244 +  char * name;                      /* Devices friendly name */
245 +  blt_role_t role;                  /* Device role (HS or AG) */
246 +  bdaddr_t bdaddr;                  /* remote address */
247 +  int channel;                      /* remote channel */
248 +  int rd;                           /* RFCOMM fd */
249 +  int tmp_rd;                       /* RFCOMM fd */
250 +  int call_cnt;                     /* Number of attempted calls */
251 +  ast_mutex_t lock;                 /* RFCOMM socket lock */
252 +  char rd_buff[BLT_RDBUFF_MAX];     /* RFCOMM input buffer */
253 +  int rd_buff_pos;                  /* RFCOMM input buffer position */
254 +  int ready;                        /* 1 When ready */
255 +
256 +  /* AG mode */
257 +  char last_ok_cmd[BLT_RDBUFF_MAX];        /* Runtime[AG]: Last AT command that was OK */
258 +  int cind;                                /* Runtime[AG]: Recieved +CIND */  
259 +  int call_pos, service_pos, callsetup_pos;  /* Runtime[AG]: Positions in CIND/CMER */
260 +  int call, service, callsetup;              /* Runtime[AG]: Values */
261 +
262 +  /* HS mode */
263 +  blt_state_t state;                       /* Runtime: Device state (AG mode only) */
264 +  int ring_timer;                          /* Runtime:Ring Timer */
265 +  char last_err_cmd[BLT_RDBUFF_MAX];       /* Runtime: Last AT command that was OK */
266 +  void (*cb)(blt_dev_t * dev, char * str); /* Runtime: Callback when in HS mode */
267 +
268 +  int brsf;                                /* Runtime: Bluetooth Retrieve Supported Features */
269 +  int bvra;                                /* Runtime: Bluetooth Voice Recognised Activation */
270 +  int gain_speaker;                        /* Runtime: Gain Of Speaker */
271 +  int clip;                                /* Runtime: Supports CLID */
272 +  int colp;                                /* Runtime: Connected Line ID */
273 +  int elip;                                /* Runtime: (Ericsson) Supports CLID */
274 +  int eolp;                                /* Runtime: (Ericsson) Connected Line ID */
275 +  int ringing;                             /* Runtime: Device is ringing */
276 +
277 +  blt_dev_t * next;                        /* Next in linked list */
278 +
279 +};
280 +
281 +typedef struct blt_atcb {
282 +
283 +  /* The command */
284 +  char * str;
285 +
286 +  /* DTE callbacks: */
287 +  int (*set)(blt_dev_t * dev, const char * arg, int len);
288 +  int (*read)(blt_dev_t * dev);
289 +  int (*execute)(blt_dev_t * dev, const char * data);
290 +  int (*test)(blt_dev_t * dev);
291 +
292 +  /* DCE callbacks: */
293 +  int (*unsolicited)(blt_dev_t * dev, const char * value);
294 +
295 +} blt_atcb_t;
296 +
297 +/* ---------------------------------- */
298 +
299 +static void rd_close(blt_dev_t * dev, int reconnect, int err);
300 +static int send_atcmd(blt_dev_t * device, const char * fmt, ...);
301 +static int sco_connect(blt_dev_t * dev);
302 +
303 +/* ---------------------------------- */
304 +
305 +/* RFCOMM channel we listen on*/
306 +static int rfcomm_channel_ag = BLT_DEFAULT_CHANNEL_AG;
307 +static int rfcomm_channel_hs = BLT_DEFAULT_CHANNEL_HS;
308 +
309 +/* Address of local bluetooth interface */
310 +static int hcidev_id;
311 +static bdaddr_t local_bdaddr;
312 +
313 +/* All the current sockets */
314 +AST_MUTEX_DEFINE_STATIC(iface_lock);
315 +static blt_dev_t * iface_head;
316 +static int ifcount = 0;
317 +
318 +static int sdp_record_hs = -1;
319 +static int sdp_record_ag = -1;
320 +
321 +/* RFCOMM listen socket */
322 +static int rfcomm_sock_ag = -1;
323 +static int rfcomm_sock_hs = -1;
324 +static int sco_socket = -1;
325 +
326 +static int monitor_pid = -1;
327 +
328 +/* The socket monitoring thread */
329 +static pthread_t monitor_thread = AST_PTHREADT_NULL;
330 +AST_MUTEX_DEFINE_STATIC(monitor_lock);
331 +
332 +/* Cound how many times this module is currently in use */
333 +static int usecnt = 0;
334 +AST_MUTEX_DEFINE_STATIC(usecnt_lock);
335 +
336 +static struct sched_context * sched = NULL;
337 +
338 +/* ---------------------------------- */
339 +
340 +static const char *
341 +role2str(blt_role_t role)
342 +{
343 +  switch (role) {
344 +    case BLT_ROLE_HS:
345 +      return "HS";
346 +    case BLT_ROLE_AG:
347 +      return "AG";
348 +    case BLT_ROLE_NONE:
349 +      return "??";
350 +  }
351 +}
352 +
353 +static const char *
354 +status2str(blt_status_t status)
355 +{
356 +  switch (status) {
357 +    case BLT_STATUS_DOWN:
358 +      return "Down";
359 +    case BLT_STATUS_CONNECTING:
360 +      return "Connecting";
361 +    case BLT_STATUS_NEGOTIATING:
362 +      return "Negotiating";
363 +    case BLT_STATUS_READY:
364 +      return "Ready";
365 +    case BLT_STATUS_RINGING:
366 +      return "Ringing";
367 +    case BLT_STATUS_IN_CALL:
368 +      return "InCall";
369 +  };
370 +  return "Unknown";
371 +}
372 +
373 +int sock_err(int fd)
374 +{
375 +  int ret;
376 +  int len = sizeof(ret);
377 +  getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
378 +  return ret;
379 +}
380 +
381 +/* ---------------------------------- */
382 +
383 +static const char *
384 +parse_cind(const char * str, char * name, int name_len)
385 +{
386 +  int c = 0;
387 +
388 +  memset(name, 0, name_len);
389 +
390 +  while (*str) {
391 +    if (*str == '(') {
392 +      if (++c == 1 && *(str+1) == '"') {
393 +        const char * start = str + 2;
394 +        int len = 0;
395 +        str += 2;
396 +        while (*str && *str != '"') {
397 +          len++;
398 +          str++;
399 +        }
400 +        if (len == 0)
401 +          return NULL;
402 +        strncpy(name, start, (len > name_len) ? name_len : len);
403 +      }
404 +    } else if (*str == ')')
405 +      c--;
406 +    else if (c == 0 && *str == ',')
407 +      return str + 1;
408 +    str++;
409 +  }
410 +  return NULL;
411 +}
412 +
413 +static void
414 +set_cind(blt_dev_t * dev, int indicator, int val)
415 +{
416 +
417 +  ast_log(LOG_DEBUG, "CIND %d set to %d\n", indicator, val);
418 +
419 +  if (indicator == dev->callsetup_pos) {
420 +
421 +    // call progress
422 +
423 +    dev->callsetup = val;
424 +
425 +    switch (val) {
426 +      case 3:
427 +        // Outgoign ringing
428 +        if (dev->owner && dev->role == BLT_ROLE_AG)
429 +          ast_queue_control(dev->owner, AST_CONTROL_RINGING);
430 +        break;
431 +      case 2:
432 +        break;
433 +      case 1:
434 +        break;
435 +      case 0:
436 +        if (dev->owner && dev->role == BLT_ROLE_AG && dev->call == 0)
437 +          ast_queue_control(dev->owner, AST_CONTROL_CONGESTION);
438 +        break;
439 +    }
440 +
441 +  } else if (indicator == dev->service_pos) {
442 +
443 +    // Signal
444 +
445 +    if (val == 0)
446 +      ast_log(LOG_NOTICE, "Audio Gateway %s lost signal\n", dev->name);
447 +    else if (dev->service == 0 && val > 0)
448 +      ast_log(LOG_NOTICE, "Audio Gateway %s got signal\n", dev->name);
449 +
450 +    dev->service = val;
451 +
452 +  } else if (indicator == dev->call_pos) {
453 +
454 +    // Call
455 +
456 +    dev->call = val;
457 +
458 +    if (dev->owner) {
459 +      if (val == 1) {
460 +        ast_queue_control(dev->owner, AST_CONTROL_ANSWER);
461 +      } else if (val == 0)
462 +        ast_queue_control(dev->owner, AST_CONTROL_HANGUP);
463 +    }
464 +
465 +  }
466 +
467 +
468 +}
469 +
470 +/* ---------------------------------- */
471 +
472 +int
473 +set_buffer(char * ring, char * data, int circular_len, int * pos, int data_len)
474 +{
475 +  int start_pos = *(pos);
476 +  int done = 0;
477 +  int copy;
478 +
479 +  while (data_len) {
480 +    // Set can_do to the most we can do in this copy.
481 +
482 +    copy = MIN(circular_len - start_pos, data_len);
483 +    memcpy(ring + start_pos, data + done, copy);
484 +
485 +    done += copy;
486 +    start_pos += copy;
487 +    data_len -= copy;
488 +
489 +    if (start_pos == circular_len)
490 +      start_pos = 0;
491 +  }
492 +  *(pos) = start_pos;
493 +  return 0;
494 +}
495 +
496 +int
497 +get_buffer(char * dst, char * ring, int ring_size, int * head, int to_copy)
498 +{
499 +  int copy;
500 +
501 +  // |1|2|3|4|5|6|7|8|9|
502 +  //      |-----|
503 +
504 +  while (to_copy) {
505 +
506 +    // Set can_do to the most we can do in this copy.
507 +    copy = MIN(ring_size - *head, to_copy);
508 +
509 +    // ast_log(LOG_DEBUG, "Getting: %d bytes, From pos %d\n", copy, *head);
510 +    memcpy(dst, ring + *head, copy);
511 +
512 +    dst += copy;
513 +    *head += copy;
514 +    to_copy -= copy;
515 +
516 +    if (*head == ring_size )
517 +      *head = 0;
518 +
519 +  }
520 +
521 +  return 0;
522 +}
523 +
524 +/* Handle SCO audio sync.
525 + *
526 + * If we are the MASTER, then we control the timing,
527 + * in 48 byte chunks.  If we're the SLAVE, we send
528 + * as and when we recieve a packet.
529 + *
530 + * Because of packet/timing nessecity, we 
531 + * start up a thread when we're passing audio, so
532 + * that things are timed exactly right.
533 + *
534 + * sco_thread() is the function that handles it.
535 + *
536 + */
537 +
538 +static void *
539 +sco_thread(void * data)
540 +{
541 +  blt_dev_t * dev = (blt_dev_t*)data;
542 +  int res;
543 +  struct pollfd pfd[2];
544 +  int in_pos = 0;
545 +  int out_pos = 0;
546 +  char c = 1;
547 +  int sending;
548 +  char buf[1024];
549 +  int len;
550 +
551 +  // Avoid deadlock in odd circumstances
552 +
553 +  ast_log(LOG_DEBUG, "SCO thread started on fd %d, pid %d\n", dev->sco, getpid());
554 +
555 +  // dev->status = BLT_STATUS_IN_CALL;
556 +  // ast_queue_control(dev->owner, AST_CONTROL_ANSWER);
557 +  // Set buffer to silence, just incase.
558 +
559 +  ast_mutex_lock(&(dev->sco_lock));
560 +
561 +  memset(dev->sco_buf_in,  0x7f, BUFLEN);
562 +  memset(dev->sco_buf_out, 0x7f, BUFLEN);
563 +
564 +  dev->sco_pos_in  = 0;
565 +  dev->sco_pos_out = 0;
566 +
567 +  ast_mutex_unlock(&(dev->sco_lock));
568 +
569 +  while (1) {
570 +
571 +    ast_mutex_lock(&(dev->sco_lock));
572 +
573 +    if (dev->sco_running != 1) {
574 +      ast_log(LOG_DEBUG, "SCO stopped.\n");
575 +      break;
576 +    }
577 +
578 +    pfd[0].fd = dev->sco;
579 +    pfd[0].events = POLLIN;
580 +
581 +    pfd[1].fd = dev->sco_pipe[1];
582 +    pfd[1].events = POLLIN;
583 +
584 +    ast_mutex_unlock(&(dev->sco_lock));
585 +
586 +    res = poll(pfd, 2, 50);
587 +
588 +    if (res == -1 && errno != EINTR) {
589 +      ast_log(LOG_DEBUG, "SCO poll() error\n");
590 +      break;
591 +    }
592 +
593 +    if (res == 0)
594 +      continue;
595 +
596 +    ast_mutex_lock(&(dev->sco_lock));
597 +
598 +    if (pfd[0].revents & POLLIN) {
599 +
600 +      len = read(dev->sco, buf, 48);
601 +
602 +      if (len) {
603 +        ast_mutex_lock(&(dev->lock));
604 +        set_buffer(dev->sco_buf_in,  buf, BUFLEN, &in_pos,  len);
605 +        get_buffer(buf, dev->sco_buf_out, BUFLEN, &out_pos, len);
606 +        write(dev->sco, buf, len);
607 +        if (dev->owner && dev->owner->_state == AST_STATE_UP)
608 +          write(dev->sco_pipe[1], &c, 1);
609 +        ast_mutex_unlock(&(dev->lock));
610 +      }
611 +
612 +      ast_mutex_unlock(&(dev->sco_lock));
613 +
614 +    } else if (pfd[0].revents) {
615 +
616 +      int e = sock_err(pfd[0].fd);
617 +      ast_log(LOG_ERROR, "SCO connection error: %s (errno %d)\n", strerror(e), e);
618 +      break;
619 +
620 +    } else if (pfd[1].revents & POLLIN) {
621 +
622 +      int len;
623 +
624 +      len = read(pfd[1].fd, &c, 1);
625 +      sending = (sending) ? 0 : 1;
626 +
627 +      ast_mutex_unlock(&(dev->sco_lock));
628 +
629 +    } else if (pfd[1].revents) {
630 +
631 +      int e = sock_err(pfd[1].fd);
632 +      ast_log(LOG_ERROR, "SCO pipe connection event %d on pipe[1]=%d: %s (errno %d)\n", pfd[1].revents, pfd[1].fd, strerror(e), e);
633 +      break;
634 +
635 +    } else {
636 +      ast_log(LOG_NOTICE, "Unhandled poll output\n");
637 +      ast_mutex_unlock(&(dev->sco_lock));
638 +    }
639 +
640 +  }
641 +
642 +  ast_mutex_lock(&(dev->lock));
643 +  close(dev->sco);
644 +  dev->sco = -1;
645 +  dev->sco_running = -1;
646 +  ast_mutex_unlock(&(dev->sco_lock));
647 +  if (dev->owner)
648 +    ast_queue_control(dev->owner, AST_CONTROL_HANGUP);
649 +  ast_mutex_unlock(&(dev->lock));
650 +  ast_log(LOG_DEBUG, "SCO thread stopped\n");
651 +  return NULL;
652 +}
653 +
654 +/* Start SCO thread.  Must be called with dev->lock */
655 +
656 +static int
657 +sco_start(blt_dev_t * dev, int fd)
658 +{
659 +
660 +  if (dev->sco_pipe[1] <= 0) {
661 +    ast_log(LOG_ERROR, "SCO pipe[1] == %d\n", dev->sco_pipe[1]);
662 +    return -1;
663 +  }
664 +
665 +  ast_mutex_lock(&(dev->sco_lock));
666 +
667 +  if (dev->sco_running != -1) {
668 +    ast_log(LOG_ERROR, "Tried to start SCO thread while already running\n");
669 +    ast_mutex_unlock(&(dev->sco_lock));
670 +    return -1;
671 +  }
672 +
673 +  if (dev->sco == -1) {
674 +    if (fd > 0) {
675 +      dev->sco = fd;
676 +    } else if (sco_connect(dev) != 0) {
677 +      ast_log(LOG_ERROR, "SCO fd invalid\n");
678 +      ast_mutex_unlock(&(dev->sco_lock));
679 +      return -1;
680 +    }
681 +  }
682 +
683 +  dev->sco_running = 1;
684 +
685 +  if (ast_pthread_create(&(dev->sco_thread), NULL, sco_thread, dev) < 0) {
686 +    ast_log(LOG_ERROR, "Unable to start SCO thread.\n");
687 +    dev->sco_running = -1;
688 +    ast_mutex_unlock(&(dev->sco_lock));
689 +    return -1;
690 +  }
691 +
692 +  ast_mutex_unlock(&(dev->sco_lock));
693 +
694 +  return 0;
695 +}
696 +
697 +/* Stop SCO thread.  Must be called with dev->lock */
698 +
699 +static int
700 +sco_stop(blt_dev_t * dev)
701 +{
702 +  ast_mutex_lock(&(dev->sco_lock));
703 +  if (dev->sco_running == 1)
704 +    dev->sco_running = 0;
705 +  else
706 +    dev->sco_running = -1;
707 +  dev->sco_sending = 0;
708 +  ast_mutex_unlock(&(dev->sco_lock));
709 +  return 0;
710 +}
711 +
712 +/* ---------------------------------- */
713 +
714 +/* Answer the call.  Call with lock held on device */
715 +
716 +static int
717 +answer(blt_dev_t * dev)
718 +{
719 +
720 +  if ( (!dev->owner) || (dev->ready != 1) || (dev->status != BLT_STATUS_READY && dev->status != BLT_STATUS_RINGING)) {
721 +    ast_log(LOG_ERROR, "Attempt to answer() in invalid state (owner=%p, ready=%d, status=%s)\n", 
722 +              dev->owner, dev->ready, status2str(dev->status));
723 +    return -1;
724 +  }
725 +
726 +    // dev->sd = sco_connect(&local_bdaddr, &(dev->bdaddr), NULL, NULL, 0);
727 +    // dev->status = BLT_STATUS_IN_CALL;
728 +    // dev->owner->fds[0] = dev->sd;
729 +    //  if we are answering (hitting button):
730 +  ast_queue_control(dev->owner, AST_CONTROL_ANSWER);
731 +    //  if asterisk signals us to answer:
732 +    // ast_setstate(ast, AST_STATE_UP);
733 +
734 +  /* Start SCO link */
735 +  sco_start(dev, -1);
736 +  return 0;
737 +}
738 +
739 +/* ---------------------------------- */
740 +
741 +static int 
742 +blt_write(struct ast_channel * ast, struct ast_frame * frame)
743 +{
744 +  blt_dev_t * dev = ast->pvt->pvt; 
745 +
746 +  /* Write a frame of (presumably voice) data */
747 +
748 +  if (frame->frametype != AST_FRAME_VOICE) {
749 +    ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
750 +    return 0;
751 +  }
752 +
753 +  if (!(frame->subclass & BLUETOOTH_FORMAT)) {
754 +    ast_log(LOG_WARNING, "Cannot handle frames in format %d\n", frame->subclass);
755 +    return 0;
756 +  }
757 +
758 +  if (ast->_state != AST_STATE_UP) {
759 +    return 0;
760 +  }
761 +
762 +  ast_mutex_lock(&(dev->sco_lock));
763 +  set_buffer(dev->sco_buf_out, frame->data, BUFLEN, &(dev->sco_pos_out), MIN(frame->datalen, BUFLEN));
764 +  ast_mutex_unlock(&(dev->sco_lock));
765 +
766 +  return 0;
767 +
768 +}
769 +
770 +static struct ast_frame *
771 +blt_read(struct ast_channel * ast)
772 +{
773 +  blt_dev_t * dev = ast->pvt->pvt;
774 +  char c = 1;
775 +  int len;
776 +
777 +  /* Some nice norms */
778 +
779 +  dev->fr.datalen = 0;
780 +  dev->fr.samples = 0;
781 +  dev->fr.data =  NULL;
782 +  dev->fr.src = BLT_CHAN_NAME;
783 +  dev->fr.offset = 0;
784 +  dev->fr.mallocd = 0;
785 +  dev->fr.delivery.tv_sec = 0;
786 +  dev->fr.delivery.tv_usec = 0;
787 +
788 +  ast_mutex_lock(&(dev->sco_lock));
789 +  dev->sco_sending = 1;
790 +  read(dev->sco_pipe[0], &c, 1);
791 +  len = get_buffer(dev->buf, dev->sco_buf_in, BUFLEN, &(dev->sco_pos_in), 48);
792 +  ast_mutex_unlock(&(dev->sco_lock));
793 +
794 +  dev->fr.data = dev->buf;
795 +  dev->fr.samples = len / 2;
796 +  dev->fr.datalen = len;
797 +  dev->fr.frametype = AST_FRAME_VOICE;
798 +  dev->fr.subclass = BLUETOOTH_FORMAT;
799 +  dev->fr.offset = 0;
800 +
801 +  return &dev->fr;
802 +}
803 +
804 +/* Escape Any '"' in str.  Return malloc()ed string */
805 +static char *
806 +escape_str(char * str)
807 +{
808 +  char * ptr = str;
809 +  char * pret;
810 +  char * ret;
811 +  int len = 0;
812 +
813 +  while (*ptr) {
814 +    if (*ptr == '"')
815 +      len++;
816 +    len++;
817 +    ptr++;
818 +  }
819 +
820 +  ret = malloc(len + 1);
821 +  pret = memset(ret, 0, len + 1);
822 +
823 +  ptr = str;
824 +  
825 +  while (*ptr) {
826 +    if (*ptr == '"')
827 +      *pret++ = '\\';
828 +    *pret++ = *ptr++;
829 +  }
830 +
831 +  return ret;
832 +}
833 +
834 +static int
835 +ring_hs(blt_dev_t * dev)
836 +{
837 +#if (ASTERISK_VERSION_NUM < 010100)
838 +  char tmp[AST_MAX_EXTENSION];
839 +  char *name, *num;
840 +#endif
841 +
842 +  ast_mutex_lock(&(dev->lock));
843 +
844 +  if (dev->owner == NULL) {
845 +    ast_mutex_unlock(&(dev->lock));
846 +    return 0;
847 +  } 
848 +
849 +  dev->ringing = 1;
850 +  dev->status = BLT_STATUS_RINGING;
851 +
852 +  send_atcmd(dev, "RING");
853 +
854 +  dev->owner->rings++;
855 +
856 +  // XXX:T: '"' needs to be escaped in ELIP.
857 +
858 +#if (ASTERISK_VERSION_NUM < 010100)
859 +
860 +  if (dev->owner->callerid) {
861 +
862 +    memset(tmp, 0, sizeof(tmp));
863 +    strncpy(tmp, dev->owner->callerid, sizeof(tmp)-1);
864 +
865 +    if (!ast_callerid_parse(tmp, &name, &num)) {
866 +
867 +      if (dev->clip && num)
868 +        send_atcmd(dev, "+CLIP: \"%s\",129", num);
869 +
870 +      if (dev->elip && name) {
871 +        char * esc = escape_str(name);
872 +        send_atcmd(dev, "*ELIP: \"%s\"", esc);
873 +        free(esc);
874 +      }
875 +    }
876 +  }
877 +
878 +
879 +#else
880 +
881 +  if (dev->clip && dev->owner->cid.cid_num)
882 +    send_atcmd(dev, "+CLIP: \"%s\",129", dev->owner->cid.cid_num);
883 +
884 +  if (dev->elip && dev->owner->cid.cid_name) {
885 +    char * esc = escape_str(dev->owner->cid.cid_name);
886 +    send_atcmd(dev, "*ELIP: \"%s\"", esc);
887 +    free(esc);
888 +  }
889 +
890 +#endif
891 +
892 +  ast_mutex_unlock(&(dev->lock));
893 +
894 +  return 1;
895 +}
896 +
897 +/*
898 + * If the HS is already connected, then just send RING, otherwise, things get a
899 + * little more sticky.  We first have to find the channel for HS using SDP, 
900 + * then intiate the connection.  Once we've done that, we can start the call.
901 + */
902 +
903 +static int
904 +blt_call(struct ast_channel * ast, char * dest, int timeout)
905 +{
906 +  blt_dev_t * dev = ast->pvt->pvt;
907 +
908 +  if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
909 +    ast_log(LOG_WARNING, "blt_call called on %s, neither down nor reserved\n", ast->name);
910 +    return -1;
911 +  }
912 +
913 +  ast_log(LOG_DEBUG, "Calling %s on %s [t: %d]\n", dest, ast->name, timeout);
914 +
915 +  if (ast_mutex_lock(&iface_lock)) {
916 +    ast_log(LOG_ERROR, "Failed to get iface_lock.\n");
917 +    return -1;
918 +  }
919 +
920 +//  ast_mutex_lock(&(dev->lock));
921 +
922 +  if (dev->ready == 0) {
923 +    ast_log(LOG_WARNING, "Tried to call a device not ready/connected.\n");
924 +    ast_setstate(ast, AST_CONTROL_CONGESTION);
925 +//    ast_mutex_unlock(&(dev->lock));
926 +    ast_mutex_unlock(&iface_lock);
927 +    return 0;
928 +  }
929 +
930 +  if (dev->role == BLT_ROLE_HS) {
931 +
932 +    send_atcmd(dev, "+CIEV: 3,1");
933 +
934 +    dev->ring_timer = ast_sched_add(sched, 5000, AST_SCHED_CB(ring_hs), dev);
935 +
936 +    ring_hs(dev);
937 +
938 +    ast_setstate(ast, AST_STATE_RINGING);
939 +    ast_queue_control(ast, AST_CONTROL_RINGING);
940 +
941 +  } else if (dev->role == BLT_ROLE_AG) {
942 +
943 +    send_atcmd(dev, "ATD%s;", dev->dnid);
944 +
945 +  } else {
946 +
947 +    ast_setstate(ast, AST_CONTROL_CONGESTION);
948 +    ast_log(LOG_ERROR, "Unknown device role\n");
949 +
950 +  }
951 +
952 +//  ast_mutex_unlock(&(dev->lock));
953 +  ast_mutex_unlock(&iface_lock);
954 +
955 +  return 0;
956 +}
957 +
958 +static int 
959 +blt_hangup(struct ast_channel * ast)
960 +{
961 +  blt_dev_t * dev = ast->pvt->pvt;
962 +
963 +  ast_log(LOG_DEBUG, "blt_hangup(%s)\n", ast->name);
964 +
965 +  if (!ast->pvt->pvt) {
966 +    ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
967 +    return 0;
968 +  }
969 +
970 +  if (ast_mutex_lock(&iface_lock)) {
971 +    ast_log(LOG_ERROR, "Failed to get iface_lock\n");
972 +    return 0;
973 +  }
974 +
975 +  ast_mutex_lock(&(dev->lock));
976 +
977 +  sco_stop(dev);
978 +  dev->sco_sending = 0;
979 +
980 +  if (dev->role == BLT_ROLE_HS) {
981 +
982 +    if (dev->ringing == 0) {
983 +      // Actual call in progress
984 +      send_atcmd(dev, "+CIEV: 2,0");
985 +    } else {
986 +
987 +      // Just ringing still
988 +
989 +      if (dev->role == BLT_ROLE_HS)
990 +        send_atcmd(dev, "+CIEV: 3,0");
991 +
992 +      if (dev->ring_timer >= 0)
993 +        ast_sched_del(sched, dev->ring_timer);
994 +
995 +      dev->ring_timer = -1;
996 +      dev->ringing = 0;
997 +
998 +    }
999 +
1000 +  } else if (dev->role == BLT_ROLE_AG) {
1001 +
1002 +    // Cancel call.
1003 +    send_atcmd(dev, "AT+CHUP");
1004 +
1005 +  }
1006 +
1007 +  if (dev->status == BLT_STATUS_IN_CALL || dev->status == BLT_STATUS_RINGING)
1008 +    dev->status = BLT_STATUS_READY;
1009 +
1010 +  ast->pvt->pvt = NULL;
1011 +  dev->owner = NULL;
1012 +  ast_mutex_unlock(&(dev->lock));
1013 +  ast_setstate(ast, AST_STATE_DOWN);
1014 +  ast_mutex_unlock(&(iface_lock));
1015 +
1016 +  return 0;
1017 +}
1018 +
1019 +static int 
1020 +blt_indicate(struct ast_channel * c, int condition)
1021 +{
1022 +  ast_log(LOG_DEBUG, "blt_indicate (%d)\n", condition);
1023 +
1024 +  switch(condition) {
1025 +    case AST_CONTROL_RINGING:
1026 +      return -1;
1027 +    default:
1028 +      ast_log(LOG_WARNING, "Don't know how to condition %d\n", condition);
1029 +      break;
1030 +  }
1031 +  return -1;
1032 +}
1033 +
1034 +static int
1035 +blt_answer(struct ast_channel * ast)
1036 +{
1037 +  blt_dev_t * dev = ast->pvt->pvt;
1038 +
1039 +  ast_mutex_lock(&dev->lock);
1040 +
1041 +  // if (dev->ring_timer >= 0)
1042 +  //   ast_sched_del(sched, dev->ring_timer);
1043 +  // dev->ring_timer = -1;
1044 +
1045 +  ast_log(LOG_DEBUG, "Answering interface\n");
1046 +
1047 +  if (ast->_state != AST_STATE_UP) {
1048 +    send_atcmd(dev, "+CIEV: 2,1");
1049 +    send_atcmd(dev, "+CIEV: 3,0");
1050 +    sco_start(dev, -1);
1051 +    ast_setstate(ast, AST_STATE_UP);
1052 +  }
1053 +
1054 +  ast_mutex_unlock(&dev->lock);
1055 +
1056 +  return 0;
1057 +}
1058 +
1059 +static struct ast_channel *
1060 +blt_new(blt_dev_t * dev, int state, const char * context, const char * number)
1061 +{
1062 +  struct ast_channel * ast;
1063 +  char c = 0;
1064 +
1065 +  if ((ast = ast_channel_alloc(1)) == NULL) {
1066 +    ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
1067 +    return NULL;
1068 +  }
1069 +
1070 +  snprintf(ast->name, sizeof(ast->name), "BLT/%s", dev->name);
1071 +
1072 +  // ast->fds[0] = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
1073 +
1074 +  ast->nativeformats       = BLUETOOTH_FORMAT;
1075 +  ast->pvt->rawreadformat  = BLUETOOTH_FORMAT;
1076 +  ast->pvt->rawwriteformat = BLUETOOTH_FORMAT;
1077 +  ast->writeformat         = BLUETOOTH_FORMAT;
1078 +  ast->readformat          = BLUETOOTH_FORMAT;
1079 +
1080 +  ast_setstate(ast, state);
1081 +
1082 +  ast->type = BLT_CHAN_NAME;
1083 +
1084 +  ast->pvt->pvt = dev;
1085 +
1086 +  ast->pvt->call     = blt_call;
1087 +  ast->pvt->indicate = blt_indicate;
1088 +  ast->pvt->hangup   = blt_hangup;
1089 +  ast->pvt->read     = blt_read;
1090 +  ast->pvt->write    = blt_write;
1091 +  ast->pvt->answer   = blt_answer;
1092 +
1093 +  strncpy(ast->context, context, sizeof(ast->context)-1);
1094 +  strncpy(ast->exten,   number,  sizeof(ast->exten) - 1);
1095 +
1096 +  ast->language[0] = '\0';
1097 +
1098 +  ast->fds[0] = dev->sco_pipe[0];
1099 +  write(dev->sco_pipe[1], &c, 1);
1100 +
1101 +  dev->owner = ast;
1102 +
1103 +  ast_mutex_lock(&usecnt_lock);
1104 +  usecnt++;
1105 +  ast_mutex_unlock(&usecnt_lock);
1106 +
1107 +  ast_update_use_count();
1108 +
1109 +  if (state != AST_STATE_DOWN) {
1110 +    if (ast_pbx_start(ast)) {
1111 +      ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast->name);
1112 +      ast_hangup(ast);
1113 +    }
1114 +  }
1115 +
1116 +  return ast;
1117 +}
1118 +
1119 +static struct ast_channel *
1120 +#if (ASTERISK_VERSION_NUM < 010100)
1121 +blt_request(char * type, int format, void * local_data)
1122 +#else
1123 +blt_request(const char * type, int format, void * local_data)
1124 +#endif
1125 +{
1126 +  char * data = (char*)local_data;
1127 +  int oldformat;
1128 +  blt_dev_t * dev = NULL;
1129 +  struct ast_channel * ast = NULL;
1130 +  char * number = data, * dname;
1131 +
1132 +  dname = strsep(&number, "/");
1133 +
1134 +  oldformat = format;
1135 +
1136 +  format &= BLUETOOTH_FORMAT;
1137 +
1138 +  if (!format) {
1139 +    ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
1140 +    return NULL;
1141 +  }
1142 +
1143 +  ast_log(LOG_DEBUG, "Dialing '%s' via '%s'\n", number, dname);
1144 +
1145 +  if (ast_mutex_lock(&iface_lock)) {
1146 +    ast_log(LOG_ERROR, "Unable to lock iface_list\n");
1147 +    return NULL;
1148 +  }
1149 +
1150 +  dev = iface_head;
1151 +
1152 +  while (dev) {
1153 +    if (strcmp(dev->name, dname) == 0) {
1154 +      ast_mutex_lock(&(dev->lock));
1155 +      if (!dev->ready) {
1156 +        ast_log(LOG_ERROR, "Device %s is not connected\n", dev->name);
1157 +        ast_mutex_unlock(&(dev->lock));
1158 +        ast_mutex_unlock(&iface_lock);
1159 +        return NULL;
1160 +      }
1161 +      break;
1162 +    }
1163 +    dev = dev->next;
1164 +  }
1165 +
1166 +  ast_mutex_unlock(&iface_lock);
1167 +
1168 +  if (!dev) {
1169 +    ast_log(LOG_WARNING, "Failed to find device named '%s'\n", dname);
1170 +    return NULL;
1171 +  }
1172 +
1173 +  if (number && dev->role != BLT_ROLE_AG) {
1174 +    ast_log(LOG_WARNING, "Tried to send a call out on non AG\n");
1175 +    ast_mutex_unlock(&(dev->lock));
1176 +    return NULL;
1177 +  }
1178 +
1179 +  if (dev->role == BLT_ROLE_AG)
1180 +    strncpy(dev->dnid, number, sizeof(dev->dnid) - 1);
1181 +
1182 +  ast = blt_new(dev, AST_STATE_DOWN, "bluetooth", "s");
1183 +
1184 +  ast_mutex_unlock(&(dev->lock));
1185 +
1186 +  return ast;
1187 +}
1188 +
1189 +/* ---------------------------------- */
1190 +
1191 +
1192 +/* ---- AT COMMAND SOCKET STUFF ---- */
1193 +
1194 +static int
1195 +send_atcmd(blt_dev_t * dev, const char * fmt, ...)
1196 +{
1197 +  char buf[1024];
1198 +  va_list ap;
1199 +  int len;
1200 +
1201 +  va_start(ap, fmt);
1202 +  len = vsnprintf(buf, 1023, fmt, ap);
1203 +  va_end(ap);
1204 +
1205 +  if (option_verbose)
1206 +    ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s < %s\n", role2str(dev->role), 10, dev->name, buf);
1207 +
1208 +  write(dev->rd, "\r\n", 2);
1209 +  len = write(dev->rd, buf, len);
1210 +  write(dev->rd, "\r\n", 2);
1211 +  return (len) ? 0 : -1;
1212 +}
1213 +
1214 +
1215 +static int
1216 +send_atcmd_ok(blt_dev_t * dev, const char * cmd)
1217 +{
1218 +  int len;
1219 +  strncpy(dev->last_ok_cmd, cmd, BLT_RDBUFF_MAX - 1);
1220 +  if (option_verbose)
1221 +    ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s < OK\n", role2str(dev->role), 10, dev->name);
1222 +  len = write(dev->rd, "\r\nOK\r\n", 6);
1223 +  return (len) ? 0 : -1;
1224 +}
1225 +
1226 +static int
1227 +send_atcmd_error(blt_dev_t * dev)
1228 +{
1229 +  int len;
1230 +
1231 +  if (option_verbose)
1232 +    ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s < ERROR\n", role2str(dev->role), 10, dev->name);
1233 +
1234 +//  write(dev->rd, "\r\n", 2);
1235 +//  len = write(dev->rd, dev->last_ok_cmd, 5);
1236 +  write(dev->rd, "\r\n", 2);
1237 +  len = write(dev->rd, "ERROR", 5);
1238 +  write(dev->rd, "\r\n", 2);
1239 +
1240 +  return (len) ? 0 : -1;
1241 +}
1242 +
1243 +
1244 +/* ---------------------------------- */
1245 +
1246 +/* -- Handle negotiation when we're an AG -- */
1247 +
1248 +/* Bluetooth Support */
1249 +
1250 +static int
1251 +atcmd_brsf_set(blt_dev_t * dev, const char * arg, int len)
1252 +{
1253 +  ast_log(LOG_DEBUG, "Device Supports: %s\n", arg);
1254 +  dev->brsf = atoi(arg);
1255 +  send_atcmd(dev, "+BRSF: %d", 23);
1256 +  return 0;
1257 +}
1258 +
1259 +/* Bluetooth Voice Recognition */
1260 +
1261 +static int
1262 +atcmd_bvra_set(blt_dev_t * dev, const char * arg, int len)
1263 +{
1264 +  ast_log(LOG_WARNING, "+BVRA Not Yet Supported\n");
1265 +  return -1;
1266 +#if 0
1267 +  // XXX:T: Fix voice recognition somehow!
1268 +  int action = atoi(arg);
1269 +  ast_log(LOG_DEBUG, "Voice Recognition: %s\n", (a) ? "ACTIVATED" : "DEACTIVATED");
1270 +  if ((action == 0) & (dev->bvra == 1)) {
1271 +    /* Disable it */
1272 +    dev->bvra = 0;
1273 +    // XXX:T: Shutdown any active bvra channel
1274 +    ast_log(LOG_DEBUG, "Voice Recognition: DISABLED\n");
1275 +  } else if ((action == 1) && (dev->bvra == 0)) {
1276 +    /* Enable it */
1277 +    dev->bvra = 1;
1278 +    // XXX:T: Schedule connection to voice recognition extension/application
1279 +    ast_log(LOG_DEBUG, "Voice Recognition: ENABLED\n");
1280 +  } else {
1281 +    ast_log(LOG_ERROR, "+BVRA out of sync (we think %d, but HS wants %d)\n", dev->bvra, action);
1282 +    return -1;
1283 +  }
1284 +  return 0;
1285 +#endif
1286 +}
1287 +
1288 +/* Clock */
1289 +
1290 +static int
1291 +atcmd_cclk_read(blt_dev_t * dev)
1292 +{
1293 +  struct tm t, *tp;
1294 +  const time_t ti = time(0);
1295 +  tp = localtime_r(&ti, &t);
1296 +  send_atcmd(dev, "+CCLK: \"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"", 
1297 +                  (tp->tm_year % 100), (tp->tm_mon + 1), (tp->tm_mday),
1298 +                  tp->tm_hour, tp->tm_min, tp->tm_sec, ((tp->tm_gmtoff / 60) / 15));
1299 +  return 0;
1300 +}
1301 +
1302 +/* CHUP - Hangup Call */
1303 +
1304 +static int
1305 +atcmd_chup_execute(blt_dev_t * dev, const char * data)
1306 +{
1307 +  if (!dev->owner) {
1308 +    ast_log(LOG_ERROR, "Request to hangup call when none in progress\n");
1309 +    return -1;
1310 +  }
1311 +  ast_log(LOG_DEBUG, "Hangup Call\n");
1312 +  ast_queue_control(dev->owner, AST_CONTROL_HANGUP);
1313 +  return 0;
1314 +}
1315 +
1316 +/* CIND - Call Indicator */
1317 +
1318 +static int
1319 +atcmd_cind_read(blt_dev_t * dev)
1320 +{
1321 +  send_atcmd(dev, "+CIND: 1,0,0");
1322 +  return 0;
1323 +}
1324 +
1325 +static int
1326 +atcmd_cind_test(blt_dev_t * dev)
1327 +{
1328 +  send_atcmd(dev, "+CIND: (\"service\",(0,1)),(\"call\",(0,1)),(\"callsetup\",(0-4))");
1329 +  return 0;
1330 +}
1331 +
1332 +/* Set Language */
1333 +
1334 +static int
1335 +atcmd_clan_read(blt_dev_t * dev)
1336 +{
1337 +  send_atcmd(dev, "+CLAN: \"en\"");
1338 +  return 0;
1339 +}
1340 +
1341 +/* Caller Id Presentation */
1342 +
1343 +static int
1344 +atcmd_clip_set(blt_dev_t * dev, const char * arg, int len)
1345 +{
1346 +  dev->clip = atoi(arg);
1347 +  return 0;
1348 +}
1349 +
1350 +/* Conneced Line Identification Presentation */
1351 +
1352 +static int
1353 +atcmd_colp_set(blt_dev_t * dev, const char * arg, int len)
1354 +{
1355 +  dev->colp = atoi(arg);
1356 +  return 0;
1357 +}
1358 +
1359 +/* CMER - Mobile Equipment Event Reporting */
1360 +
1361 +static int
1362 +atcmd_cmer_set(blt_dev_t * dev, const char * arg, int len)
1363 +{
1364 +  dev->ready = 1;
1365 +  dev->status = BLT_STATUS_READY;
1366 +  return 0;
1367 +}
1368 +
1369 +/* PhoneBook Types:
1370 + *
1371 + *  - FD - SIM Fixed Dialing Phone Book
1372 + *  - ME - ME Phone book
1373 + *  - SM - SIM Phone Book
1374 + *  - DC - ME dialled-calls list
1375 + *  - RC - ME recieved-calls lisr
1376 + *  - MC - ME missed-calls list
1377 + *  - MV - ME Voice Activated Dialing List
1378 + *  - HP - Hierachial Phone Book
1379 + *  - BC - Own Business Card (PIN2 required)
1380 + *
1381 + */
1382 +
1383 +/* Read Phone Book Entry */
1384 +
1385 +static int
1386 +atcmd_cpbr_set(blt_dev_t * dev, const char * arg, int len)
1387 +{
1388 +  // XXX:T: Fix the phone book!
1389 +  // * Maybe add res_phonebook or something? */
1390 +  send_atcmd(dev, "+CPBR: %d,\"%s\",128,\"%s\"", atoi(arg), arg, arg);
1391 +  return 0;
1392 +}
1393 +
1394 +/* Select Phone Book */
1395 +
1396 +static int
1397 +atcmd_cpbs_set(blt_dev_t * dev, const char * arg, int len)
1398 +{
1399 +  // XXX:T: I guess we'll just accept any?
1400 +  return 0;
1401 +}
1402 +
1403 +static int
1404 +atcmd_cscs_set(blt_dev_t * dev, const char * arg, int len)
1405 +{
1406 +  // XXX:T: Language
1407 +  return 0;
1408 +}
1409 +
1410 +static int
1411 +atcmd_eips_set(blt_dev_t * dev, const char * arg, int len)
1412 +{
1413 +  ast_log(LOG_DEBUG, "Identify Presentation Set: %s=%s\n",
1414 +                         (*(arg) == 49) ? "ELIP" : "EOLP",
1415 +                         (*(arg+2) == 49) ? "ON" : "OFF");
1416 +
1417 +  if (*(arg) == 49)
1418 +    dev->eolp = (*(arg+2) == 49) ? 1 : 0;
1419 +  else
1420 +    dev->elip = (*(arg+2) == 49) ? 1 : 0;
1421 +
1422 +  return 0;
1423 +}
1424 +
1425 +/* VGS - Speaker Volume Gain */
1426 +
1427 +static int
1428 +atcmd_vgs_set(blt_dev_t * dev, const char * arg, int len)
1429 +{
1430 +  dev->gain_speaker = atoi(arg);
1431 +  return 0;
1432 +}
1433 +
1434 +/* Dial */
1435 +static int
1436 +atcmd_dial_execute(blt_dev_t * dev, const char * data)
1437 +{
1438 +  char * number = NULL;
1439 +
1440 +  /* Make sure there is a ';' at the end of the line */
1441 +  if (*(data + (strlen(data) - 1)) != ';') {
1442 +    ast_log(LOG_WARNING, "Can't dial non-voice right now: %s\n", data);
1443 +    return -1;
1444 +  }
1445 +
1446 +  number = strndup(data, strlen(data) - 1);
1447 +  ast_log(LOG_NOTICE, "Dial: [%s]\n", number);
1448 +
1449 +  send_atcmd(dev, "+CIEV: 2,1");
1450 +  send_atcmd(dev, "+CIEV: 3,0");
1451 +
1452 +  sco_start(dev, -1);
1453 +
1454 +  if (blt_new(dev, AST_STATE_UP, "bluetooth", number) == NULL) {
1455 +    sco_stop(dev);
1456 +  }
1457 +
1458 +  free(number);
1459 +
1460 +  return 0;
1461 +}
1462 +
1463 +/* Answer */
1464 +
1465 +static int
1466 +atcmd_answer_execute(blt_dev_t * dev, const char * data)
1467 +{
1468 +
1469 +  if (!dev->ringing || !dev->owner) {
1470 +    ast_log(LOG_WARNING, "Can't answer non existant call\n");
1471 +    return -1;
1472 +  }
1473 +
1474 +  dev->ringing = 0;
1475 +
1476 +  if (dev->ring_timer >= 0)
1477 +    ast_sched_del(sched, dev->ring_timer);
1478 +
1479 +  dev->ring_timer = -1;
1480 +
1481 +  send_atcmd(dev, "+CIEV: 2,1");
1482 +  send_atcmd(dev, "+CIEV: 3,0");
1483 +
1484 +  return answer(dev);
1485 +}
1486 +
1487 +static int
1488 +ag_unsol_ciev(blt_dev_t * dev, const char * data)
1489 +{
1490 +  const char * orig = data;
1491 +  int indicator;
1492 +  int status;
1493 +
1494 +  while (*(data) && *(data) == ' ')
1495 +    data++;
1496 +
1497 +  if (*(data) == 0) {
1498 +    ast_log(LOG_WARNING, "Invalid value[1] for '+CIEV:%s'\n", orig);
1499 +    return -1;
1500 +  }
1501 +
1502 +  indicator = *(data++) - 48;
1503 +
1504 +  if (*(data++) != ',') {
1505 +    ast_log(LOG_WARNING, "Invalid value[2] for '+CIEV:%s'\n", orig);
1506 +    return -1;
1507 +  }
1508 +
1509 +  if (*(data) == 0) {
1510 +    ast_log(LOG_WARNING, "Invalid value[3] for '+CIEV:%s'\n", orig);
1511 +    return -1;
1512 +  }
1513 +
1514 +  status = *(data) - 48;
1515 +
1516 +  set_cind(dev, indicator, status);
1517 +
1518 +  return 0;
1519 +}
1520 +
1521 +static int
1522 +ag_unsol_cind(blt_dev_t * dev, const char * data)
1523 +{
1524 +
1525 +  while (*(data) && *(data) == ' ')
1526 +    data++;
1527 +
1528 +
1529 +  if (dev->cind == 0)
1530 +  {
1531 +    int pos = 1;
1532 +    char name[1024];
1533 +
1534 +    while ((data = parse_cind(data, name, 1023)) != NULL) {
1535 +      ast_log(LOG_DEBUG, "CIND: %d=%s\n", pos, name);
1536 +      if (strcmp(name, "call") == 0)
1537 +        dev->call_pos = pos;
1538 +      else if (strcmp(name, "service") == 0)
1539 +        dev->service_pos = pos;
1540 +      else if (strcmp(name, "call_setup") == 0 || strcmp(name, "callsetup") == 0)
1541 +        dev->callsetup_pos = pos;
1542 +      pos++;
1543 +    }
1544 +
1545 +    ast_log(LOG_DEBUG, "CIND: %d=%s\n", pos, name);
1546 +
1547 +  } else {
1548 +
1549 +    int pos = 1, len = 0;
1550 +    char val[128];
1551 +    const char * start = data;
1552 +
1553 +    while (*data) {
1554 +      if (*data == ',') {
1555 +        memset(val, 0, 128);
1556 +        strncpy(val, start, len);
1557 +        set_cind(dev, pos, atoi(val));
1558 +        pos++;
1559 +        len = 0;
1560 +        data++;
1561 +        start = data;
1562 +        continue;
1563 +      }
1564 +      len++;
1565 +      data++;
1566 +    }
1567 +
1568 +    memset(val, 0, 128);
1569 +    strncpy(val, start, len);
1570 +    ast_log(LOG_DEBUG, "CIND IND %d set to %d [%s]\n", pos, atoi(val), val);
1571 +
1572 +
1573 +  }
1574 +
1575 +  return 0;
1576 +}
1577 +
1578 +static blt_atcb_t
1579 +atcmd_list[] = 
1580 +{
1581 +  { "A",     NULL,           NULL,            atcmd_answer_execute, NULL,             NULL },
1582 +  { "D",     NULL,           NULL,            atcmd_dial_execute,   NULL,             NULL },
1583 +  { "+BRSF", atcmd_brsf_set, NULL,            NULL,                 NULL,             NULL },
1584 +  { "+BVRA", atcmd_bvra_set, NULL,            NULL,                 NULL,             NULL },
1585 +  { "+CCLK", NULL,           atcmd_cclk_read, NULL,                 NULL,             NULL },
1586 +  { "+CHUP", NULL,           NULL,            atcmd_chup_execute,   NULL,             NULL },
1587 +  { "+CIEV", NULL,           NULL,            NULL,                 NULL,             ag_unsol_ciev },
1588 +  { "+CIND", NULL,           atcmd_cind_read, NULL,                 atcmd_cind_test,  ag_unsol_cind },
1589 +  { "+CLAN", NULL,           atcmd_clan_read, NULL,                 NULL,             NULL },
1590 +  { "+CLIP", atcmd_clip_set, NULL,            NULL,                 NULL,             NULL },
1591 +  { "+COLP", atcmd_colp_set, NULL,            NULL,                 NULL,             NULL },
1592 +  { "+CMER", atcmd_cmer_set, NULL,            NULL,                 NULL,             NULL },
1593 +  { "+CPBR", atcmd_cpbr_set, NULL,            NULL,                 NULL,             NULL },
1594 +  { "+CPBS", atcmd_cpbs_set, NULL,            NULL,                 NULL,             NULL },
1595 +  { "+CSCS", atcmd_cscs_set, NULL,            NULL,                 NULL,             NULL },
1596 +  { "*EIPS", atcmd_eips_set, NULL,            NULL,                 NULL,             NULL },
1597 +  { "+VGS",  atcmd_vgs_set,  NULL,            NULL,                 NULL,             NULL },
1598 +};
1599 +
1600 +#define ATCMD_LIST_LEN (sizeof(atcmd_list) / sizeof(blt_atcb_t))
1601 +
1602 +/* ---------------------------------- */
1603 +
1604 +/* -- Handle negotiation when we're a HS -- */
1605 +
1606 +void
1607 +ag_unknown_response(blt_dev_t * dev, char * cmd)
1608 +{
1609 +  ast_log(LOG_DEBUG, "Got UNKN response: %s\n", cmd);
1610 +
1611 +  // DELAYED
1612 +  // NO CARRIER
1613 +
1614 +}
1615 +
1616 +void
1617 +ag_cgmi_response(blt_dev_t * dev, char * cmd)
1618 +{
1619 +  // CGMM - Phone Model
1620 +  // CGMR - Phone Revision
1621 +  // CGSN - IMEI
1622 +  // AT*
1623 +  // VTS - send tone
1624 +  // CREG
1625 +  // CBC - BATTERY
1626 +  // CSQ - SIGANL
1627 +  // CSMS - SMS STUFFS
1628 +  //  CMGL
1629 +  //  CMGR
1630 +  //  CMGS
1631 +  // CSCA - sms CENTER NUMBER
1632 +  // CNMI - SMS INDICATION
1633 +  // ast_log(LOG_DEBUG, "Manufacturer: %s\n", cmd);
1634 +  dev->cb = ag_unknown_response;
1635 +}
1636 +
1637 +void
1638 +ag_cgmi_valid_response(blt_dev_t * dev, char * cmd)
1639 +{
1640 +  // send_atcmd(dev, "AT+WS46?");
1641 +  // send_atcmd(dev, "AT+CRC=1");
1642 +  // send_atcmd(dev, "AT+CNUM");
1643 +
1644 +  if (strcmp(cmd, "OK") == 0) {
1645 +    send_atcmd(dev, "AT+CGMI");
1646 +    dev->cb = ag_cgmi_response;
1647 +  } else {
1648 +    dev->cb = ag_unknown_response;
1649 +  }
1650 +}
1651 +
1652 +void
1653 +ag_clip_response(blt_dev_t * dev, char * cmd)
1654 +{
1655 +  send_atcmd(dev, "AT+CGMI=?");
1656 +  dev->cb = ag_cgmi_valid_response;
1657 +}
1658 +
1659 +void
1660 +ag_cmer_response(blt_dev_t * dev, char * cmd)
1661 +{
1662 +  dev->cb = ag_clip_response;
1663 +  dev->ready = 1;
1664 +  dev->status = BLT_STATUS_READY;
1665 +  send_atcmd(dev, "AT+CLIP=1");
1666 +}
1667 +
1668 +void
1669 +ag_cind_status_response(blt_dev_t * dev, char * cmd)
1670 +{
1671 +  // XXX:T: Handle response.
1672 +  dev->cb = ag_cmer_response;
1673 +  send_atcmd(dev, "AT+CMER=3,0,0,1");
1674 +  // Initiase SCO link!
1675 +}
1676 +
1677 +void
1678 +ag_cind_response(blt_dev_t * dev, char * cmd)
1679 +{
1680 +  dev->cb = ag_cind_status_response;
1681 +  dev->cind = 1;
1682 +  send_atcmd(dev, "AT+CIND?");
1683 +}
1684 +
1685 +void
1686 +ag_brsf_response(blt_dev_t * dev, char * cmd)
1687 +{
1688 +  dev->cb = ag_cind_response;
1689 +  ast_log(LOG_DEBUG, "Bluetooth features: %s\n", cmd);
1690 +  dev->cind = 0;
1691 +  send_atcmd(dev, "AT+CIND=?");
1692 +}
1693 +
1694 +/* ---------------------------------- */
1695 +
1696 +static int
1697 +sdp_register(sdp_session_t * session)
1698 +{
1699 +  // XXX:T: Fix this horrible function so it makes some sense and is extensible!
1700 +  sdp_list_t *svclass_id, *pfseq, *apseq, *root;
1701 +  uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid;
1702 +  sdp_profile_desc_t profile;
1703 +  sdp_list_t *aproto, *proto[2];
1704 +  sdp_record_t record;
1705 +  uint8_t u8 = rfcomm_channel_ag;
1706 +  uint8_t u8_hs = rfcomm_channel_hs;
1707 +  sdp_data_t *channel;
1708 +  int ret = 0;
1709 +
1710 +  memset((void *)&record, 0, sizeof(sdp_record_t));
1711 +  record.handle = 0xffffffff;
1712 +  sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1713 +  root = sdp_list_append(0, &root_uuid);
1714 +  sdp_set_browse_groups(&record, root);
1715 +
1716 +  // Register as an AG
1717 +
1718 +  sdp_uuid16_create(&svclass_uuid, HANDSFREE_AUDIO_GW_SVCLASS_ID);
1719 +  svclass_id = sdp_list_append(0, &svclass_uuid);
1720 +  sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1721 +  svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1722 +  sdp_set_service_classes(&record, svclass_id);
1723 +  sdp_uuid16_create(&profile.uuid, 0x111f);
1724 +  profile.version = 0x0100;
1725 +  pfseq = sdp_list_append(0, &profile);
1726 +
1727 +  sdp_set_profile_descs(&record, pfseq);
1728 +
1729 +  sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1730 +  proto[0] = sdp_list_append(0, &l2cap_uuid);
1731 +  apseq = sdp_list_append(0, proto[0]);
1732 +
1733 +  sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1734 +  proto[1] = sdp_list_append(0, &rfcomm_uuid);
1735 +  channel = sdp_data_alloc(SDP_UINT8, &u8);
1736 +  proto[1] = sdp_list_append(proto[1], channel);
1737 +  apseq = sdp_list_append(apseq, proto[1]);
1738 +
1739 +  aproto = sdp_list_append(0, apseq);
1740 +  sdp_set_access_protos(&record, aproto);
1741 +
1742 +  sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
1743 +
1744 +  if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
1745 +    ast_log(LOG_ERROR, "Service Record registration failed\n");
1746 +    ret = -1;
1747 +    goto end;
1748 +  }
1749 +
1750 +  sdp_record_ag = record.handle;
1751 +
1752 +  ast_log(LOG_NOTICE, "HeadsetAudioGateway service registered\n");
1753 +
1754 +  sdp_data_free(channel);
1755 +  sdp_list_free(proto[0], 0);
1756 +  sdp_list_free(proto[1], 0);
1757 +  sdp_list_free(apseq, 0);
1758 +  sdp_list_free(aproto, 0);
1759 +
1760 +  // -------------
1761 +
1762 +  memset((void *)&record, 0, sizeof(sdp_record_t));
1763 +  record.handle = 0xffffffff;
1764 +  sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
1765 +  root = sdp_list_append(0, &root_uuid);
1766 +  sdp_set_browse_groups(&record, root);
1767 +
1768 +  // Register as an HS
1769 +
1770 +  sdp_uuid16_create(&svclass_uuid, HANDSFREE_AUDIO_GW_SVCLASS_ID);
1771 +  svclass_id = sdp_list_append(0, &svclass_uuid);
1772 +  sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
1773 +  svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
1774 +  sdp_set_service_classes(&record, svclass_id);
1775 +  sdp_uuid16_create(&profile.uuid, 0x111e);
1776 +  profile.version = 0x0100;
1777 +  pfseq = sdp_list_append(0, &profile);
1778 +  sdp_set_profile_descs(&record, pfseq);
1779 +
1780 +  sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
1781 +  proto[0] = sdp_list_append(0, &l2cap_uuid);
1782 +  apseq = sdp_list_append(0, proto[0]);
1783 +
1784 +  sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
1785 +  proto[1] = sdp_list_append(0, &rfcomm_uuid);
1786 +  channel = sdp_data_alloc(SDP_UINT8, &u8_hs);
1787 +  proto[1] = sdp_list_append(proto[1], channel);
1788 +  apseq = sdp_list_append(apseq, proto[1]);
1789 +
1790 +  aproto = sdp_list_append(0, apseq);
1791 +  sdp_set_access_protos(&record, aproto);
1792 +  sdp_set_info_attr(&record, "Voice Gateway", 0, 0);
1793 +
1794 +  if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
1795 +    ast_log(LOG_ERROR, "Service Record registration failed\n");
1796 +    ret = -1;
1797 +    goto end;
1798 +  }
1799 +
1800 +  sdp_record_hs = record.handle;
1801 +
1802 +  ast_log(LOG_NOTICE, "HeadsetAudioGateway service registered\n");
1803 +
1804 +end:
1805 +  sdp_data_free(channel);
1806 +  sdp_list_free(proto[0], 0);
1807 +  sdp_list_free(proto[1], 0);
1808 +  sdp_list_free(apseq, 0);
1809 +  sdp_list_free(aproto, 0);
1810 +
1811 +  return ret;
1812 +}
1813 +
1814 +static int
1815 +rfcomm_listen(bdaddr_t * bdaddr, int channel)
1816 +{
1817 +
1818 +  int sock = -1;
1819 +  struct sockaddr_rc loc_addr;
1820 +  int on = 1;
1821 +
1822 +  if ((sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
1823 +    ast_log(LOG_ERROR, "Can't create socket: %s (errno: %d)\n", strerror(errno), errno);
1824 +    return -1;
1825 +  }
1826 +
1827 +  loc_addr.rc_family = AF_BLUETOOTH;
1828 +
1829 +  /* Local Interface Address */
1830 +  bacpy(&loc_addr.rc_bdaddr, bdaddr);
1831 +
1832 +  /* Channel */
1833 +  loc_addr.rc_channel = channel;
1834 +
1835 +  if (bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) < 0) {
1836 +    ast_log(LOG_ERROR, "Can't bind socket: %s (errno: %d)\n", strerror(errno), errno);
1837 +    close(sock);
1838 +    return -1;
1839 +  }
1840 +
1841 +  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
1842 +    ast_log(LOG_ERROR, "Set socket SO_REUSEADDR option on failed: errno %d, %s", errno, strerror(errno));
1843 +    close(sock);
1844 +    return -1;
1845 +  }
1846 +
1847 +  if (fcntl(sock, F_SETFL, O_RDWR|O_NONBLOCK) != 0)
1848 +    ast_log(LOG_ERROR, "Can't set RFCOMM socket to NBIO\n");
1849 +
1850 +  if (listen(sock, 10) < 0) {
1851 +    ast_log(LOG_ERROR,"Can not listen on the socket. %s(%d)\n", strerror(errno), errno);
1852 +    close(sock);
1853 +    return -1;
1854 +  }
1855 +
1856 +  ast_log(LOG_NOTICE, "Listening for RFCOMM channel %d connections on FD %d\n", channel, sock);
1857 +
1858 +  return sock;
1859 +}
1860 +
1861 +
1862 +static int
1863 +sco_listen(bdaddr_t * bdaddr)
1864 +{
1865 +  int sock = -1;
1866 +  int on = 1;
1867 +  struct sockaddr_sco loc_addr;
1868 +
1869 +  memset(&loc_addr, 0, sizeof(loc_addr));
1870 +
1871 +  if ((sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
1872 +    ast_log(LOG_ERROR, "Can't create SCO socket: %s (errno: %d)\n", strerror(errno), errno);
1873 +    return -1;
1874 +  }
1875 +
1876 +  loc_addr.sco_family = AF_BLUETOOTH;
1877 +  bacpy(&loc_addr.sco_bdaddr, BDADDR_ANY);
1878 +
1879 +  if (bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) < 0) {
1880 +    ast_log(LOG_ERROR, "Can't bind SCO socket: %s (errno: %d)\n", strerror(errno), errno);
1881 +    close(sock);
1882 +    return -1;
1883 +  }
1884 +
1885 +  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
1886 +    ast_log(LOG_ERROR, "Set SCO socket SO_REUSEADDR option on failed: errno %d, %s", errno, strerror(errno));
1887 +    close(sock);
1888 +    return -1;
1889 +  }
1890 +
1891 +  if (fcntl(sock, F_SETFL, O_RDWR|O_NONBLOCK) != 0)
1892 +    ast_log(LOG_ERROR, "Can't set SCO socket to NBIO\n");
1893 +
1894 +  if (listen(sock, 10) < 0) {
1895 +    ast_log(LOG_ERROR,"Can not listen on SCO socket: %s(%d)\n", strerror(errno), errno);
1896 +    close(sock);
1897 +    return -1;
1898 +  }
1899 +
1900 +  ast_log(LOG_NOTICE, "Listening for SCO connections on FD %d\n", sock);
1901 +
1902 +  return sock;
1903 +}
1904 +
1905 +static int
1906 +rfcomm_connect(bdaddr_t * src, bdaddr_t * dst, int channel, int nbio)
1907 +{
1908 +  struct sockaddr_rc addr;
1909 +  int s;
1910 +
1911 +  if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
1912 +    return -1;
1913 +  }
1914 +
1915 +  memset(&addr, 0, sizeof(addr));
1916 +  addr.rc_family = AF_BLUETOOTH;
1917 +  bacpy(&addr.rc_bdaddr, src);
1918 +  addr.rc_channel = 0;
1919 +
1920 +  if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1921 +    close(s);
1922 +    return -1;
1923 +  }
1924 +
1925 +  memset(&addr, 0, sizeof(addr));
1926 +  addr.rc_family = AF_BLUETOOTH;
1927 +  bacpy(&addr.rc_bdaddr, dst);
1928 +  addr.rc_channel = channel;
1929 +
1930 +  if (nbio) {
1931 +    if (fcntl(s, F_SETFL, O_RDWR|O_NONBLOCK) != 0)
1932 +      ast_log(LOG_ERROR, "Can't set RFCOMM socket to NBIO\n");
1933 +  }
1934 +
1935 +  if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 && (nbio != 1 || (errno != EAGAIN))) {
1936 +    close(s);
1937 +    return -1;
1938 +  }
1939 +
1940 +  return s;
1941 +}
1942 +
1943 +/* Must be called with dev->lock held */
1944 +
1945 +static int
1946 +sco_connect(blt_dev_t * dev)
1947 +{
1948 +  struct sockaddr_sco addr;
1949 +  // struct sco_conninfo conn;
1950 +  // struct sco_options opts;
1951 +  // int size;
1952 +  // bdaddr_t * src = &local_bdaddr;
1953 +
1954 +  int s;
1955 +  bdaddr_t * dst = &(dev->bdaddr);
1956 +
1957 +  if (dev->sco != -1) {
1958 +    ast_log(LOG_ERROR, "SCO fd already open.\n");
1959 +    return -1;
1960 +  }
1961 +
1962 +  if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
1963 +    ast_log(LOG_ERROR, "Can't create SCO socket(): %s\n", strerror(errno));
1964 +    return -1;
1965 +  }
1966 +
1967 +  memset(&addr, 0, sizeof(addr));
1968 +
1969 +  addr.sco_family = AF_BLUETOOTH;
1970 +  bacpy(&addr.sco_bdaddr, BDADDR_ANY);
1971 +
1972 +  if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1973 +    ast_log(LOG_ERROR, "Can't bind() SCO socket: %s\n", strerror(errno));
1974 +    close(s);
1975 +    return -1;
1976 +  }
1977 +
1978 +  memset(&addr, 0, sizeof(addr));
1979 +  addr.sco_family = AF_BLUETOOTH;
1980 +  bacpy(&addr.sco_bdaddr, dst);
1981 +
1982 +  if (fcntl(s, F_SETFL, O_RDWR|O_NONBLOCK) != 0)
1983 +    ast_log(LOG_ERROR, "Can't set SCO socket to NBIO\n");
1984 +
1985 +  if ((connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) && (errno != EAGAIN)) {
1986 +    ast_log(LOG_ERROR, "Can't connect() SCO socket: %s (errno %d)\n", strerror(errno), errno);
1987 +    close(s);
1988 +    return -1;
1989 +  }
1990 +
1991 +  //size = sizeof(conn);
1992 +
1993 +
1994 +/* XXX:T: HERE, fix getting SCO conninfo.
1995 +
1996 +  if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) {
1997 +    ast_log(LOG_ERROR, "Can't getsockopt SCO_CONNINFO on SCO socket: %s\n", strerror(errno));
1998 +    close(s);
1999 +    return -1;
2000 +  }
2001 +
2002 +  size = sizeof(opts);
2003 +
2004 +  if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) {
2005 +    ast_log(LOG_ERROR, "Can't getsockopt SCO_OPTIONS on SCO socket: %s\n", strerror(errno));
2006 +    close(s);
2007 +    return -1;
2008 +  }
2009 +
2010 +  dev->sco_handle = conn.hci_handle;
2011 +  dev->sco_mtu = opts.mtu;
2012 +
2013 +*/
2014 +
2015 +  ast_log(LOG_DEBUG, "SCO: %d\n", s);
2016 +
2017 +  dev->sco = s;
2018 +
2019 +  return 0;
2020 +}
2021 +
2022 +
2023 +/* ---------------------------------- */
2024 +
2025 +/* Non blocking (async) outgoing bluetooth connection */
2026 +
2027 +static int
2028 +try_connect(blt_dev_t * dev)
2029 +{
2030 +  int fd;
2031 +  ast_mutex_lock(&(dev->lock));
2032 +
2033 +  if (dev->status != BLT_STATUS_CONNECTING && dev->status != BLT_STATUS_DOWN) {
2034 +    ast_mutex_unlock(&(dev->lock));
2035 +    return 0;
2036 +  }
2037 +
2038 +  if (dev->rd != -1) {
2039 +
2040 +    int ret;
2041 +    struct pollfd pfd;
2042 +
2043 +    if (dev->status != BLT_STATUS_CONNECTING) {
2044 +      ast_mutex_unlock(&(dev->lock));
2045 +      dev->outgoing_id = -1;
2046 +      return 0;
2047 +    }
2048 +
2049 +    // ret = connect(dev->rd, (struct sockaddr *)&(dev->addr), sizeof(struct sockaddr_rc)); // 
2050 +
2051 +    pfd.fd = dev->rd;
2052 +    pfd.events = POLLIN | POLLOUT;
2053 +
2054 +    ret = poll(&pfd, 1, 0);
2055 +
2056 +    if (ret == -1) {
2057 +      close(dev->rd);
2058 +      dev->rd = -1;
2059 +      dev->status = BLT_STATUS_DOWN;
2060 +      dev->outgoing_id = ast_sched_add(sched, 10000, AST_SCHED_CB(try_connect), dev);
2061 +      ast_mutex_unlock(&(dev->lock));
2062 +      return 0;
2063 +    }
2064 +
2065 +    if (ret > 0) {
2066 +
2067 +      int len = sizeof(ret);
2068 +      getsockopt(dev->rd, SOL_SOCKET, SO_ERROR, &ret, &len);
2069 +
2070 +      if (ret == 0) {
2071 +
2072 +        ast_log(LOG_NOTICE, "Initialised bluetooth link to device %s\n", dev->name); 
2073 +
2074 +#if 0
2075 +        {
2076 +          struct hci_conn_info_req * cr;
2077 +          int dd;
2078 +          char name[248];
2079 +
2080 +          cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
2081 +          dd = hci_open_dev(hcidev_id);
2082 +          cr->type = ACL_LINK;
2083 +          bacpy(&cr->bdaddr, &(dev->bdaddr));
2084 +
2085 +          if (ioctl(dd, HCIGETCONNINFO, (unsigned long)cr) < 0) {
2086 +            ast_log(LOG_ERROR, "Failed to get connection info: %s\n", strerror(errno));
2087 +          } else {
2088 +            ast_log(LOG_DEBUG, "HCI Handle: %d\n", cr->conn_info->handle);
2089 +          }
2090 +
2091 +          if (hci_read_remote_name(dd, &(dev->bdaddr), sizeof(name), name, 25000) == 0)
2092 +            ast_log(LOG_DEBUG, "Remote Name: %s\n", name);
2093 +          free(cr);
2094 +        }
2095 +#endif
2096 +
2097 +        dev->status = BLT_STATUS_NEGOTIATING;
2098 +
2099 +        /* If this device is a AG, we initiate the negotiation. */
2100 +
2101 +        if (dev->role == BLT_ROLE_AG) {
2102 +          dev->cb = ag_brsf_response;
2103 +          send_atcmd(dev, "AT+BRSF=23");
2104 +        }
2105 +
2106 +        dev->outgoing_id = -1;
2107 +        ast_mutex_unlock(&(dev->lock));
2108 +        return 0;
2109 +
2110 +      } else {
2111 +
2112 +        if (ret != EHOSTDOWN)
2113 +          ast_log(LOG_NOTICE, "Connect to device %s failed: %s (errno %d)\n", dev->name, strerror(ret), ret);
2114 +
2115 +        close(dev->rd);
2116 +        dev->rd = -1;
2117 +        dev->status = BLT_STATUS_DOWN;
2118 +        dev->outgoing_id = ast_sched_add(sched, (ret == EHOSTDOWN) ? 10000 : 2500, AST_SCHED_CB(try_connect), dev);
2119 +        ast_mutex_unlock(&(dev->lock));
2120 +        return 0;
2121 +
2122 +      }
2123 +
2124 +    }
2125 +
2126 +    dev->outgoing_id = ast_sched_add(sched, 100, AST_SCHED_CB(try_connect), dev);
2127 +    ast_mutex_unlock(&(dev->lock));
2128 +    return 0;
2129 +  }
2130 +
2131 +  fd = rfcomm_connect(&local_bdaddr, &(dev->bdaddr), dev->channel, 1);
2132 +
2133 +  if (fd == -1) {
2134 +    ast_log(LOG_WARNING, "NBIO connect() to %s returned %d: %s\n", dev->name, errno, strerror(errno));
2135 +    dev->outgoing_id = ast_sched_add(sched, 5000, AST_SCHED_CB(try_connect), dev);
2136 +    ast_mutex_unlock(&(dev->lock));
2137 +    return 0;
2138 +  }
2139 +
2140 +  dev->rd = fd;
2141 +  dev->status = BLT_STATUS_CONNECTING;
2142 +  dev->outgoing_id = ast_sched_add(sched, 100, AST_SCHED_CB(try_connect), dev);
2143 +  ast_mutex_unlock(&(dev->lock));
2144 +  return 0;
2145 +}
2146 +
2147 +
2148 +/* Called whenever a new command is recieved while we're the AG */
2149 +
2150 +
2151 +static int
2152 +process_rfcomm_cmd(blt_dev_t * dev, char * cmd)
2153 +{
2154 +  int i;
2155 +  char * fullcmd = cmd;
2156 +
2157 +  if (option_verbose)
2158 +    ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s > %s\n", role2str(dev->role), 10, dev->name, cmd);
2159 +
2160 +  /* Read the 'AT' from the start of the string */
2161 +  if (strncmp(cmd, "AT", 2)) {
2162 +    ast_log(LOG_WARNING, "Unknown command without 'AT': %s\n", cmd);
2163 +    send_atcmd_error(dev);
2164 +    return 0;
2165 +  }
2166 +
2167 +  cmd += 2;
2168 +
2169 +  // Don't forget 'AT' on it's own is OK.
2170 +
2171 +  if (strlen(cmd) == 0) {
2172 +    send_atcmd_ok(dev, fullcmd);
2173 +    return 0;
2174 +  }
2175 +
2176 +  for (i = 0 ; i < ATCMD_LIST_LEN ; i++) {
2177 +    if (strncmp(atcmd_list[i].str, cmd, strlen(atcmd_list[i].str)) == 0) {
2178 +      char * pos = (cmd + strlen(atcmd_list[i].str));
2179 +      if ((strncmp(pos, "=?", 2) == 0) && (strlen(pos) == 2)) {
2180 +        /* TEST command */
2181 +        if (atcmd_list[i].test) {
2182 +          if (atcmd_list[i].test(dev) == 0)
2183 +            send_atcmd_ok(dev, fullcmd);
2184 +          else
2185 +            send_atcmd_error(dev);
2186 +        } else {
2187 +          send_atcmd_ok(dev, fullcmd);
2188 +        }
2189 +      } else if ((strncmp(pos, "?", 1) == 0) && (strlen(pos) == 1)) {
2190 +        /* READ command */
2191 +        if (atcmd_list[i].read) {
2192 +          if (atcmd_list[i].read(dev) == 0)
2193 +            send_atcmd_ok(dev, fullcmd);
2194 +          else
2195 +            send_atcmd_error(dev);
2196 +        } else {
2197 +          ast_log(LOG_WARNING, "AT Command: '%s' missing READ function\n", fullcmd);
2198 +          send_atcmd_error(dev);
2199 +        }
2200 +      } else if (strncmp(pos, "=", 1) == 0) {
2201 +        /* SET command */
2202 +        if (atcmd_list[i].set) {
2203 +          if (atcmd_list[i].set(dev, (pos + 1), (*(pos + 1)) ? strlen(pos + 1) : 0) == 0)
2204 +            send_atcmd_ok(dev, fullcmd);
2205 +          else
2206 +            send_atcmd_error(dev);
2207 +        } else {
2208 +          ast_log(LOG_WARNING, "AT Command: '%s' missing SET function\n", fullcmd);
2209 +          send_atcmd_error(dev);
2210 +        }
2211 +      } else {
2212 +        /* EXECUTE command */
2213 +        if (atcmd_list[i].execute) {
2214 +          if (atcmd_list[i].execute(dev, cmd + strlen(atcmd_list[i].str)) == 0)
2215 +            send_atcmd_ok(dev, fullcmd);
2216 +          else
2217 +            send_atcmd_error(dev);
2218 +        } else {
2219 +          ast_log(LOG_WARNING, "AT Command: '%s' missing EXECUTE function\n", fullcmd);
2220 +          send_atcmd_error(dev);
2221 +        }
2222 +      }
2223 +      return 0;
2224 +    }
2225 +  }
2226 +
2227 +  ast_log(LOG_WARNING, "Unknown AT Command: '%s' (%s)\n", fullcmd, cmd);
2228 +  send_atcmd_error(dev);
2229 +
2230 +  return 0;
2231 +}
2232 +
2233 +/* Called when a socket is incoming */
2234 +
2235 +static void
2236 +handle_incoming(int fd, blt_role_t role)
2237 +{
2238 +  blt_dev_t * dev;
2239 +  struct sockaddr_rc addr;
2240 +  int len = sizeof(addr);
2241 +
2242 +  // Got a new incoming socket.
2243 +  ast_log(LOG_DEBUG, "Incoming RFCOMM socket\n");
2244 +
2245 +  ast_mutex_lock(&iface_lock);
2246 +
2247 +  fd = accept(fd, (struct sockaddr*)&addr, &len);
2248 +
2249 +  dev = iface_head;
2250 +  while (dev) {
2251 +    if (bacmp(&(dev->bdaddr), &addr.rc_bdaddr) == 0) {
2252 +      ast_log(LOG_DEBUG, "Connect from %s\n", dev->name);
2253 +      ast_mutex_lock(&(dev->lock));
2254 +      /* Kill any outstanding connect attempt. */
2255 +      if (dev->outgoing_id > -1) {
2256 +        ast_sched_del(sched, dev->outgoing_id);
2257 +        dev->outgoing_id = -1;
2258 +      }
2259 +
2260 +      rd_close(dev, 0, 0);
2261 +
2262 +      dev->status = BLT_STATUS_NEGOTIATING;
2263 +      dev->rd = fd;
2264 +
2265 +      if (dev->role == BLT_ROLE_AG) {
2266 +        dev->cb = ag_brsf_response;
2267 +        send_atcmd(dev, "AT+BRSF=23");
2268 +      }
2269 +
2270 +      ast_mutex_unlock(&(dev->lock));
2271 +      break;
2272 +    }
2273 +    dev = dev->next;
2274 +  }
2275 +
2276 +  if (dev == NULL) {
2277 +    ast_log(LOG_WARNING, "Connect from unknown device\n");
2278 +    close(fd);
2279 +  }
2280 +  ast_mutex_unlock(&iface_lock);
2281 +
2282 +  return;
2283 +}
2284 +
2285 +static void
2286 +handle_incoming_sco(int master)
2287 +{
2288 +
2289 +  blt_dev_t * dev;
2290 +  struct sockaddr_sco addr;
2291 +  struct sco_conninfo conn;
2292 +  struct sco_options opts;
2293 +  int len = sizeof(addr);
2294 +  int fd;
2295 +
2296 +  ast_log(LOG_DEBUG, "Incoming SCO socket\n");
2297 +
2298 +  fd = accept(master, (struct sockaddr*)&addr, &len);
2299 +
2300 +  if (fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK) != 0) {
2301 +    ast_log(LOG_ERROR, "Can't set SCO socket to NBIO\n");
2302 +    close(fd);
2303 +    return;
2304 +  }
2305 +
2306 +  len = sizeof(conn);
2307 +
2308 +  if (getsockopt(fd, SOL_SCO, SCO_CONNINFO, &conn, &len) < 0) {
2309 +    ast_log(LOG_ERROR, "Can't getsockopt SCO_CONNINFO on SCO socket: %s\n", strerror(errno));
2310 +    close(fd);
2311 +    return;
2312 +  }
2313 +
2314 +  len = sizeof(opts);
2315 +
2316 +  if (getsockopt(fd, SOL_SCO, SCO_OPTIONS, &opts, &len) < 0) {
2317 +    ast_log(LOG_ERROR, "Can't getsockopt SCO_OPTIONS on SCO socket: %s\n", strerror(errno));
2318 +    close(fd);
2319 +    return;
2320 +  }
2321 +
2322 +  ast_mutex_lock(&iface_lock);
2323 +  dev = iface_head;
2324 +  while (dev) {
2325 +    if (bacmp(&(dev->bdaddr), &addr.sco_bdaddr) == 0) {
2326 +      ast_log(LOG_DEBUG, "SCO Connect from %s\n", dev->name);
2327 +      ast_mutex_lock(&(dev->lock));
2328 +      if (dev->sco_running != -1) {
2329 +        ast_log(LOG_ERROR, "Incoming SCO socket, but SCO thread already running.\n");
2330 +      } else {
2331 +        sco_start(dev, fd);
2332 +      }
2333 +      ast_mutex_unlock(&(dev->lock));
2334 +      break;
2335 +    }
2336 +    dev = dev->next;
2337 +  }
2338 +
2339 +  ast_mutex_unlock(&iface_lock);
2340 +
2341 +  if (dev == NULL) {
2342 +    ast_log(LOG_WARNING, "SCO Connect from unknown device\n");
2343 +    close(fd);
2344 +  } else {
2345 +    // XXX:T: We need to handle the fact we might have an outgoing connection attempt in progress.
2346 +    ast_log(LOG_DEBUG, "SCO: %d, HCIHandle=%d, MUT=%d\n", fd, conn.hci_handle, opts.mtu);
2347 +  }
2348 +
2349 +
2350 +
2351 +  return;
2352 +}
2353 +
2354 +/* Called when there is data waiting on a socket */
2355 +
2356 +static int
2357 +handle_rd_data(blt_dev_t * dev)
2358 +{
2359 +  char c;
2360 +  int ret;
2361 +
2362 +  while ((ret = read(dev->rd, &c, 1)) == 1) {
2363 +
2364 +    // log_buf[i++] = c;
2365 +
2366 +    if (dev->role == BLT_ROLE_HS) {
2367 +
2368 +      if (c == '\r') {
2369 +        ret = process_rfcomm_cmd(dev, dev->rd_buff);
2370 +        dev->rd_buff_pos = 0;
2371 +        memset(dev->rd_buff, 0, BLT_RDBUFF_MAX);
2372 +        return ret;
2373 +      }
2374 +
2375 +      if (dev->rd_buff_pos >= BLT_RDBUFF_MAX)
2376 +        return 0;
2377 +
2378 +      dev->rd_buff[dev->rd_buff_pos++] = c;
2379 +
2380 +    } else if (dev->role == BLT_ROLE_AG) {
2381 +
2382 +      switch (dev->state) {
2383 +
2384 +        case BLT_STATE_WANT_R:
2385 +          if (c == '\r') {
2386 +            dev->state = BLT_STATE_WANT_N;
2387 +          } else if (c == '+') {
2388 +            dev->state = BLT_STATE_WANT_CMD;
2389 +            dev->rd_buff[dev->rd_buff_pos++] = '+';
2390 +          } else {
2391 +            ast_log(LOG_ERROR, "Device %s: Expected '\\r', got %d. state=BLT_STATE_WANT_R\n", dev->name, c);
2392 +            return -1;
2393 +          }
2394 +          break;
2395 +
2396 +        case BLT_STATE_WANT_N:
2397 +          if (c == '\n')
2398 +            dev->state = BLT_STATE_WANT_CMD;
2399 +          else {
2400 +            ast_log(LOG_ERROR, "Device %s: Expected '\\n', got %d. state=BLT_STATE_WANT_N\n", dev->name, c);
2401 +            return -1;
2402 +          }
2403 +          break;
2404 +
2405 +        case BLT_STATE_WANT_CMD:
2406 +          if (c == '\r')
2407 +            dev->state = BLT_STATE_WANT_N2;
2408 +          else {
2409 +            if (dev->rd_buff_pos >= BLT_RDBUFF_MAX) {
2410 +              ast_log(LOG_ERROR, "Device %s: Buffer exceeded\n", dev->name);
2411 +              return -1;
2412 +            }
2413 +            dev->rd_buff[dev->rd_buff_pos++] = c;
2414 +          }
2415 +          break;
2416 +
2417 +        case BLT_STATE_WANT_N2:
2418 +          if (c == '\n') {
2419 +
2420 +            dev->state = BLT_STATE_WANT_R;
2421 +
2422 +            if (dev->rd_buff[0] == '+') {
2423 +              int i;
2424 +              // find unsolicited
2425 +              for (i = 0 ; i < ATCMD_LIST_LEN ; i++) {
2426 +                if (strncmp(atcmd_list[i].str, dev->rd_buff, strlen(atcmd_list[i].str)) == 0) {
2427 +                  if (atcmd_list[i].unsolicited)
2428 +                    atcmd_list[i].unsolicited(dev, dev->rd_buff + strlen(atcmd_list[i].str) + 1);
2429 +                  else
2430 +                    ast_log(LOG_WARNING, "Device %s: Unhandled Unsolicited: %s\n", dev->name, dev->rd_buff);
2431 +                  break;
2432 +                }
2433 +              }
2434 +
2435 +              if (option_verbose)
2436 +                ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s > %s\n", role2str(dev->role), 10, dev->name, dev->rd_buff);
2437 +
2438 +              if (i == ATCMD_LIST_LEN)
2439 +                ast_log(LOG_DEBUG, "Device %s: Got unsolicited message: %s\n", dev->name, dev->rd_buff);
2440 +
2441 +            } else {
2442 +
2443 +              if (
2444 +                strcmp(dev->rd_buff, "OK") != 0 && 
2445 +                strcmp(dev->rd_buff, "CONNECT") != 0 &&
2446 +                strcmp(dev->rd_buff, "RING") != 0 &&
2447 +                strcmp(dev->rd_buff, "NO CARRIER") != 0 && 
2448 +                strcmp(dev->rd_buff, "ERROR") != 0 &&
2449 +                strcmp(dev->rd_buff, "NO DIALTONE") != 0 && 
2450 +                strcmp(dev->rd_buff, "BUSY") != 0 && 
2451 +                strcmp(dev->rd_buff, "NO ANSWER") != 0 && 
2452 +                strcmp(dev->rd_buff, "DELAYED") != 0
2453 +              ){
2454 +                // It must be a multiline error
2455 +                strncpy(dev->last_err_cmd, dev->rd_buff, 1023);
2456 +                if (option_verbose)
2457 +                  ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s > %s\n", role2str(dev->role), 10, dev->name, dev->rd_buff);
2458 +              } else if (dev->cb) {
2459 +                if (option_verbose)
2460 +                  ast_verbose(VERBOSE_PREFIX_1 "[%s] %*s > %s\n", role2str(dev->role), 10, dev->name, dev->rd_buff);
2461 +                dev->cb(dev, dev->rd_buff);
2462 +              } else {
2463 +                ast_log(LOG_ERROR, "Device %s: Data on socket in HS mode, but no callback\n", dev->name);
2464 +              }
2465 +
2466 +            }
2467 +
2468 +            dev->rd_buff_pos = 0;
2469 +            memset(dev->rd_buff, 0, BLT_RDBUFF_MAX);
2470 +
2471 +          } else {
2472 +
2473 +            ast_log(LOG_ERROR, "Device %s: Expected '\\n' got %d. state = BLT_STATE_WANT_N2:\n", dev->name, c);
2474 +            return -1;
2475 +
2476 +          }
2477 +
2478 +          break;
2479 +
2480 +        default:
2481 +          ast_log(LOG_ERROR, "Device %s: Unknown device state %d\n", dev->name, dev->state);
2482 +          return -1;
2483 +
2484 +      }
2485 +
2486 +    }
2487 +
2488 +  }
2489 +
2490 +  return 0;
2491 +}
2492 +
2493 +/* Close the devices RFCOMM socket, and SCO if it exists. Must hold dev->lock */
2494 +
2495 +static void
2496 +rd_close(blt_dev_t * dev, int reconnect, int e)
2497 +{
2498 +  dev->ready = 0;
2499 +
2500 +  if (dev->rd)
2501 +    close(dev->rd);
2502 +
2503 +  dev->rd = -1;
2504 +
2505 +  dev->status = BLT_STATUS_DOWN;
2506 +
2507 +  sco_stop(dev);
2508 +
2509 +  if (dev->owner) {
2510 +    ast_setstate(dev->owner, AST_STATE_DOWN);
2511 +    ast_queue_control(dev->owner, AST_CONTROL_HANGUP);
2512 +  }
2513 +
2514 +  /* Schedule a reconnect */
2515 +  if (reconnect && dev->autoconnect) {
2516 +    dev->outgoing_id = ast_sched_add(sched, 5000, AST_SCHED_CB(try_connect), dev);
2517 +
2518 +    if (monitor_thread == pthread_self()) {
2519 +      // Because we're not the monitor thread, we needd to inturrupt poll().
2520 +      pthread_kill(monitor_thread, SIGURG);
2521 +    }
2522 +
2523 +    if (e)
2524 +      ast_log(LOG_NOTICE, "Device %s disconnected, scheduled reconnect in 5 seconds: %s (errno %d)\n", dev->name, strerror(e), e);
2525 +  } else if (e) {
2526 +    ast_log(LOG_NOTICE, "Device %s disconnected: %s (errno %d)\n", dev->name, strerror(e), e);
2527 +  }
2528 +
2529 +  return;
2530 +}
2531 +
2532 +/*
2533 + * Remember that we can only add to the scheduler from
2534 + * the do_monitor thread, as it calculates time to next one from
2535 + * this loop.
2536 + */
2537 +
2538 +static void *
2539 +do_monitor(void * data)
2540 +{
2541 +#define SRV_SOCK_CNT 3
2542 +
2543 +  int res = 0;
2544 +  blt_dev_t * dev;
2545 +  struct pollfd * pfds = malloc(sizeof(struct pollfd) * (ifcount + SRV_SOCK_CNT));
2546 +
2547 +  /* -- We start off by trying to connect all of our devices (non blocking) -- */
2548 +
2549 +  monitor_pid = getpid();
2550 +
2551 +  if (ast_mutex_lock(&iface_lock)) {
2552 +    ast_log(LOG_ERROR, "Failed to get iface_lock.\n");
2553 +    return NULL;
2554 +  }
2555 +
2556 +  dev = iface_head;
2557 +  while (dev) {
2558 +
2559 +    if (socketpair(PF_UNIX, SOCK_STREAM, 0, dev->sco_pipe) != 0) {
2560 +      ast_log(LOG_ERROR, "Failed to create socket pair: %s (errno %d)\n", strerror(errno), errno);
2561 +      ast_mutex_unlock(&iface_lock);
2562 +      return NULL;
2563 +    }
2564 +
2565 +    if (dev->autoconnect && dev->status == BLT_STATUS_DOWN)
2566 +      dev->outgoing_id = ast_sched_add(sched, 1500, AST_SCHED_CB(try_connect), dev);
2567 +    dev = dev->next;
2568 +  }
2569 +  ast_mutex_unlock(&iface_lock);
2570 +
2571 +  /* -- Now, Scan all sockets, and service scheduler -- */
2572 +
2573 +  pfds[0].fd = rfcomm_sock_ag;
2574 +  pfds[0].events = POLLIN;
2575 +
2576 +  pfds[1].fd = rfcomm_sock_hs;
2577 +  pfds[1].events = POLLIN;
2578 +
2579 +  pfds[2].fd = sco_socket;
2580 +  pfds[2].events = POLLIN;
2581 +
2582 +  while (1) {
2583 +    int cnt = SRV_SOCK_CNT;
2584 +    int i;
2585 +
2586 +    /* -- Build pfds -- */
2587 +
2588 +    if (ast_mutex_lock(&iface_lock)) {
2589 +      ast_log(LOG_ERROR, "Failed to get iface_lock.\n");
2590 +      return NULL;
2591 +    }
2592 +    dev = iface_head;
2593 +    while (dev) {
2594 +      ast_mutex_lock(&(dev->lock));
2595 +      if (dev->rd > 0 && ((dev->status != BLT_STATUS_DOWN) && (dev->status != BLT_STATUS_CONNECTING))) {
2596 +        pfds[cnt].fd = dev->rd;
2597 +        pfds[cnt].events = POLLIN;
2598 +        cnt++;
2599 +      }
2600 +      ast_mutex_unlock(&(dev->lock));
2601 +      dev = dev->next;
2602 +    }
2603 +    ast_mutex_unlock(&iface_lock);
2604 +
2605 +    /* -- End Build pfds -- */
2606 +
2607 +    res = ast_sched_wait(sched);
2608 +    res = poll(pfds, cnt, MAX(100, MIN(100, res)));
2609 +
2610 +    if (res == 0)
2611 +      ast_sched_runq(sched);
2612 +
2613 +    if (pfds[0].revents) {
2614 +      handle_incoming(rfcomm_sock_ag, BLT_ROLE_AG);
2615 +      res--;
2616 +    }
2617 +
2618 +    if (pfds[1].revents) {
2619 +      handle_incoming(rfcomm_sock_hs, BLT_ROLE_HS);
2620 +      res--;
2621 +    }
2622 +
2623 +    if (pfds[2].revents) {
2624 +      handle_incoming_sco(sco_socket);
2625 +      res--;
2626 +    }
2627 +
2628 +    if (res == 0)
2629 +      continue;
2630 +
2631 +    for (i = SRV_SOCK_CNT ; i < cnt ; i++) {
2632 +
2633 +      /* Optimise a little bit */
2634 +      if (res == 0)
2635 +        break;
2636 +      else if (pfds[i].revents == 0)
2637 +        continue;
2638 +
2639 +      /* -- Find the socket that has activity -- */
2640 +
2641 +      if (ast_mutex_lock(&iface_lock)) {
2642 +        ast_log(LOG_ERROR, "Failed to get iface_lock.\n");
2643 +        return NULL;
2644 +      }
2645 +
2646 +      dev = iface_head;
2647 +
2648 +      while (dev) {
2649 +        if (pfds[i].fd == dev->rd) {
2650 +          ast_mutex_lock(&(dev->lock));
2651 +          if (pfds[i].revents & POLLIN) {
2652 +            if (handle_rd_data(dev) == -1) {
2653 +              rd_close(dev, 0, 0);
2654 +            }
2655 +          } else {
2656 +            rd_close(dev, 1, sock_err(dev->rd));
2657 +          }
2658 +          ast_mutex_unlock(&(dev->lock));
2659 +          res--;
2660 +          break;
2661 +        }
2662 +        dev = dev->next;
2663 +      }
2664 +
2665 +      if (dev == NULL) {
2666 +        ast_log(LOG_ERROR, "Unhandled fd from poll()\n");
2667 +        close(pfds[i].fd);
2668 +      }
2669 +
2670 +      ast_mutex_unlock(&iface_lock);
2671 +
2672 +      /* -- End find socket with activity -- */
2673 +
2674 +    }
2675 +
2676 +  }
2677 +
2678 +  return NULL;
2679 +}
2680 +
2681 +static int
2682 +restart_monitor(void)
2683 +{
2684 +
2685 +  if (monitor_thread == AST_PTHREADT_STOP)
2686 +    return 0;
2687 +
2688 +  if (ast_mutex_lock(&monitor_lock)) {
2689 +    ast_log(LOG_WARNING, "Unable to lock monitor\n");
2690 +    return -1;
2691 +  }
2692 +
2693 +  if (monitor_thread == pthread_self()) {
2694 +    ast_mutex_unlock(&monitor_lock);
2695 +    ast_log(LOG_WARNING, "Cannot kill myself\n");
2696 +    return -1;
2697 +  }
2698 +
2699 +  if (monitor_thread != AST_PTHREADT_NULL) {
2700 +
2701 +    /* Just signal it to be sure it wakes up */
2702 +    pthread_cancel(monitor_thread);
2703 +    pthread_kill(monitor_thread, SIGURG);
2704 +    ast_log(LOG_DEBUG, "Waiting for monitor thread to join...\n");
2705 +    pthread_join(monitor_thread, NULL);
2706 +    ast_log(LOG_DEBUG, "joined\n");
2707 +
2708 +  } else {
2709 +
2710 +    /* Start a new monitor */
2711 +    if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
2712 +      ast_mutex_unlock(&monitor_lock);
2713 +      ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
2714 +      return -1;
2715 +    }
2716 +
2717 +  }
2718 +
2719 +  ast_mutex_unlock(&monitor_lock);
2720 +  return 0;
2721 +}
2722 +
2723 +static int
2724 +blt_parse_config(void)
2725 +{
2726 +  struct ast_config * cfg;
2727 +  struct ast_variable * v;
2728 +  char * cat;
2729 +
2730 +  cfg = ast_load(BLT_CONFIG_FILE);
2731 +
2732 +  if (!cfg) {
2733 +    ast_log(LOG_NOTICE, "Unable to load Bluetooth config: %s.  Bluetooth disabled\n", BLT_CONFIG_FILE);
2734 +    return -1;
2735 +  }
2736 +
2737 +  v = ast_variable_browse(cfg, "general");
2738 +
2739 +  while (v) {
2740 +    if (!strcasecmp(v->name, "rfchannel_ag")) {
2741 +      rfcomm_channel_ag = atoi(v->value);
2742 +    } else if (!strcasecmp(v->name, "rfchannel_hs")) {
2743 +      rfcomm_channel_hs = atoi(v->value);
2744 +    } else if (!strcasecmp(v->name, "interface")) {
2745 +      hcidev_id = atoi(v->value);
2746 +    } else {
2747 +      ast_log(LOG_WARNING, "Unknown config key '%s' in section [general]\n", v->name);
2748 +    }
2749 +    v = v->next;
2750 +  }
2751 +  cat = ast_category_browse(cfg, NULL);
2752 +
2753 +  while(cat) {
2754 +
2755 +    char * str;
2756 +
2757 +    if (strcasecmp(cat, "general")) {
2758 +      blt_dev_t * device = malloc(sizeof(blt_dev_t));
2759 +      memset(device, 0, sizeof(blt_dev_t));
2760 +      device->sco_running = -1;
2761 +      device->sco = -1;
2762 +      device->rd = -1;
2763 +      device->outgoing_id = -1;
2764 +      device->status = BLT_STATUS_DOWN;
2765 +      str2ba(cat, &(device->bdaddr));
2766 +      device->name = ast_variable_retrieve(cfg, cat, "name");
2767 +
2768 +      str = ast_variable_retrieve(cfg, cat, "type");
2769 +
2770 +      if (str == NULL) {
2771 +        ast_log(LOG_ERROR, "Device [%s] has no role.  Specify type=<HS/AG>\n", cat);
2772 +        return -1;
2773 +      } else if (strcasecmp(str, "HS") == 0)
2774 +        device->role = BLT_ROLE_HS;
2775 +      else if (strcasecmp(str, "AG") == 0) {
2776 +        device->role = BLT_ROLE_AG;
2777 +      } else {
2778 +        ast_log(LOG_ERROR, "Device [%s] has invalid role '%s'\n", cat, str);
2779 +        return -1;
2780 +      }
2781 +
2782 +      /* XXX:T: Find channel to use using SDP.
2783 +       *        However, this needs to be non blocking, and I can't see
2784 +       *        anything in sdp_lib.h that will allow non blocking calls.
2785 +       */
2786 +
2787 +      device->channel = 1;
2788 +
2789 +      if ((str = ast_variable_retrieve(cfg, cat, "channel")) != NULL)
2790 +        device->channel = atoi(str);
2791 +
2792 +      if ((str = ast_variable_retrieve(cfg, cat, "autoconnect")) != NULL)
2793 +        device->autoconnect = (strcasecmp(str, "yes") == 0 || strcmp(str, "1") == 0) ? 1 : 0;
2794 +
2795 +      device->next = iface_head;
2796 +      iface_head = device;
2797 +      ifcount++;
2798 +    }
2799 +
2800 +    cat = ast_category_browse(cfg, cat);
2801 +  }
2802 +  return 0;
2803 +}
2804 +
2805 +
2806 +static int
2807 +blt_show_peers(int fd, int argc, char *argv[])
2808 +{
2809 +  blt_dev_t * dev;
2810 +
2811 +  if (ast_mutex_lock(&iface_lock)) {
2812 +    ast_log(LOG_ERROR, "Failed to get Iface lock\n");
2813 +    ast_cli(fd, "Failed to get iface lock\n");
2814 +    return RESULT_FAILURE;
2815 +  }
2816 +
2817 +  dev = iface_head;
2818 +
2819 +  ast_cli(fd, "BDAddr            Name       Role Status      A/C SCOCon/Fd/Th Sig\n");
2820 +  ast_cli(fd, "----------------- ---------- ---- ----------- --- ------------ ---\n");
2821 +
2822 +  while (dev) {
2823 +    char b1[18];
2824 +    ba2str(&(dev->bdaddr), b1);
2825 +    ast_cli(fd, "%s %-10s %-4s %-11s %-3s %2d/%02d/%-6ld %s\n",
2826 +                b1, dev->name, (dev->role == BLT_ROLE_HS) ? "HS" : "AG", status2str(dev->status),
2827 +                (dev->autoconnect) ? "Yes" : "No",
2828 +                dev->sco_running,
2829 +                dev->sco,
2830 +                dev->sco_thread,
2831 +                (dev->role == BLT_ROLE_AG) ? (dev->service) ? "Yes" : "No" : "N/A"
2832 +            );
2833 +    dev = dev->next;
2834 +  }
2835 +
2836 +  ast_mutex_unlock(&iface_lock);
2837 +  return RESULT_SUCCESS;
2838 +}
2839 +
2840 +static int
2841 +blt_show_information(int fd, int argc, char *argv[])
2842 +{
2843 +  char b1[18];
2844 +  ba2str(&local_bdaddr, b1);
2845 +  ast_cli(fd, "-------------------------------------------\n");
2846 +  ast_cli(fd, "       Version : %s\n", BLT_SVN_REVISION);
2847 +  ast_cli(fd, "   Monitor PID : %d\n", monitor_pid);
2848 +  ast_cli(fd, "     RFCOMM AG : Channel %d, FD %d\n", rfcomm_channel_ag, rfcomm_sock_ag);
2849 +  ast_cli(fd, "     RFCOMM HS : Channel %d, FD %d\n", rfcomm_channel_hs, rfcomm_sock_hs);
2850 +  ast_cli(fd, "        Device : hci%d, MAC Address %s\n", hcidev_id, b1);
2851 +  ast_cli(fd, "-------------------------------------------\n");
2852 +  return RESULT_SUCCESS;
2853 +}
2854 +
2855 +static int
2856 +blt_ag_sendcmd(int fd, int argc, char *argv[])
2857 +{
2858 +  blt_dev_t * dev;
2859 +
2860 +  if (argc != 4)
2861 +    return RESULT_SHOWUSAGE;
2862 +
2863 +  ast_mutex_lock(&iface_lock);
2864 +  dev = iface_head;
2865 +  while (dev) {
2866 +    if (!strcasecmp(argv[2], dev->name))
2867 +      break;
2868 +    dev = dev->next;
2869 +  }
2870 +  ast_mutex_unlock(&iface_lock);
2871 +
2872 +  if (!dev) {
2873 +    ast_cli(fd, "Device '%s' does not exist\n", argv[2]);
2874 +    return RESULT_FAILURE;
2875 +  }
2876 +
2877 +  if (dev->role != BLT_ROLE_AG) {
2878 +    ast_cli(fd, "Device '%s' is not an AudioGateway\n", argv[2]);
2879 +    return RESULT_FAILURE;
2880 +  }
2881 +
2882 +  if (dev->status == BLT_STATUS_DOWN || dev->status == BLT_STATUS_NEGOTIATING) {
2883 +    ast_cli(fd, "Device '%s' is not connected\n", argv[2]);
2884 +    return RESULT_FAILURE;
2885 +  }
2886 +
2887 +  if (*(argv[3] + strlen(argv[3]) - 1) == '.')
2888 +    *(argv[3] + strlen(argv[3]) - 1) = '?';
2889 +
2890 +  ast_cli(fd, "Sending AT command to %s: %s\n", dev->name, argv[3]);
2891 +
2892 +  ast_mutex_lock(&(dev->lock));
2893 +  send_atcmd(dev, argv[3]);
2894 +  ast_mutex_unlock(&(dev->lock));
2895 +
2896 +  return RESULT_SUCCESS;
2897 +}
2898 +
2899 +static char *
2900 +complete_device(char * line, char * word, int pos, int state, int rpos, blt_role_t role)
2901 +{
2902 +  blt_dev_t * dev;
2903 +  int which = 0;
2904 +  char *ret;
2905 +
2906 +  if (pos != rpos)
2907 +    return NULL;
2908 +
2909 +  ast_mutex_lock(&iface_lock);
2910 +
2911 +  dev = iface_head;
2912 +
2913 +  while (dev) {
2914 +
2915 +    if ((dev->role == role) && (!strncasecmp(word, dev->name, strlen(word)))) {
2916 +      if (++which > state)
2917 +        break;
2918 +    }
2919 +
2920 +    dev = dev->next;
2921 +  }
2922 +
2923 +  if (dev)
2924 +    ret = strdup(dev->name);
2925 +  else
2926 +    ret = NULL;
2927 +
2928 +  ast_mutex_unlock(&iface_lock);
2929 +
2930 +  return ret;
2931 +}
2932 +
2933 +static char *
2934 +complete_device_2_ag(char * line, char * word, int pos, int state)
2935 +{
2936 +  return complete_device(line, word, pos, state, 2, BLT_ROLE_AG);
2937 +}
2938 +
2939 +static char show_peers_usage[] =
2940 +"Usage: bluetooth show peers\n"
2941 +"       List all bluetooth peers and their status\n";
2942 +
2943 +static struct ast_cli_entry
2944 +cli_show_peers =
2945 +    { { "bluetooth", "show", "peers", NULL }, blt_show_peers, "List Bluetooth Peers", show_peers_usage };
2946 +
2947 +
2948 +static char ag_sendcmd[] =
2949 +"Usage: bluetooth ag <device> sendcmd <cmd>\n"
2950 +"       Sends a AT cmd over the RFCOMM link, and print result (AG only)\n";
2951 +
2952 +static struct ast_cli_entry
2953 +cli_ag_sendcmd =
2954 +    { { "bluetooth", "sendcmd", NULL }, blt_ag_sendcmd, "Send AG an AT command", ag_sendcmd, complete_device_2_ag };
2955 +
2956 +static char show_information[] =
2957 +"Usage: bluetooth show information\n"
2958 +"       Lists information about the bluetooth subsystem\n";
2959 +
2960 +static struct ast_cli_entry
2961 +cli_show_information =
2962 +    { { "bluetooth", "show", "information", NULL }, blt_show_information, "List Bluetooth Info", show_information };
2963 +
2964 +void
2965 +remove_sdp_records(void)
2966 +{
2967 +
2968 +  sdp_session_t * sdp;
2969 +  sdp_list_t * attr;
2970 +  sdp_record_t * rec;
2971 +  int res = -1;
2972 +  uint32_t range = 0x0000ffff;
2973 +
2974 +  if (sdp_record_ag == -1 || sdp_record_hs == -1)
2975 +    return;
2976 +
2977 +  ast_log(LOG_DEBUG, "Removing SDP records\n");
2978 +
2979 +  sdp = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
2980 +
2981 +  if (!sdp)
2982 +    return;
2983 +
2984 +  attr = sdp_list_append(0, &range);
2985 +  rec = sdp_service_attr_req(sdp, sdp_record_ag, SDP_ATTR_REQ_RANGE, attr);
2986 +  sdp_list_free(attr, 0);
2987 +
2988 +  if (rec)
2989 +    if (sdp_record_unregister(sdp, rec) == 0)
2990 +      res = 0;
2991 +
2992 +  attr = sdp_list_append(0, &range);
2993 +  rec = sdp_service_attr_req(sdp, sdp_record_hs, SDP_ATTR_REQ_RANGE, attr);
2994 +  sdp_list_free(attr, 0);
2995 +
2996 +  if (rec)
2997 +    if (sdp_record_unregister(sdp, rec) == 0)
2998 +      res = 0;
2999 +
3000 +  sdp_close(sdp);
3001 +
3002 +  if (res == 0)
3003 +    ast_log(LOG_NOTICE, "Removed SDP records\n");
3004 +  else
3005 +    ast_log(LOG_ERROR, "Failed to remove SDP records\n");
3006 +
3007 +}
3008 +
3009 +static int
3010 +__unload_module(void)
3011 +{
3012 +
3013 +  ast_channel_unregister(BLT_CHAN_NAME);
3014 +
3015 +  if (monitor_thread != AST_PTHREADT_NULL) {
3016 +
3017 +    if (ast_mutex_lock(&monitor_lock)) {
3018 +
3019 +      if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
3020 +        pthread_cancel(monitor_thread);
3021 +        pthread_kill(monitor_thread, SIGURG);
3022 +        fprintf(stderr, "Waiting for monitor thread to join...\n");
3023 +        pthread_join(monitor_thread, NULL);
3024 +        fprintf(stderr, "joined\n");
3025 +      }
3026 +      monitor_thread = AST_PTHREADT_STOP;
3027 +      ast_mutex_unlock(&monitor_lock);
3028 +
3029 +    } else {
3030 +
3031 +      ast_log(LOG_WARNING, "Unable to lock the monitor\n");
3032 +      return -1;
3033 +
3034 +    }
3035 +
3036 +  }
3037 +
3038 +  ast_unregister_atexit(remove_sdp_records);
3039 +  remove_sdp_records();
3040 +  return 0;
3041 +}
3042 +
3043 +int
3044 +load_module()
3045 +{
3046 +  sdp_session_t * sess;
3047 +  int dd;
3048 +  uint16_t vs;
3049 +
3050 +  hcidev_id = BLT_DEFAULT_HCI_DEV;
3051 +
3052 +  if (blt_parse_config() != 0) {
3053 +    ast_log(LOG_ERROR, "Bluetooth configuration error.  Bluetooth Disabled\n");
3054 +    return unload_module();
3055 +  }
3056 +
3057 +  dd  = hci_open_dev(hcidev_id);
3058 +  if (dd == -1) {
3059 +    ast_log(LOG_ERROR, "Unable to open interface hci%d: %s.\n", hcidev_id, strerror(errno));
3060 +    return -1;
3061 +  }
3062 +
3063 +  hci_read_voice_setting(dd, &vs, 1000);
3064 +  vs = htobs(vs);
3065 +  close(dd);
3066 +
3067 +  if (vs != 0x0060) {
3068 +    ast_log(LOG_ERROR, "Bluetooth voice setting must be 0x0060, not 0x%04x\n", vs);
3069 +    unload_module();
3070 +    return 0;
3071 +  }
3072 +
3073 +  if ((sched = sched_context_create()) == NULL) {
3074 +    ast_log(LOG_WARNING, "Unable to create schedule context\n");
3075 +    return -1;
3076 +  }
3077 +
3078 +  memset(&local_bdaddr, 0, sizeof(local_bdaddr));
3079 +
3080 +  hci_devba(hcidev_id, &local_bdaddr);
3081 +
3082 +  /* --- Add SDP record --- */
3083 +
3084 +  sess = sdp_connect(&local_bdaddr, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
3085 +
3086 +  if ((rfcomm_sock_ag = rfcomm_listen(&local_bdaddr, rfcomm_channel_ag)) < 0) {
3087 +    return -1;
3088 +  }
3089 +
3090 +  if ((rfcomm_sock_hs = rfcomm_listen(&local_bdaddr, rfcomm_channel_hs)) < 0)
3091 +    return -1;
3092 +
3093 +  if ((sco_socket = sco_listen(&local_bdaddr)) < 0)
3094 +    return -1;
3095 +
3096 +  if (!sess) {
3097 +    ast_log(LOG_ERROR, "Failed to connect to SDP server: %s\n", strerror(errno));
3098 +    return -1;
3099 +  }
3100 +
3101 +  if (sdp_register(sess) != 0) {
3102 +    ast_log(LOG_ERROR, "Failed to register HeadsetAudioGateway in SDP\n");
3103 +    return -1;
3104 +  }
3105 +
3106 +  sdp_close(sess);
3107 +
3108 +  if (restart_monitor() != 0)
3109 +    return -1;
3110 +
3111 +  if (ast_channel_register(BLT_CHAN_NAME, "Bluetooth Driver", BLUETOOTH_FORMAT, blt_request)) {
3112 +    ast_log(LOG_ERROR, "Unable to register channel class BTL\n");
3113 +    __unload_module();
3114 +    return -1;
3115 +  }
3116 +
3117 +  ast_cli_register(&cli_show_information);
3118 +  ast_cli_register(&cli_show_peers);
3119 +  ast_cli_register(&cli_ag_sendcmd);
3120 +
3121 +  ast_register_atexit(remove_sdp_records);
3122 +
3123 +  ast_log(LOG_NOTICE, "Loaded Bluetooth support, %s\n", BLT_SVN_REVISION + 1);
3124 +
3125 +  return 0;
3126 +}
3127 +
3128 +int
3129 +unload_module(void)
3130 +{
3131 +  ast_cli_unregister(&cli_ag_sendcmd);
3132 +  ast_cli_unregister(&cli_show_peers);
3133 +  ast_cli_unregister(&cli_show_information);
3134 +  return __unload_module();
3135 +}
3136 +
3137 +int
3138 +usecount()
3139 +{
3140 +  int res;
3141 +  ast_mutex_lock(&usecnt_lock);
3142 +  res = usecnt;
3143 +  ast_mutex_unlock(&usecnt_lock);
3144 +  return res;
3145 +}
3146 +
3147 +char *description()
3148 +{
3149 +  return "Bluetooth Channel Driver";
3150 +}
3151 +
3152 +char *
3153 +key()
3154 +{
3155 +  return ASTERISK_GPL_KEY;
3156 +}
3157 +
3158 +
3159 diff -urN asterisk-1.4.0-beta3-o-o/configs/bluetooth.conf.sample asterisk-1.4.0-beta3/configs/bluetooth.conf.sample
3160 --- asterisk-1.4.0-beta3-o-o/configs/bluetooth.conf.sample      1969-12-31 17:00:00.000000000 -0700
3161 +++ asterisk-1.4.0-beta3/configs/bluetooth.conf.sample  2006-11-06 12:44:39.000000000 -0700
3162 @@ -0,0 +1,33 @@
3163 +[general]
3164 +; Channel we listen on as a HS (Headset)
3165 +rfchannel_hs = 2
3166 +; Channel we listen on as an AG (AudioGateway)
3167 +rfchannel_ag = 3
3168 +; hci interface to use (number - e.g '0')
3169 +interface = 0
3170 +
3171 +;; A HBH-500 Handsfree Kit
3172 +[00:0A:D9:A1:AA:D2]
3173 +; Any name to use, this is what we use to send calls to (BLT/<name>).
3174 +name        = HBH-500
3175 +; IS this a HS or AG?
3176 +type        = HS
3177 +;
3178 +;
3179 +; RFCOMM channel to connect to.  For a HandsSet:
3180 +;    sdptool search --bdaddr xx:xx:xx:xx:xx:xx 0x111E
3181 +; or,for an AudioGateway (Phone):
3182 +;    sdptool search --bdaddr xx:xx:xx:xx:xx:xx 0x111F
3183 +;
3184 +; Find the 'channel' value under RFCOMM.
3185 +;
3186 +channel     = 2
3187 +; Automatically conenct?
3188 +autoconnect = yes
3189 +
3190 +;; A Nokia 6310i
3191 +[00:60:57:1C:00:99]
3192 +name        = Neil
3193 +type        = AG
3194 +channel     = 13
3195 +autoconnect = yes
3196 diff -urN asterisk-1.4.0-beta3-o-o/configure.ac asterisk-1.4.0-beta3/configure.ac
3197 --- asterisk-1.4.0-beta3-o-o/configure.ac       2006-10-13 09:41:14.000000000 -0600
3198 +++ asterisk-1.4.0-beta3/configure.ac   2006-11-06 12:44:39.000000000 -0700
3199 @@ -152,6 +152,7 @@
3200  # by the --with option name, to make things easier for the users :-)
3201  
3202  AST_EXT_LIB_SETUP([ALSA], [Advanced Linux Sound Architecture], [asound])
3203 +AST_EXT_LIB_SETUP([BLUETOOTH], [Bluetooth], [bluetooth])
3204  AST_EXT_LIB_SETUP([CURL], [cURL], [curl])
3205  AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
3206  AST_EXT_LIB_SETUP([GNUTLS], [GNU TLS support (used for iksemel only)], [gnutls])
3207 @@ -314,6 +315,8 @@
3208  
3209  AST_EXT_LIB_CHECK([ALSA], [asound], [snd_spcm_init], [alsa/asoundlib.h], [-lm -ldl])
3210  
3211 +AST_EXT_LIB_CHECK([BLUETOOTH], [bluetooth], [bt_malloc], [bluetooth/bluetooth.h])
3212 +
3213  AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
3214  
3215  GSM_INTERNAL="yes"
3216 diff -urN asterisk-1.4.0-beta3-o-o/makeopts.in asterisk-1.4.0-beta3/makeopts.in
3217 --- asterisk-1.4.0-beta3-o-o/makeopts.in        2006-09-19 08:04:15.000000000 -0600
3218 +++ asterisk-1.4.0-beta3/makeopts.in    2006-11-06 12:44:39.000000000 -0700
3219 @@ -157,3 +157,6 @@
3220  
3221  SUPPSERV_INCLUDE=@SUPPSERV_INCLUDE@
3222  SUPPSERV_LIB=@SUPPSERV_LIB@
3223 +
3224 +BLUETOOTH_INCLUDE=@BLUETOOTH_INCLUDE@
3225 +BLUETOOTH_LIB=@BLUETOOTH_LIB@
This page took 0.290902 seconds and 3 git commands to generate.