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