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