update asterisk to 1.2.16, add chan-oss subpackage (closes: #1492)
[openwrt/svn-archive/archive.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