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